public RecurringTransaction UpdateRecurringTransaction( int id, [FromBody] InputRecurringTransaction input, [FromQuery] bool updateInstances) { return(this.manager.UpdateRecurringTransaction( id, input, updateInstances)); }
public RecurringTransaction CreateRecurringTransaction(InputRecurringTransaction input) { return(this.manager.CreateRecurringTransaction(input)); }
/// <inheritdoc /> public RecurringTransaction CreateRecurringTransaction(InputRecurringTransaction input) { this.validator.Description(input.Description); var startPeriod = this.validator.DateString(input.StartDateString, "startDate"); var endPeriod = input.EndDateString.Select(d => this.validator.DateString(d, "endDate")); if (endPeriod.IsSome) { this.validator.Period(startPeriod, endPeriod); } this.validator.Interval(input.Interval); var type = this.GetTransactionType(input.CategoryId, input.ReceivingAccountId, input.Amount); this.validator.Splits(this.splitwiseContext, input.PaymentRequests, input.SplitwiseSplits, type, input.Amount); return(this.ConcurrentInvoke(() => { var processor = new TransactionProcessor(this.Context, this.splitwiseContext); var account = this.Context.Accounts.GetEntity(input.AccountId, false); this.validator.AccountType(account.Type); var category = input.CategoryId.Select(cId => this.Context.Categories.GetEntity(cId, false)); AccountEntity receivingAccount = null; if (input.ReceivingAccountId.IsSome) { receivingAccount = this.Context.Accounts.GetEntity(input.ReceivingAccountId.Value, false); if (receivingAccount.Id == account.Id) { throw new ValidationException("Sender account can not be the same as receiver account."); } this.validator.AccountType(receivingAccount.Type); } // Verify a Splitwise account exists when adding providing splits. if (input.SplitwiseSplits.Any()) { this.Context.Accounts.GetSplitwiseEntity(); } var entity = new RecurringTransactionEntity { Description = input.Description, Type = type, Amount = input.Amount, StartDate = startPeriod, EndDate = endPeriod.ToNullable(), AccountId = input.AccountId, Account = account, CategoryId = input.CategoryId.ToNullable(), Category = category.ToNullIfNone(), ReceivingAccountId = input.ReceivingAccountId.ToNullable(), ReceivingAccount = receivingAccount, Interval = input.Interval, IntervalUnit = input.IntervalUnit, NeedsConfirmation = input.NeedsConfirmation, NextOccurence = startPeriod, PaymentRequests = new List <PaymentRequestEntity>(), // TODO: Payment requests SplitDetails = input.SplitwiseSplits.Select(s => s.ToSplitDetailEntity()).ToList(), }; processor.Process(entity); this.Context.RecurringTransactions.Add(entity); this.Context.SaveChanges(); return entity.AsRecurringTransaction(); })); }
/// <inheritdoc /> public RecurringTransaction UpdateRecurringTransaction( int id, InputRecurringTransaction input, bool updateInstances) { this.validator.Description(input.Description); var startPeriod = this.validator.DateString(input.StartDateString, "startDate"); var endPeriod = input.EndDateString.Select(d => this.validator.DateString(d, "endDate")); if (endPeriod.IsSome) { this.validator.Period(startPeriod, endPeriod); } this.validator.Interval(input.Interval); var type = this.GetTransactionType(input.CategoryId, input.ReceivingAccountId, input.Amount); this.validator.Splits(this.splitwiseContext, input.PaymentRequests, input.SplitwiseSplits, type, input.Amount); return(this.ConcurrentInvoke(() => { var processor = new TransactionProcessor(this.Context, this.splitwiseContext); var entity = this.Context.RecurringTransactions.GetEntity(id); this.validator.AccountType(entity.Account.Type); if (entity.ReceivingAccount != null) { this.validator.AccountType(entity.ReceivingAccount.Type); } if (type != entity.Type) // TODO: Add test for this case { throw new ValidationException("Changing the type of transaction is not possible."); } if (!updateInstances && startPeriod != entity.StartDate) { throw new ValidationException($"Updating the start date without updating already created instances is not supported."); } var account = this.Context.Accounts.GetEntity(input.AccountId, false); this.validator.AccountType(account.Type); var category = input.CategoryId.Select(cId => this.Context.Categories.GetEntity(cId, false)); AccountEntity receivingAccount = null; if (input.ReceivingAccountId.IsSome) { receivingAccount = this.Context.Accounts.GetEntity(input.ReceivingAccountId.Value, false); if (receivingAccount.Id == account.Id) { throw new ValidationException("Sender account can not be the same as receiver account."); } this.validator.AccountType(receivingAccount.Type); } // Verify a Splitwise account exists when adding providing splits. if (input.SplitwiseSplits.Any()) { this.Context.Accounts.GetSplitwiseEntity(); } entity.AccountId = input.AccountId; entity.Account = account; entity.Description = input.Description; entity.StartDate = startPeriod; entity.EndDate = endPeriod.ToNullable(); entity.Amount = input.Amount; entity.CategoryId = input.CategoryId.ToNullable(); entity.Category = category.ToNullIfNone(); entity.ReceivingAccountId = input.ReceivingAccountId.ToNullable(); entity.ReceivingAccount = receivingAccount; entity.NeedsConfirmation = input.NeedsConfirmation; entity.Interval = input.Interval; entity.IntervalUnit = input.IntervalUnit; entity.SplitDetails = input.SplitwiseSplits.Select(s => s.ToSplitDetailEntity()).ToList(); var instances = this.Context.Transactions.GetTransactionsFromRecurring(entity.Id); var instancesToUpdate = updateInstances ? instances.ToList() // Copy the list // Always update all unprocessed transactions. : instances.Where(t => !t.Processed).ToList(); foreach (var instance in instancesToUpdate) { processor.RevertIfProcessed(instance); instances.Remove(instance); this.Context.Remove(instance); } entity.LastOccurence = instances .OrderByDescending(t => t.Date) .FirstOrNone() .Select(t => (LocalDate?)t.Date) .ValueOrElse(() => (LocalDate?)null); entity.SetNextOccurrence(); processor.Process(entity); this.Context.SaveChanges(); return entity.AsRecurringTransaction(); })); }
public void Test_CreateRecurringTransaction_SplitwiseSplits() { this.SplitwiseContextMock.GenerateUser(1, "Wouter", "van Acht"); this.SplitwiseContextMock.GenerateUser(2, "Jeroen"); var(account, _) = this.context.GenerateAccount(); var splitwiseAccount = this.context.GenerateAccount(AccountType.Splitwise); var category = this.context.GenerateCategory(); this.context.SaveChanges(); var input = new InputRecurringTransaction { AccountId = account.Id, Description = "Transaction", StartDateString = DateTime.Today.ToDateString(), EndDateString = null, Amount = -300, CategoryId = category.Id, ReceivingAccountId = Maybe <int> .None, NeedsConfirmation = false, Interval = 1, IntervalUnit = IntervalUnit.Months, PaymentRequests = new List <InputPaymentRequest>(), SplitwiseSplits = new List <InputSplitwiseSplit> { new InputSplitwiseSplit { Amount = 100, UserId = 1, }, new InputSplitwiseSplit { Amount = 150, UserId = 2, }, }, }; var recurringTransaction = this.RecurringTransactionManager.CreateRecurringTransaction(input); this.RefreshContext(); var transaction = this.context.Transactions.IncludeAll() .Single(t => t.RecurringTransactionId == recurringTransaction.Id); var expense = this.SplitwiseContextMock.Expenses.Single(e => e.Id == transaction.SplitwiseTransaction.Id); account = this.context.Accounts.GetEntity(account.Id); Wv8Assert.IsSome(transaction.SplitwiseTransaction.ToMaybe()); Assert.True(transaction.SplitwiseTransaction.Imported); Assert.Equal(250, transaction.SplitwiseTransaction.OwedByOthers); Assert.Equal(50, transaction.SplitwiseTransaction.PersonalAmount); Assert.Equal(300, transaction.SplitwiseTransaction.PaidAmount); Assert.Equal(-50, transaction.PersonalAmount); Assert.Equal(-50, recurringTransaction.PersonalAmount); Assert.Equal(transaction.SplitwiseTransactionId.Value, expense.Id); Assert.Equal(transaction.SplitwiseTransaction.PaidAmount, expense.PaidAmount); Assert.Equal(transaction.SplitwiseTransaction.PersonalAmount, expense.PersonalAmount); Assert.Equal(transaction.Date, expense.Date); Assert.False(expense.IsDeleted); Assert.Equal(2, recurringTransaction.SplitDetails.Count); Assert.Contains(recurringTransaction.SplitDetails, sd => sd.SplitwiseUserId == 1 && sd.Amount == 100); Assert.Contains(recurringTransaction.SplitDetails, sd => sd.SplitwiseUserId == 2 && sd.Amount == 150); Assert.Equal(2, transaction.SplitDetails.Count); Assert.Contains(transaction.SplitDetails, sd => sd.SplitwiseUserId == 1 && sd.Amount == 100); Assert.Contains(transaction.SplitDetails, sd => sd.SplitwiseUserId == 2 && sd.Amount == 150); Assert.Equal(-300, account.CurrentBalance); }