Exemple #1
0
        static void Main(string[] args)
        {
            var user = new User {
                Id = 1, Name = "Name"
            };

            var phone = new Phone {
                Id = 1, PhoneCode = "123", Value = "123124"
            };

            var userRepository = new ObjectRepository <User>();

            userRepository.Add(user);

            var contactRepository = new ObjectRepository <Phone>();

            contactRepository.Add(phone);

            foreach (var value in contactRepository.GetAll())
            {
                var contact = (Contact)value;
                Console.WriteLine(contact.Value);
            }

            contactRepository.Add(user);

            foreach (var value in contactRepository.GetAll())
            {
                var contact = (Contact)value;
                Console.WriteLine(contact.Value);
            }
        }
Exemple #2
0
        public async Task <IActionResult> SmsIfThisThenThat()
        {
            var success = GetJsonResponseForSms(true);

            try
            {
                string data;
                using (var ms = new MemoryStream())
                {
                    await HttpContext.Request.Body.CopyToAsync(ms);

                    ms.Position = 0;
                    data        = await new HttpRequestStreamReader(ms, Encoding.UTF8).ReadToEndAsync();
                }

                _logger.LogInformation(data);
                var items = JObject.Parse(data);
                var from  = items["from"].Value <string>();

                if (string.IsNullOrWhiteSpace(from))
                {
                    from = items["fromNumber"].Value <string>();
                }

                var message  = items["message"].Value <string>();
                var when     = items["sent_timestamp"].Value <string>();
                var whenDate = DateTime.Parse(when.Replace("at", ""));

                var smsModel = new SmsModel(@from, message, whenDate);

                lock (typeof(SmsModel))
                {
                    var existingMessage = _objectRepository.Set <SmsModel>()
                                          .FirstOrDefault(s => Math.Abs((s.When - smsModel.When).TotalMinutes) < 2 && smsModel.Message.StartsWith(s.Message));
                    if (existingMessage == null)
                    {
                        _objectRepository.Add(smsModel);
                    }
                    else
                    {
                        existingMessage.Message = smsModel.Message;
                    }
                }

                _logger.LogInformation($"parsed form: {from} {message} {when}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to parse sms");

                success = GetJsonResponseForSms(false, "failed to get result " + ex);
            }

            return(Content(success, "application/json"));
        }
Exemple #3
0
        public void EditDebt(Debt request)
        {
            DebtModel model;

            if (request.Id.ToGuid() == Guid.Empty)
            {
                model = new DebtModel();
                ObjectRepository.Add(model);
            }
            else
            {
                model = ObjectRepository.Set <DebtModel>().First(v => v.Id == request.Id.ToGuid());
            }

            model.When        = request.Issued.ToDateTime();
            model.Amount      = request.Amount;
            model.Ccy         = request.Ccy;
            model.Percentage  = request.Percentage;
            model.DaysCount   = request.DaysCount;
            model.Description = request.Description;
            try
            {
                if (!string.IsNullOrWhiteSpace(request.RegexForTransfer))
                {
                    // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                    new Regex(request.RegexForTransfer, RegexOptions.None, TimeSpan.FromSeconds(0.1)).Match("test");
                }
            }
            catch
            {
                request.RegexForTransfer = "";
            }

            model.RegexForTransfer = request.RegexForTransfer;
        }
