/// <summary> /// Replaces a transaction in a <see cref="Book"/> with an updated copy of the same transaction. /// </summary> /// <param name="oldTransaction">The transaction that should be replaced.</param> /// <param name="newTransaction">The transaction that will replace the old transaction.</param> public void ReplaceTransaction(Transaction oldTransaction, Transaction newTransaction) { lock (this.lockMutex) { if (oldTransaction == null) { throw new ArgumentNullException("oldTransaction"); } if (newTransaction == null) { throw new ArgumentNullException("newTransaction"); } if (oldTransaction.TransactionId != newTransaction.TransactionId) { throw new InvalidOperationException("The new transaction given may not replace the old transaction, because they do not share the same TransactionId."); } TransactionLock oldTransactionLock; if (!this.transactions.TryGetValue(oldTransaction, out oldTransactionLock)) { throw new InvalidOperationException("Could not remove the transaction from the book, because the transaction is not a member of the book."); } TransactionLock newTransactionLock = null; try { newTransactionLock = newTransaction.Lock(); if (!newTransaction.IsValid) { throw new InvalidOperationException("Could not replace the transaction in the book, because the new transaction is not valid."); } var splitsWithoutAccountsInBook = from s in newTransaction.Splits where !this.accounts.Contains(s.Account) select s; if (splitsWithoutAccountsInBook.Any()) { throw new InvalidOperationException( "Could not replace the transaction in the book, because the new transaction contains at least one split whose account has not been added."); } var splitsWithoutSecurityInBook = from s in newTransaction.Splits where s.Account.Security == null where !this.securities.Contains(s.Security) select s; if (splitsWithoutSecurityInBook.Any()) { throw new InvalidOperationException( "Could not add the transaction to the book, because the transaction contains at least one split whose security has not been added."); } oldTransactionLock.Dispose(); this.transactions.Remove(oldTransaction); this.transactions.Add(newTransaction, newTransactionLock); this.UpdateSaveTracks(st => st.RemoveTransaction(oldTransaction.TransactionId)); this.UpdateSaveTracks(st => st.AddTransaction(new TransactionData(newTransaction))); newTransactionLock = null; } finally { if (newTransactionLock != null) { newTransactionLock.Dispose(); } } this.RemoveTransactionFromBalances(oldTransaction); this.AddTransactionToBalances(newTransaction); } this.TransactionRemoved.SafeInvoke(this, new TransactionRemovedEventArgs(oldTransaction)); this.TransactionAdded.SafeInvoke(this, new TransactionAddedEventArgs(newTransaction)); }
public Transaction Copy() { lock (this.lockMutex) { var tNew = new Transaction(this.TransactionId, this.BaseSecurity); using (var tLock = tNew.Lock()) { tNew.SetDate(this.Date, tLock); foreach (var split in this.splits) { var sNew = tNew.AddSplit(tLock); sNew.SetAccount(split.Account, tLock); sNew.SetAmount(split.Amount, tLock); sNew.SetDateCleared(split.DateCleared, tLock); sNew.SetIsReconciled(split.IsReconciled, tLock); sNew.SetSecurity(split.Security, tLock); sNew.SetTransactionAmount(split.TransactionAmount, tLock); } } return tNew; } }
/// <summary> /// Adds a transaction to the <see cref="Book"/>. /// </summary> /// <param name="transaction">The transaction to add.</param> public void AddTransaction(Transaction transaction) { lock (this.lockMutex) { if (transaction == null) { throw new ArgumentNullException("transaction"); } if (this.transactions.ContainsKey(transaction)) { throw new InvalidOperationException("Could not add the transaction to the book, because the transaction already belongs to the book."); } if (this.transactionIds.Contains(transaction.TransactionId)) { throw new InvalidOperationException( "Could not add the transaction to the book, because another transaction has already been added with the same Transaction Id."); } TransactionLock transactionLock = null; try { transactionLock = transaction.Lock(); if (!transaction.IsValid) { throw new InvalidOperationException("Could not add the transaction to the book, because the transaction is not valid."); } var splitsWithoutAccountsInBook = from s in transaction.Splits where !this.accounts.Contains(s.Account) select s; if (splitsWithoutAccountsInBook.Any()) { throw new InvalidOperationException( "Could not add the transaction to the book, because the transaction contains at least one split whose account has not been added."); } var splitsWithoutSecurityInBook = from s in transaction.Splits where s.Account.Security == null where !this.securities.Contains(s.Security) select s; if (splitsWithoutSecurityInBook.Any()) { throw new InvalidOperationException( "Could not add the transaction to the book, because the transaction contains at least one split whose security has not been added."); } this.transactions.Add(transaction, transactionLock); this.transactionIds.Add(transaction.TransactionId); this.UpdateSaveTracks(st => st.AddTransaction(new TransactionData(transaction))); transactionLock = null; } finally { if (transactionLock != null) { transactionLock.Dispose(); } } this.AddTransactionToBalances(transaction); } this.TransactionAdded.SafeInvoke(this, new TransactionAddedEventArgs(transaction)); }
public void AddTransaction(TransactionData transaction) { lock (this) { var baseSecurity = this.destinationBook.Securities.Where(s => s.SecurityId == transaction.BaseSecurityId).Single(); var newTransaction = new Transaction( transaction.TransactionId, baseSecurity); using (var tlock = newTransaction.Lock()) { newTransaction.SetDate(transaction.Date, tlock); foreach (var split in transaction.Splits) { var newSplit = newTransaction.AddSplit(tlock); var account = this.destinationBook.Accounts.Where(a => a.AccountId == split.AccountId).Single(); var security = this.destinationBook.Securities.Where(s => s.SecurityId == split.SecurityId).Single(); newSplit.SetAccount(account, tlock); newSplit.SetSecurity(security, tlock); newSplit.SetAmount(split.Amount, tlock); newSplit.SetTransactionAmount(split.TransactionAmount, tlock); newSplit.SetDateCleared(split.DateCleared, tlock); newSplit.SetIsReconciled(split.IsReconciled, tlock); } } this.destinationBook.AddTransaction( newTransaction); } }