public async Task Save(IEntityRepository repository, DateTime dateTime) { var accountSettingsQueries = repository.GetQuery <AccountFlowSettings>(); var accountIds = Accounts.Select(x => x.Id).ToList(); var accountSettings = await accountSettingsQueries .Where(x => accountIds.Contains(x.AccountId)) .ToListAsync() .ConfigureAwait(false); Accounts.ForEach(x => { var settings = accountSettings.FirstOrDefault(s => s.AccountId == x.Id); if (settings == null) { settings = new AccountFlowSettings { AccountId = x.Id, CanFlow = x.CanFlow }; repository.Create(settings); } else { settings.CanFlow = x.CanFlow; repository.Update(settings); } }); var flowSettingsQueries = repository.GetQuery <ExpenseFlowSettings>(); var flowIds = ExpenseFlows.Select(x => x.Id).ToList(); var flowSettings = await flowSettingsQueries .Where(x => flowIds.Contains(x.ExpenseFlowId)) .ToListAsync() .ConfigureAwait(false); ExpenseFlows.ForEach(x => { var settings = flowSettings.FirstOrDefault(s => s.ExpenseFlowId == x.Id); if (settings == null) { settings = new ExpenseFlowSettings { ExpenseFlowId = x.Id, CanFlow = x.CanFlow, Rule = x.Rule, Amount = x.Amount }; repository.Create(settings); } else { settings.CanFlow = x.CanFlow; settings.Rule = x.Rule; settings.Amount = x.Amount; repository.Update(settings); } }); var distribution = new DataAccess.Model.Distribution.Distribution() { DateTime = dateTime, SumFlow = DistributionFlows.Sum(x => x.Amount) }; repository.Create(distribution); var accountQueries = repository.GetQuery <Account>(); var flowQueries = repository.GetQuery <ExpenseFlow>(); var accounts = await accountQueries .Where(x => accountIds.Contains(x.Id)) .ToListAsync() .ConfigureAwait(false); var expenseFlows = await flowQueries .Where(x => flowIds.Contains(x.Id)) .ToListAsync() .ConfigureAwait(false); DistributionFlows.ForEach(x => { var flow = new Flow { Distribution = distribution, SourceId = x.SourceId, RecipientId = x.RecipientId, Amount = x.Amount }; repository.Create(flow); var account = accounts.First(a => a.Id == x.SourceId); var expenseFlow = expenseFlows.First(f => f.Id == x.RecipientId); account.AvailBalance -= x.Amount; repository.Update(account); expenseFlow.Balance += x.Amount; repository.Update(expenseFlow); }); await repository.SaveChangesAsync().ConfigureAwait(false); }
public async Task Distribute(IEntityRepository repository, IFlowDistributor distributor) { var accountIds = Accounts.Select(x => x.Id).ToList(); var accountsQueries = repository.GetQuery <Account>(); var accounts = await accountsQueries .Where(x => accountIds.Contains(x.Id)) .Select(x => x.ToModel()) .ToListAsync() .ConfigureAwait(false); accounts.ForEach(x => { var account = Accounts.First(a => a.Id == x.Id); account.Balance = x.AvailBalance; (x as IFlowEndPoint).FlowRule = new DistributionFlowRule { CanFlow = account.CanFlow, Destination = FlowDestination.Source }; }); var flowIds = ExpenseFlows.Select(x => x.Id).ToList(); var flowQueries = repository.GetQuery <ExpenseFlow>(); var flows = await flowQueries .Where(x => flowIds.Contains(x.Id)) .Select(x => x.ToModel()) .ToListAsync() .ConfigureAwait(false); flows.ForEach(x => { var expenseFlow = ExpenseFlows.First(s => s.Id == x.Id); expenseFlow.Balance = x.Balance; x.FlowRule = new DistributionFlowRule { CanFlow = expenseFlow.CanFlow, Destination = FlowDestination.Recipient, Rule = expenseFlow.Rule, Amount = expenseFlow.Amount }; }); var endPoints = new List <IFlowEndPoint>(); endPoints.AddRange(accounts); endPoints.AddRange(flows); distributor.Distribute(endPoints); DistributionFlows = distributor.FlowRecords .Select(x => new DistributionFlowModel { SourceId = x.Source.Id, SourceName = x.Source.Name, RecipientId = x.Recipient.Id, RecipientName = x.Recipient.Name, Amount = x.Amount, AmountFormatted = x.Amount.ToMoney() }).ToList(); Accounts.ForEach(x => { if (!x.CanFlow) { return; } var withdrawTotal = distributor.FlowRecords.Where(f => f.Source.Id == x.Id).Sum(f => f.Amount); if (withdrawTotal > 0) { x.WithdrawTotal = $"\u2013{withdrawTotal.ToMoney()}"; } x.Result = (x.Balance - withdrawTotal).ToMoney(); }); ExpenseFlows.ForEach(x => { if (!x.CanFlow) { return; } var topupTotal = distributor.FlowRecords.Where(f => f.Recipient.Id == x.Id).Sum(f => f.Amount); if (topupTotal > 0) { x.TopupTotal = $"+{topupTotal.ToMoney()}"; } x.Result = (x.Balance + topupTotal).ToMoney(); }); }