Exemple #4
0
        public IActionResult CreateRule(RuleType ruleType, string regexSender, string regexText)
        {
            try
            {
                // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                if (!string.IsNullOrEmpty(regexSender))
                {
                    Regex.Match("test", regexSender);
                }
                // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                if (!string.IsNullOrEmpty(regexText))
                {
                    Regex.Match("test", regexText);
                }
            }
            catch
            {
                return(RedirectToAction(nameof(SmsRules)));
            }

            var rule = new RuleModel(ruleType, regexSender, regexText);

            _objectRepository.Add(rule);
            return(RedirectToAction(nameof(SmsRules)));
        }
        public void EditCategory(SpentCategory request)
        {
            if (request.Id.ToGuid() == Guid.Empty)
            {
                try
                {
                    if (!string.IsNullOrWhiteSpace(request.Pattern))
                    {
                        // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                        new Regex(request.Pattern, RegexOptions.None, TimeSpan.FromSeconds(0.1)).Match("test");
                    }
                }
                catch
                {
                    request.Pattern = "";
                }

                var spentCategoryModel = new SpentCategoryModel(request.Pattern, request.Category, request.Kind);
                ObjectRepository.Add(spentCategoryModel);
            }
            else
            {
                var id          = request.Id.ToGuid();
                var categoryObj = ObjectRepository.Set <SpentCategoryModel>().First(v => v.Id == id);

                categoryObj.Pattern  = request.Pattern;
                categoryObj.Category = request.Category;
                categoryObj.Kind     = request.Kind;
            }
        }
Exemple #6
0
        public OkResult CreateCategory(string pattern, string category, PaymentKind kind)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(pattern))
                {
                    // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                    new Regex(pattern, RegexOptions.None, TimeSpan.FromSeconds(0.1)).Match("test");
                }
            }
            catch
            {
                pattern = "";
            }

            _objectRepository.Add(new SpentCategoryModel(pattern, category, kind));
            return(Ok());
        }
Exemple #7
0
        static void Main(string[] args)
        {
            ObjectRepository.Add("object1", new Object());
            ObjectRepository.Add("dir/obj", new Object());
            IObject proxy = new ProxyObj("object1");

            Console.WriteLine(proxy.Method(15));
            proxy = new ProxyObj("dir/obj");
            Console.WriteLine(proxy.Method(15));
        }
        public void AddScraper(string name, string login, string password)
        {
            var scm = new ScraperConfigurationModel(name)
            {
                Login    = login,
                Password = password
            };

            ObjectRepository.Add(scm);
        }
        public void Process()
        {
            try
            {
                Monitor.Enter(this);
                var smsList = _objectRepository.Set <SmsModel>().Where(v => v.AppliedRule == null).ToList();
                var rules   = _objectRepository.Set <RuleModel>();

                var regexOptions = RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase;
                foreach (RuleModel rule in rules)
                {
                    var sReg = string.IsNullOrEmpty(rule.RegexSender)
                        ? null
                        : new Regex(rule.RegexSender, regexOptions);
                    var sText = string.IsNullOrEmpty(rule.RegexText) ? null : new Regex(rule.RegexText, regexOptions);

                    foreach (SmsModel sms in smsList)
                    {
                        if (sReg?.IsMatch(sms.From) != false && sText?.IsMatch(sms.Message) != false)
                        {
                            try
                            {
                                if (rule.RuleType == RuleType.Money)
                                {
                                    _objectRepository.Add(new PaymentModel(sms, rule));
                                }

                                sms.AppliedRule = rule;
                            }
                            catch
                            {
                            }
                        }
                    }
                }

                var oldSms = _objectRepository.Set <SmsModel>()
                             .Where(v => v.AppliedRule != null && v.When.AddDays(7) < DateTime.UtcNow).ToList();

                foreach (var item in oldSms)
                {
                    foreach (var p in item.Payments)
                    {
                        p.Sms = null;
                    }
                }

                _objectRepository.RemoveRange(oldSms);
            }
            finally
            {
                Monitor.Exit(this);
            }
        }
