private async void ResendMessageIfNeeded() { DateTime nowLocal = TimeZoneInfo.ConvertTimeFromUtc(SystemTime.Now(), TimeZoneInfo.Local); DateTime todayUtc = SystemTime.Now().Date; DateTime lastReceivedMessageDateTimeUtc = MessageUtils.GetDateTimeFromSecureStorageForKey(SecureStorageKeys.LAST_SENT_NOTIFICATION_UTC_KEY, nameof(ResendMessageIfNeeded)); DateTime lastReceivedMessageDateTimeLocal = lastReceivedMessageDateTimeUtc.ToLocalTime(); if (lastReceivedMessageDateTimeUtc < todayUtc && nowLocal.Date.Subtract(lastReceivedMessageDateTimeLocal.Date).TotalHours >= Conf.HOURS_UNTIL_RESEND_MESSAGES) { if (nowLocal.Hour >= Conf.HOUR_WHEN_MESSAGE_SHOULD_BE_RESEND) { List <MessageSQLiteModel> unreadMessages = await MessageUtils.GetAllUnreadMessages(); List <MessageSQLiteModel> unreadMessagesNotOlderThanMsgRetentionTime = unreadMessages.FindAll(message => { double totalMinutes = SystemTime.Now().Subtract(message.TimeStamp).TotalMinutes; return(totalMinutes < Conf.MAX_MESSAGE_RETENTION_TIME_IN_MINUTES); }) .ToList(); if (unreadMessagesNotOlderThanMsgRetentionTime.Count > 0) { NotificationsHelper.CreateNotification(NotificationsEnum.NewMessageReceived, 0); MessageUtils.SaveDateTimeToSecureStorageForKey( SecureStorageKeys.LAST_SENT_NOTIFICATION_UTC_KEY, SystemTime.Now(), nameof(ResendMessageIfNeeded)); } } } }
public async Task <ActionResult> Create([Bind(Include = "Description,Amount,BudgetItemId,BankAccountId,Created,IncomeExpenseId")] Transaction transaction) { if (!userHelper.UserHasEverything()) { TempData["Error"] = "You must have a household, budget, and bank account(s) first!"; return(RedirectToAction("ErrorPage", "Home")); } if (ModelState.IsValid) { var user = db.Users.Find(User.Identity.GetUserId()); transaction.EnteredById = user.Id; transaction.Created = DateTimeOffset.Now; db.Transactions.Add(transaction); db.SaveChanges(); //Send emails and notifications #region Send Balance Notificationsa and emails var account = db.BankAccounts.FirstOrDefault(a => a.Id == transaction.BankAccountId); var recipientEmail = account.AccountOwner.Email; var accountBalance = accountHelper.GetAccountBalance(account.Id); if (accountBalance <= account.WarningBalance) { var callbackUrl = Url.Action("ViewTransactionAlert", "Transactions", new { transId = transaction.Id }, protocol: Request.Url.Scheme); var message = new IdentityMessage(); message.Destination = account.AccountOwner.Email; message.Subject = "Account Balance Warning"; message.Body = account.Name + " has a balance of $" + accountBalance + ". Please click <a href=\"" + callbackUrl + "\">here</a> to view"; var emailSvc = new EmailService(); await emailSvc.SendAsync(message); notificationsHelper.CreateNotification(message); } #endregion return(RedirectToAction("Index")); } ViewBag.BankAccountId = new SelectList(db.BankAccounts, "Id", "Name", transaction.BankAccountId); ViewBag.BudgetItemId = new SelectList(db.BudgetItems, "Id", "Name", transaction.BudgetItemId); ViewBag.EnteredById = new SelectList(db.Users, "Id", "FirstName", transaction.EnteredById); ViewBag.IncomeExpenseId = new SelectList(db.IncomeExpenses, "Id", "Type", transaction.IncomeExpenseId); return(View(transaction)); }
public async Task <ActionResult> SaveTransaction([Bind(Include = "Description,Amount,BudgetItemId,BankAccountId,Created,IncomeExpenseId")] Transaction transaction, int UploadedTransactionId) //public async Task<ActionResult> SaveTransaction(string Description, decimal Amount, int BudgetItemId, int BankAccountId, DateTimeOffset Created, int IncomeExpenseId, int UploadedTransactionId) { //var transaction = new Transaction(); if (!userHelper.UserHasEverything()) { TempData["Error"] = "You must have a household, budget, and bank account(s) first!"; return(RedirectToAction("ErrorPage", "Home")); } var upTrans = db.UploadedTransactions.FirstOrDefault(up => up.Id == UploadedTransactionId); var user = db.Users.Find(User.Identity.GetUserId()); transaction.EnteredById = user.Id; //transaction.Description = Description; //transaction.Created = Created; //transaction.Amount = Amount; //transaction.BudgetItemId = BudgetItemId; //transaction.BankAccountId = BankAccountId; //transaction.IncomeExpenseId = IncomeExpenseId; //Add to db and save changes upTrans.Saved = true; db.Entry(upTrans).State = EntityState.Modified; db.Transactions.Add(transaction); db.SaveChanges(); //Send emails and notifications #region Send Balance Notificationsa and emails var account = db.BankAccounts.FirstOrDefault(a => a.Id == transaction.BankAccountId); var recipientEmail = account.AccountOwner.Email; var accountBalance = accountHelper.GetAccountBalance(account.Id); if (accountBalance <= account.WarningBalance) { var callbackUrl = Url.Action("ViewTransactionAlert", "Transactions", new { transId = transaction.Id }, protocol: Request.Url.Scheme); var message = new IdentityMessage(); message.Destination = account.AccountOwner.Email; message.Subject = "Account Balance Warning"; message.Body = account.Name + " has a balance of $" + accountBalance + ". Please click <a href=\"" + callbackUrl + "\">here</a> to view"; var emailSvc = new EmailService(); await emailSvc.SendAsync(message); notificationsHelper.CreateNotification(message); } #endregion /*Using RedirectToAction to clear residual SelectList data, so last selection does not appear in all of the * Budget Item Lists.*/ return(RedirectToAction("NextTransaction")); }
/// <summary> /// Fetches the new keys if any. /// </summary> /// <returns>Paths to the temporary location where the zips are stored</returns> public async Task <IEnumerable <string> > PullNewKeys(ExposureNotificationWebService service, CancellationToken cancellationToken) { PullKeysParams requestParams = PullKeysParams.GenerateParams(); LocalPreferencesHelper.DidFirstFileOfTheDayEndedWith204 = false; List <string> zipLocations = new List <string>(); bool lastPull = false; int? lastBatchReceived = null; int? lastReceivedStatusCodeFromRequest = null; while (!lastPull) { string requestUrl = requestParams.ToBatchFileRequest(); ApiResponse <Stream> response = await service.GetDiagnosisKeys(requestUrl, cancellationToken); HttpHeaders headers = response.Headers; lastReceivedStatusCodeFromRequest = response.StatusCode; bool headersAreValid = true; if (response == null || (!response.IsSuccessfull)) { if (response?.StatusCode == 410) { NotificationsHelper.CreateNotification(NotificationsEnum.ApiDeprecated, 0); string warning = "410 Api was deprecated"; _developerTools.AddToPullHistoryRecord(warning, requestUrl); LogUtils.LogMessage(LogSeverity.WARNING, $"{_logPrefix}.{nameof(DownloadZips)}: {warning}"); } else { //Failed to fetch new keys due to server error. This is already logged in the webservice. _developerTools.AddToPullHistoryRecord($"{response.StatusCode} Server Error", requestUrl); } break; //Abort pulling } // If the server says 204: No Content, it means that there were no new keys (I.e. the request batch does not exist) if (response.StatusCode == 204) { if (requestParams.Date.Date < SystemTime.Now().Date) { //If there were no new keys for a day which is not today, then move on to fetch keys for the next date. requestParams.Date = requestParams.Date.AddDays(1); requestParams.BatchNumber = 1; lastPull = false; } else { //There were no new keys to fetch for today _developerTools.AddToPullHistoryRecord($"204 No Content - No new keys", requestUrl); string warning = $"API {response.Endpoint} returned 204 No Content - No new keys since last pull"; LogUtils.LogMessage(LogSeverity.WARNING, $"{_logPrefix}.{nameof(DownloadZips)}: {warning}"); lastPull = true; } } else { try { int lastBatchReceivedValue = int.Parse(headers.GetValues(LastBatchReturnedHeader).First()); bool moreBatchesExist = bool.Parse(headers.GetValues(MoreBatchesExistHeader).First()); //If both headers parse (no exceptions), then save lastBatchValue to be persisted lastBatchReceived = lastBatchReceivedValue; if (moreBatchesExist) { //There are still more batches to fetch for the given date requestParams.BatchNumber = (int)lastBatchReceived + 1; lastPull = false; } else if (requestParams.Date.Date < SystemTime.Now().Date) { //If there were no new keys for a day which is not today, then move on to fetch keys for the next date. requestParams.Date = requestParams.Date.AddDays(1); requestParams.BatchNumber = 1; lastPull = false; } else { //There are no more batches to fetch for today. Try again in some hours. lastPull = true; } } catch (Exception e) { headersAreValid = false; HandleErrorWhenPulling(e, $"Failed to parse {MoreBatchesExistHeader} or {LastBatchReturnedHeader} header.", requestUrl); break; //Abort pulling } } // Copy the zip stream in the response into a temp file if (response.StatusCode == 200 && headersAreValid) { try { _developerTools.AddToPullHistoryRecord("200 OK", requestUrl); string tmpFile = Path.Combine(ServiceLocator.Current.GetInstance <IFileSystem>().CacheDirectory, Guid.NewGuid() + ".zip"); FileStream tmpFileStream = File.Create(tmpFile); await response.Data.CopyToAsync(tmpFileStream); tmpFileStream.Close(); zipLocations.Add(tmpFile); } catch (Exception e) { HandleErrorWhenPulling(e, "Failed to save zip locally", requestUrl); break; //Abort pulling } } } if (zipLocations.Any() && lastBatchReceived != null) { //Persist the last batch that was fetched, to know which one to fetch next time the background task runs. LocalPreferencesHelper.LastPullKeysBatchNumberNotSubmitted = (int)lastBatchReceived; //Also save the last batchtype fetched LocalPreferencesHelper.LastPulledBatchType = requestParams.BatchType; } // Edge case for when pulling across multiple days ends up in 204 for the first file if (requestParams.Date.Date == SystemTime.Now().Date && requestParams.BatchNumber == 1 && lastReceivedStatusCodeFromRequest == 204) { LocalPreferencesHelper.DidFirstFileOfTheDayEndedWith204 = true; } return(zipLocations); }