public async Task <int> AddTransactionAsync(AddUpdateTransactionDtoBase dto) { await ValidateTransactionDtoAsync(dto); TransactionBase newTransaction; switch (dto) { case AddUpdateCategoryTransactionDto categoryDto: newTransaction = categoryDto.ToEntity(); break; case AddUpdateWalletTransactionDto walletDto: newTransaction = walletDto.ToEntity(); break; default: throw new ArgumentException("Unknown/unhandled addTransactionDto type."); } newTransaction.TimeStamp = dto.ManualTimestamp ?? DateTime.Now; _dbContext.Transactions.Add(newTransaction); await _dbContext.SaveChangesAsync(); return(newTransaction.Id); }
public async Task <TransactionDomain> UpdateTransactionAsync(int transactionId, AddUpdateTransactionDtoBase dto) { await ValidateTransactionDtoAsync(dto); TransactionBase transaction = _dbContext.Transactions.Find(transactionId); if (dto is AddUpdateCategoryTransactionDto && transaction is WalletTransaction || dto is AddUpdateWalletTransactionDto && transaction is CategoryTransaction) { throw new AttemptedChangeOfTransactionTypeException(); } transaction.Amount = dto.Amount; transaction.WalletId = dto.WalletId; if (dto.ManualTimestamp != null) { transaction.TimeStamp = dto.ManualTimestamp.Value; } switch (transaction) { case CategoryTransaction ct: var cDto = dto as AddUpdateCategoryTransactionDto; ct.CategoryId = cDto.CaterodyId; break; case WalletTransaction wt: var wDto = dto as AddUpdateWalletTransactionDto; wt.OtherWalletId = wDto.OtherWalletId; break; default: throw new NotImplementedException( "Updating for this transaction type is not implemented (or something went wrong)"); } await _dbContext.SaveChangesAsync(); return(await _dbContext.Transactions .Where(t => t.Id == transactionId) .Select(t => new TransactionDomain { Id = t.Id, Amount = t.Amount, TargetLabel = (t is CategoryTransaction) ? (t as CategoryTransaction).Category.Name : (t as WalletTransaction).OtherWallet.Name, Timestamp = t.TimeStamp }) .SingleAsync()); }
private async Task ValidateTransactionDtoAsync(AddUpdateTransactionDtoBase dto) { if (dto.Amount == 0) { throw new ValidationException(new() { { nameof(dto.Amount), "Transaction amount can't be 0." } }); } if (dto is AddUpdateCategoryTransactionDto) { var cDto = dto as AddUpdateCategoryTransactionDto; var categoryBelongsToWalletOwner = await _dbContext.Categories .Where(c => c.Id == cDto.CaterodyId) .Join( _dbContext.Wallets.Where(w => w.Id == cDto.WalletId), c => c.UserId, w => w.UserId, (c, w) => 1) .AnyAsync(); if (categoryBelongsToWalletOwner == false) { throw new ValidationException(new() { { nameof(cDto.CaterodyId), "Category should belong to the wallet's owner." } }); } var targetCategory = await _dbContext.Categories .AsNoTracking() .FirstAsync(c => c.Id == cDto.CaterodyId); if (targetCategory.IsIncome && cDto.Amount < 0) { throw new ValidationException(new() { { nameof(cDto.Amount), "The transaction value should be positive for an income category." } }); } if (targetCategory.IsIncome == false && cDto.Amount > 0) { throw new ValidationException(new() { { nameof(cDto.Amount), "The transaction value should be negative for an expense category." } }); } } if (dto is AddUpdateWalletTransactionDto) { var wDto = dto as AddUpdateWalletTransactionDto; if (wDto.WalletId == wDto.OtherWalletId) { throw new ValidationException(new() { { nameof(wDto.OtherWalletId), "Source wallet can not be the same as the wallet transaction belongs to." } }); } bool userAuthorizedForOtherWallet = await _dbContext.Wallets .Where(w => w.Id == wDto.OtherWalletId && (w.UserId == dto.UserId || w.WalletAllowedUsers.Any(wu => wu.UserId == dto.UserId))) .AnyAsync(); if (userAuthorizedForOtherWallet == false) { throw new HttpStatusException(404, "other wallet not found."); } } }