Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        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)}");
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
        /// <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);
                    }
                }
            }
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <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);
        }