Exemple #10
0
        public void SplitPayment(SplitPaymentRequest request)
        {
            var amount  = request.Amount;
            var id      = request.Id.ToGuid();
            var payment = ObjectRepository.Set <PaymentModel>().First(v => v.Id == id);

            var newKind = amount < 0 ? PaymentKind.Expense : PaymentKind.Income;

            if (payment.Kind != PaymentKind.Expense && payment.Kind != PaymentKind.Income)
            {
                newKind = payment.Kind;

                payment.Amount -= amount;
            }
            else
            {
                amount = Math.Abs(amount);

                if (payment.Kind == newKind.GetOpposite())
                {
                    amount = -amount;
                }

                payment.Amount -= amount;

                amount = Math.Abs(amount);
            }

            if (Math.Abs(amount) > 0.01)
            {
                if (payment.Amount < 0 && payment.Kind != payment.Kind.GetOpposite())
                {
                    payment.Kind   = payment.Kind.GetOpposite();
                    payment.Amount = Math.Abs(payment.Amount);
                }

                var newPayment = new PaymentModel(payment.When, payment.What, amount, newKind, payment.Ccy, null, payment.Column);
                ObjectRepository.Add(newPayment);
                newPayment.UserEdited = true;
            }
            SendUpdate(new PaymentsStream
            {
                Snapshot = new PaymentsList
                {
                    ShowCategorized = ShowCategorized,
                    Payments        = { _collection.Select(v => v.ToMonthSummary()) }
                }
            });
        }
        public IActionResult CreateCategory(string pattern, string category, PaymentKind kind)
        {
            try
            {
                // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
                Regex.Match("test", pattern);
            }
            catch
            {
                return(RedirectToAction(nameof(SpentCategories)));
            }

            _objectRepository.Add(new SpentCategoryModel(pattern, category, kind));
            return(RedirectToAction(nameof(SpentCategories)));
        }
        public OkResult CreateRule(RuleType ruleType, string regexSender, string regexText)
        {
            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
            if (!string.IsNullOrEmpty(regexSender))
            {
                new Regex(regexSender, RegexOptions.None, TimeSpan.FromSeconds(0.1)).Match("test");
            }
            // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
            if (!string.IsNullOrEmpty(regexText))
            {
                new Regex(regexText, RegexOptions.None, TimeSpan.FromSeconds(0.1)).Match("test");
            }

            var rule = new RuleModel(ruleType, regexSender, regexText);

            _objectRepository.Add(rule);
            return(Ok());
        }
        public OkResult MetadataEdit(Guid id, string userFriendlyName, string function, bool autogenerateStatements)
        {
            MoneyColumnMetadataModel existingModel;

            if (id == Guid.Empty)
            {
                existingModel = new MoneyColumnMetadataModel(MoneyColumnMetadataModel.ComputedProdiver, null);
                _objectRepository.Add(existingModel);
            }
            else
            {
                existingModel = _objectRepository.Set <MoneyColumnMetadataModel>().First(v => v.Id == id);
            }

            existingModel.Function               = function ?? "";
            existingModel.UserFriendlyName       = userFriendlyName;
            existingModel.AutogenerateStatements = autogenerateStatements;

            return(Ok());
        }
