internal static void UpdateWallets(UserDetails personWhoPay, AddMessageToAddCashflowQueueDto dto, TraceWriter log) { var wallets = JsonConvert.DeserializeObject <List <Wallet> >(personWhoPay.Wallets); var wallet = wallets.First(x => x.Guid == dto.WalletGuid); log.Info($"Person who pay is {personWhoPay.Login} and the wallet: {wallet.Name} that contain {JsonConvert.SerializeObject(wallet.Money)} will be updated by substracting {dto.Amount.Amount}"); wallet.Money.Amount -= dto.Amount.Amount; personWhoPay.Wallets = JsonConvert.SerializeObject(wallets); }
/// <summary> /// tu wystarczy zdj¹æ sumê tego co maj¹ wszyscy /// </summary> /// <param name="dto"></param> /// <param name="log"></param> private static void UpdateHousehold(Household household, AddMessageToAddCashflowQueueDto dto, TraceWriter log, TableBatchOperation tableOperations) { var moneyList = JsonConvert.DeserializeObject <List <Money> >(household.MoneyAggregated); var money = moneyList.First(x => x.Currency == dto.Amount.Currency); log.Info($"Update Household - money was {JsonConvert.SerializeObject(money)}"); money.Amount -= dto.Amount.Amount; log.Info($"Update Household - money after update should be {JsonConvert.SerializeObject(money)}"); household.MoneyAggregated = JsonConvert.SerializeObject(moneyList); var updateOperation = TableOperation.Replace(household); tableOperations.Add(updateOperation); }
private static async Task UpdateUsersWallet(AddMessageToAddCashflowQueueDto dto, CloudTable table, TraceWriter log) { var retrievePersonWhoPay = TableOperation.Retrieve <UserDetails>(dto.HouseholdPk, $"user_{dto.Login}"); var operationResult = table.Execute(retrievePersonWhoPay); if (operationResult.Result != null && operationResult.Result is UserDetails) { var personWhoPay = operationResult.Result as UserDetails; log.Info($"DequeueAddCashflow - user who pay retreived. Wallets: {JsonConvert.SerializeObject(personWhoPay.Wallets)}"); DequeueAddCashflow.UpdateWallets(personWhoPay, dto, log); var updateOperation = TableOperation.Replace(personWhoPay); await table.ExecuteAsync(updateOperation); log.Info($"DequeueAddCashflow - updated wallets of person who pay. Wallets: {JsonConvert.SerializeObject(personWhoPay.Wallets)}"); } }
public static async Task <HttpResponseMessage> Run( [HttpTrigger( AuthorizationLevel.Function, "post", Route = "cashflows/add/{login}/") ] HttpRequestMessage req, string login, [Table("ExpensesApp")] ICollector <Cashflow> outTable, [Table("ExpensesApp", "user_{login}", "user_{login}")] UserLogInData user, [Queue("expenses-addcashflow")] CloudQueue queue, [Table("ExpensesApp")] CloudTable table, TraceWriter log) { AddCashFlowDto dto = null; try { log.Info($"json dto: " + req.Content); dto = await req.Content.ReadAsDeserializedJson <AddCashFlowDto>(); } catch { log.Info("AddCashFlow response: BadRequest - cannot read dto object"); return(req.CreateResponse( statusCode: HttpStatusCode.BadRequest, value: "Please pass a valid dto object in the request content")); } if (login == null) { log.Info("AddCashFlow response: BadRequest - login is null"); return(req.CreateResponse( statusCode: HttpStatusCode.BadRequest, value: "Please pass a login on the query string or in the request body")); } if (user == null) { log.Info($"AddCashFlow response: BadRequest - user does not exist"); return(req.CreateResponse( statusCode: HttpStatusCode.BadRequest, value: "User with given login does not exist" )); } var cashflowBase = new Cashflow() { DateTime = dto.DateTime, CategoryGuid = dto.CategoryGuid, Amount = JsonConvert.SerializeObject(dto.Amount), Details = JsonConvert.SerializeObject(dto.Details), WalletGuid = dto.WalletGuid }; var dateTimeInverted = RowKeyUtils.GetInvertedDateString(dto.DateTime); var guid = Guid.NewGuid(); if (user.BelongsToGroup) { var cashflowHousehold = new Cashflow(cashflowBase) { PartitionKey = user.HouseholdId, RowKey = $"householdCashflow_{dateTimeInverted}_{guid}" }; outTable.Add(cashflowHousehold); log.Info($"Added cashflowHousehold PK={cashflowHousehold.PartitionKey} RK={cashflowHousehold.RowKey}"); } var cashflowUser = new Cashflow(cashflowBase) { PartitionKey = user.HouseholdId, RowKey = $"userCashflow_{login}_{dateTimeInverted}_{guid}" }; outTable.Add(cashflowUser); log.Info($"Added cashflowHousehold PK={cashflowUser.PartitionKey} RK={cashflowUser.RowKey}"); //var cashflowHouseholdCategory = new Cashflow(cashflowBase) //{ // PartitionKey = user.HouseholdId, // RowKey = $"householdCategoryCashflow_{dto.CategoryGuid}_{dateTimeInverted}_{guid}" //}; //outTable.Add(cashflowHouseholdCategory); //log.Info($"Added cashflowHousehold PK={cashflowHouseholdCategory.PartitionKey} RK={cashflowHouseholdCategory.RowKey}"); //var cashflowUserCategory = new Cashflow(cashflowBase) //{ // PartitionKey = user.HouseholdId, // RowKey = $"userCategoryCashflow_{login}_{dto.CategoryGuid}_{dateTimeInverted}_{guid}" //}; //outTable.Add(cashflowUserCategory); //log.Info($"Added cashflowHousehold PK={cashflowUserCategory.PartitionKey} RK={cashflowUserCategory.RowKey}"); var addMessageDto = new AddMessageToAddCashflowQueueDto() { Amount = dto.Amount, HouseholdPk = user.HouseholdId, HouseholdRk = user.HouseholdId, WalletGuid = dto.WalletGuid, CategoryGuid = dto.CategoryGuid, UserBelongsToGroup = user.BelongsToGroup, Login = login }; if (user.BelongsToGroup) { var message = JsonConvert.SerializeObject(addMessageDto); await queue.AddMessageAsync(new CloudQueueMessage(message)); log.Info($"Enqueued message {message}"); } else { log.Info("User does not belong to a group. Only his wallet will be updated"); await UpdateUsersWallet(addMessageDto, table, log); } return(req.CreateResponse(HttpStatusCode.OK)); }
/// <summary> /// tu trzeba zastosowaæ przelicznik /// </summary> /// <param name="dto"></param> /// <param name="table"></param> /// <param name="log"></param> private static void UpdateUsersDetails(Household household, AddMessageToAddCashflowQueueDto dto, CloudTable table, TraceWriter log, TableBatchOperation tableOperations) { var categories = JsonConvert.DeserializeObject <List <Category> >(household.CategoriesAggregated); List <UserDetails> userDetailsList = GetUserDetailsList(household.PartitionKey, table, log); log.Info($"User detail list contains users: {userDetailsList.Select(x=>x.Login).Aggregate((x,y)=>x + ", " + y)}"); Dictionary <string, Dictionary <string, decimal> > result = WhoPaysToWho(dto, categories, userDetailsList, log); log.Info($"Who pays to who: {JsonConvert.SerializeObject(result)}"); var personWhoPay = userDetailsList.First(x => x.Wallets.Contains(dto.WalletGuid.ToString())); UpdateWallets(personWhoPay, dto, log); foreach (var userDetails in userDetailsList) { if (result.ContainsKey(userDetails.Login)) { var dictWithUpdates = result[userDetails.Login]; var chargesList = JsonConvert.DeserializeObject <Dictionary <string, List <Money> > >(userDetails.Charges); bool anyChange = false; log.Info($"Proceeding update for user {userDetails.Login}, with updates given by: {JsonConvert.SerializeObject(dictWithUpdates)}, using earlier charges value: {JsonConvert.SerializeObject(chargesList)}"); foreach (var keyvalue in dictWithUpdates) { if (chargesList == null) { log.Info("ChargesList was null, creating one"); chargesList = new Dictionary <string, List <Money> >(); } if (!chargesList.ContainsKey(keyvalue.Key)) { log.Info($"ChargesList didnt contain the key {keyvalue.Key} before. Creating one"); chargesList.Add(keyvalue.Key, new List <Money>()); } var listItem = chargesList[keyvalue.Key].FirstOrDefault(x => x.Currency == dto.Amount.Currency); if (listItem == null) { log.Info($"chargesList[{keyvalue.Key}] didnt contain currency {dto.Amount.Currency}. Adding the currency with amount {keyvalue.Value}"); chargesList[keyvalue.Key].Add(new Money() { Amount = keyvalue.Value, Currency = dto.Amount.Currency }); } else { log.Info($"chargesList[{keyvalue.Key}] did contain currency {dto.Amount.Currency}. Adding {keyvalue.Value} to {listItem.Amount}"); listItem.Amount += keyvalue.Value; } anyChange = true; } if (anyChange || userDetails == personWhoPay) { userDetails.Charges = JsonConvert.SerializeObject(chargesList); log.Info($"Updating {userDetails.Login} with charges list {userDetails.Charges}"); var operation = TableOperation.Replace(userDetails); tableOperations.Add(operation); } } } }
/// <summary> /// how much was spent in each category /// </summary> /// <param name="categories"></param> /// <param name="dto"></param> /// <returns></returns> private static Dictionary <Category, decimal> HowMuchWasSpentInEachCategory(List <Category> categories, AddMessageToAddCashflowQueueDto dto) { var categoryDict = new Dictionary <Category, decimal>(); foreach (var category in categories) { categoryDict.Add(category, 0); } var generalCategory = categories.First(x => x.Guid == dto.CategoryGuid); categoryDict[generalCategory] = dto.Amount.Amount; if (dto.Details != null) { foreach (var detail in dto.Details) { categoryDict[generalCategory] -= detail.Amount; var detailCategory = categories.First(x => x.Guid == detail.CategoryGuid); categoryDict[detailCategory] += detail.Amount; } } return(categoryDict); }
/// <summary> /// returns dictionary with compound key of two logins and the value is how much one login is charged to other login /// </summary> /// <param name="dto"></param> /// <param name="categories"></param> /// <param name="members"></param> /// <returns></returns> private static Dictionary <string, Dictionary <string, decimal> > WhoPaysToWho(AddMessageToAddCashflowQueueDto dto, List <Category> categories, List <UserDetails> userDetailsList, TraceWriter log) { var howMuchWasSpentInEachCategory = HowMuchWasSpentInEachCategory(categories, dto); var guidAsString = dto.WalletGuid.ToString(); var personWhoPaid = userDetailsList.First(x => x.Wallets.Contains(guidAsString)); Dictionary <string, decimal> loginAndHowMuchShouldPay = new Dictionary <string, decimal>(); foreach (var userDetails in userDetailsList) { var login = userDetails.Login; loginAndHowMuchShouldPay.Add( key: login, value: CalculateHowMuchUserShouldPay(howMuchWasSpentInEachCategory, login, log)); } // actually, the `personWhoPaid` paid 100% and the rest paid 0 // so the others are in debt to `personWhoPaid` var result = new Dictionary <string, Dictionary <string, decimal> >(); var loginAndHowMuchShouldPayWithoutPersonWhoPaid = loginAndHowMuchShouldPay.Where(x => x.Key != personWhoPaid.Login).ToDictionary(i => i.Key, i => i.Value); result.Add(personWhoPaid.Login, loginAndHowMuchShouldPayWithoutPersonWhoPaid); foreach (var keyvalue in loginAndHowMuchShouldPayWithoutPersonWhoPaid) { var key = keyvalue.Key; var debtDictionary = new Dictionary <string, decimal>() { { personWhoPaid.Login, loginAndHowMuchShouldPay[key] * -1 } }; result.Add(key, debtDictionary); } return(result); }