Exemple #14
0
        public IActionResult MetadataEdit(Guid id, string userFriendlyName, bool isVisible, string function, string charts)
        {
            MoneyColumnMetadataModel existingModel;

            if (id == Guid.Empty)
            {
                existingModel = new MoneyColumnMetadataModel(MoneyColumnMetadataModel.ComputedProdiver, null);
                _objectRepository.Add(existingModel);
            }
            else
            {
                existingModel = _objectRepository.Set <MoneyColumnMetadataModel>().First(v => v.Id == id);
            }

            existingModel.Function         = function;
            existingModel.UserFriendlyName = userFriendlyName;
            existingModel.IsVisible        = isVisible;

            return(RedirectToAction(nameof(Index)));
        }
        public void ScrapeImpl(String name, Action <GenericScraper, ScraperConfigurationModel> action, [CallerMemberName] string caller = null)
        {
            if (!Startup.IsProduction)
            {
                return;
            }

            var scrapeConfig = _objectRepository.Set <ScraperConfigurationModel>().FirstOrDefault(v => v.ScraperName == name);
            var scraper      = _scrapers.FirstOrDefault(v => v.ProviderName == name);

            if (scrapeConfig == null || scraper == null)
            {
                _logger.LogInformation($"Not enabled scraper {name}");
                return;
            }

            lock (_chrome)
            {
                _chrome.Reset();

                try
                {
                    _logger.LogInformation($"Scraping {name} {caller}");
                    action(scraper, scrapeConfig);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"Failed to get state for {scraper.ProviderName}...");
                    throw;
                }
                finally
                {
                    _chrome.Reset();
                }
            }

            // default strategy - generated money statements from diff between states.
            foreach (var column in _objectRepository.Set <MoneyColumnMetadataModel>().Where(v => v.AutogenerateStatements))
            {
                var payments = _objectRepository.Set <PaymentModel>()
                               .Where(v => v.Column == column)
                               .ToList();

                var models = _objectRepository.Set <MoneyStateModel>()
                             .Where(v => v.Column == column)
                             .OrderBy(v => v.When)
                             .ToList();

                if (models.Any())
                {
                    var emptyModel = new MoneyStateModel
                    {
                        Amount = 0,
                        Ccy    = models.First().Ccy,
                        Column = models.First().Column,
                        When   = models.First().When.AddDays(-1)
                    };
                    models.Insert(0, emptyModel);

                    models.Aggregate((a, b) =>
                    {
                        var delta = b.Amount - a.Amount;

                        var matchingPayments = payments
                                               .Where(v => v.Column == column && v.When >= a.When && v.When <= b.When).ToList();

                        delta -= matchingPayments.Sum(v => v.Amount);

                        delta = Math.Round(delta * 100, MidpointRounding.AwayFromZero) / 100;

                        if (Math.Abs(delta) >= 0.01)
                        {
                            var when = a.When + (b.When - a.When) / 2;
                            var kind = delta > 0 ? PaymentKind.Income : PaymentKind.Expense;

                            var paymentModel = payments.FirstOrDefault(v =>
                                                                       v.Column == column && v.When >= a.When && v.When <= b.When && v.Autogenerated);

                            if (paymentModel == null)
                            {
                                paymentModel = new PaymentModel(when,
                                                                "Коррекция баланса " + column.Provider + " " + column.AccountName,
                                                                delta, kind, a.Ccy, "N/A-" + DateTime.Now.Ticks, column);

                                _objectRepository.Add(paymentModel);
                            }
                            else
                            {
                                paymentModel.Amount += delta;
                            }

                            paymentModel.Autogenerated = true;
                        }

                        return(b);
                    });
                }
            }
        }
        public void Scrape()
        {
            lock (_chrome)
            {
                _chrome.Reset();
                var logger       = _logger;
                var currentState = _objectRepository.Set <MoneyStateModel>();

                var scrapeConfigs = _objectRepository.Set <ScraperConfigurationModel>().ToList();

                foreach (var scraperConfig in scrapeConfigs)
                {
                    var scraper = _scrapers.FirstOrDefault(v => v.ProviderName == scraperConfig.ScraperName);

                    if (scraper == null)
                    {
                        logger.LogError($"Failed to find scraper {scraperConfig.ScraperName}");
                        continue;
                    }

                    logger.LogInformation($"Scraping {scraper.ProviderName}");

                    if (scraper is IStatementScraper ss)
                    {
                        try
                        {
                            var minDates = new[]
                            {
                                _objectRepository.Set <PaymentModel>()
                                .Where(v => v.Provider == scraper.ProviderName)
                                .OrderByDescending(v => v.When)
                                .FirstOrDefault()?.When,
                                _objectRepository.Set <MoneyStateModel>().OrderBy(v => v.When)
                                .FirstOrDefault()?.When,
                                _objectRepository.Set <PaymentModel>().OrderBy(v => v.When)
                                .FirstOrDefault()?.When
                            };

                            var lastPayment = minDates.Where(v => v != null).OrderBy(v => v).FirstOrDefault() ??
                                              DateTime.MinValue;

                            if (lastPayment.AddHours(24) > DateTime.Now)
                            {
                                continue; // Let's not scrape statements too often - it's hard
                            }
                            logger.LogInformation($"Scraping statement for {scraper.ProviderName} since {lastPayment}...");

                            var statements = ss.ScrapeStatement(scraperConfig, _chrome, lastPayment).ToList();

                            logger.LogInformation($"Got statement of {statements.Count} items...");

                            foreach (var s in statements)
                            {
                                var existingItem = _objectRepository.Set <PaymentModel>().FirstOrDefault(v =>
                                                                                                         v.When.Date == s.When.Date &&
                                                                                                         Math.Abs(v.Amount - s.Amount) < 0.01 &&
                                                                                                         v.Ccy == s.Ccy &&
                                                                                                         v.StatementReference == null || v.StatementReference == s.StatementReference);

                                if (existingItem == null)
                                {
                                    _objectRepository.Add(s);
                                }
                                else
                                {
                                    if (existingItem.Provider == null)
                                    {
                                        existingItem.Provider = s.Provider;
                                    }

                                    if (existingItem.Account == null)
                                    {
                                        existingItem.Account = s.Account;
                                    }

                                    if (existingItem.StatementReference == null)
                                    {
                                        existingItem.StatementReference = s.StatementReference;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.LogError(ex, $"Failed to get statement for {scraper.ProviderName}...");
                        }
                    }

                    _chrome.Reset();

                    var accountCount = currentState.Where(s => s.Provider == scraper.ProviderName && s.When.Date == DateTime.UtcNow.Date.AddDays(-1))
                                       .Select(s => s.AccountName).Distinct()
                                       .ToList();

                    var todayState = currentState.Where(s => s.Provider == scraper.ProviderName && s.When.Date == DateTime.UtcNow.Date)
                                     .Select(s => s.AccountName).Distinct()
                                     .ToList();

                    var toScrape = accountCount.Count == 0 || accountCount.Except(todayState).Any();

                    if (toScrape)
                    {
                        try
                        {
                            logger.LogInformation("No cached items, scraping...");

                            var items = scraper.Scrape(scraperConfig, _chrome.Driver);

                            logger.LogInformation($"Found {items.Count()} items, indexing...");

                            foreach (var item in items)
                            {
                                logger.LogInformation($" - {item.Provider} / {item.AccountName}: {item.Amount} ({item.Ccy})");
                                if (!string.IsNullOrWhiteSpace(item.Provider))
                                {
                                    if (item.Amount <= 0.001)
                                    {
                                        if (!_objectRepository.Set <MoneyStateModel>().Any(s =>
                                                                                           s.Provider == item.Provider &&
                                                                                           s.AccountName == item.AccountName &&
                                                                                           s.Amount > 0
                                                                                           ))
                                        {
                                            continue;
                                        }
                                    }

                                    if (todayState.Contains(item.AccountName))
                                    {
                                        continue;
                                    }

                                    _objectRepository.Add(item);
                                }
                            }

                            logger.LogInformation("Indexed...");
                        }
                        catch (Exception ex)
                        {
                            logger.LogError(ex, "There were an issue scraping");
                        }
                    }
                    else
                    {
                        logger.LogInformation("For today there are already scraped items, continuing...");
                    }
                }
            }

            foreach (var item in _objectRepository.Set <MoneyStateModel>().GroupBy(v => v.Provider, v => v.AccountName))
            {
                foreach (var sub in item.Distinct())
                {
                    var existing = _objectRepository.Set <MoneyColumnMetadataModel>()
                                   .FirstOrDefault(v => v.Provider == item.Key && v.AccountName == sub);

                    if (existing == null)
                    {
                        existing = new MoneyColumnMetadataModel(item.Key, sub)
                        {
                            UserFriendlyName = sub,
                            IsVisible        = true
                        };
                        _objectRepository.Add(existing);
                    }
                }
            }
        }
        public TableViewModel(ObjectRepository repository)
        {
            var headersDictionary = repository.Set <MoneyColumnMetadataModel>().SortColumns()
                                    .ToDictionary(v => new MoneyColumnMetadataJsModel(v), v => v);

            Headers = headersDictionary.Keys.ToList();

            var headersCached = new Dictionary <string, MoneyColumnMetadataJsModel>();

            foreach (var h in Headers)
            {
                if (!string.IsNullOrWhiteSpace(h.UserFriendlyName))
                {
                    headersCached[h.UserFriendlyName] = h;
                }

                headersCached[h.Provider + "/" + h.AccountName] = h;
            }

            var paymentsToExempt = repository.Set <PaymentModel>().Where(v => v.Kind == PaymentKind.Transfer).ToList().GroupBy(v => v.Column)
                                   .ToDictionary(v => new MoneyColumnMetadataJsModel(v.Key), v =>
            {
                var d = new Dictionary <DateTime, double>();
                foreach (var item in v)
                {
                    d[item.When.Date] = d.GetValueOrDefault(item.When.Date, 0) + item.Amount;
                }
                return(d);
            });

            var rows = repository.Set <MoneyStateModel>()
                       .GroupBy(x => x.When.Date)
                       .OrderByDescending(v => v.Key)
                       .ToList();

            var end = rows.Select(v => (DateTime?)v.Key.Date).FirstOrDefault();

            foreach (var col in paymentsToExempt)
            {
                var      cumulative = 0.0;
                DateTime start      = col.Value.Keys.Min();
                for (; start <= (end ?? start); start = start.AddDays(1))
                {
                    var curValue = col.Value.GetValueOrDefault(start, 0);
                    if (Math.Abs(cumulative + curValue) >= 0.0001)
                    {
                        col.Value[start] = -(curValue + cumulative);
                        cumulative      += curValue;
                    }
                }
            }

            Values = rows
                     .Select(v => new TableRowViewModel(v.ToList(), Headers, headersCached, paymentsToExempt))
                     .ToList();

            for (int i = 0; i < Values.Count - 1; i++)
            {
                var row = Values[i];
                row.Previous = Values[i + 1];
                foreach (var value in row.CalculatedCells.Values)
                {
                    var previous = Values[i + 1];
                    value.PreviousValue = previous.CalculatedCells.GetValueOrDefault(value.Column);
                }
            }

            var markedAsOkCells = Enumerable.Empty <MoneyColumnMetadataJsModel>();

            for (int i = Values.Count - 1; i >= 0; i--)
            {
                var row = Values[i];

                var toAddMissing = markedAsOkCells.Except(row.CalculatedCells.Keys).ToList();

                foreach (var item in toAddMissing)
                {
                    row.CalculatedCells.Add(item, CalculatedResult.Empty(item));
                }

                markedAsOkCells = row.CalculatedCells.Values.Where(v => !(v is ExpressionCalculatedResult) && v.Value != null && double.IsNaN(v.Value.Value))
                                  .Select(v => v.Column).ToList();
            }

            var columnsToCheck = Values.SelectMany(v => v.CalculatedCells.Keys).Distinct()
                                 .Where(v => !v.IsComputed).ToList();

            for (int i = Values.Count - 1; i >= 0; i--)
            {
                var row = Values[i];

                columnsToCheck = columnsToCheck.Except(row.CalculatedCells.Keys).ToList();

                foreach (var item in columnsToCheck)
                {
                    row.CalculatedCells.Add(item, CalculatedResult.Empty(item));
                }
            }

            foreach (var r in Values)
            {
                foreach (var cell in r.CalculatedCells.Values.OfType <ExpressionCalculatedResult>())
                {
                    if (cell.IsOk && cell.Value != null)
                    {
                        repository.Add(new MoneyStateModel
                        {
                            Amount      = cell.Value.Value,
                            Ccy         = cell.Ccy,
                            Column      = headersDictionary[cell.Column],
                            When        = r.When,
                            Description = cell.TooltipWithoutAdjustment
                        });
                    }
                }
            }
        }