public async Task <IActionResult> Create([FromBody] InterpreterDetailsModel interpreter) { if (interpreter == null) { return(ReturnError(ErrorCodes.IncomingPayloadIsMissing)); } try { var brokerId = User.TryGetBrokerId().Value; if (EnumHelper.GetEnumByCustomName <InterpreterInformationType>(interpreter.InterpreterInformationType) != InterpreterInformationType.NewInterpreter) { ReturnError(ErrorCodes.InterpreterFaultyIntention); } var createdInterpreter = _apiUserService.GetInterpreter(interpreter, brokerId); await _dbContext.SaveChangesAsync(); var createdInterpreterResponse = ApiUserService.GetModelFromEntity(createdInterpreter); return(Ok(new CreateInterpreterResponse { Interpreter = createdInterpreterResponse })); } catch (InvalidApiCallException ex) { return(ReturnError(ex.ErrorCode)); } catch (Exception e) { _logger.LogError(e, $"Unexpected error occured when client called Request/{nameof(View)}"); return(ReturnError(ErrorCodes.UnspecifiedProblem)); } }
public async Task <ActionResult> Edit(CustomerModel model) { var customer = _dbContext.CustomerOrganisations.Single(c => c.CustomerOrganisationId == model.CustomerId); customer.CustomerSettings = await _dbContext.CustomerSettings.GetCustomerSettingsForCustomer(customer.CustomerOrganisationId).ToListAsync(); if ((await _authorizationService.AuthorizeAsync(User, customer, Policies.Edit)).Succeeded) { if (ModelState.IsValid) { var customerSettings = model.CustomerSettings.Select(cs => new CustomerSetting { CustomerSettingType = cs.CustomerSettingType, Value = cs.Value }); customer.UpdateCustomerSettingsAndHistory(_clock.SwedenNow, User.GetUserId(), customerSettings); model.UpdateCustomer(customer); await _dbContext.SaveChangesAsync(); await _cacheService.Flush(CacheKeys.CustomerSettings); await _cacheService.Flush(CacheKeys.OrganisationSettings); return(RedirectToAction(nameof(View), new { Id = model.CustomerId, Message = "Myndighet har uppdaterats" })); } return(View(model)); } return(Forbid()); }
public async Task <ActionResult> Edit(InterpreterModel model) { if (ModelState.IsValid) { var interpreter = _dbContext.InterpreterBrokers.SingleOrDefault(u => u.InterpreterBrokerId == model.Id); if ((await _authorizationService.AuthorizeAsync(User, interpreter, Policies.Edit)).Succeeded) { if (!_interpreterService.IsUniqueOfficialInterpreterId(model.OfficialInterpreterId, User.GetBrokerId(), model.Id)) { ModelState.AddModelError(nameof(model.OfficialInterpreterId), $"Er förmedling har redan registrerat en tolk med detta tolknummer (Kammarkollegiets) i tjänsten."); } else { if (interpreter.IsActive != model.IsActive) { model.UpdateAndChangeStatusInterpreter(interpreter, interpreter.IsActive ? (int?)User.GetUserId() : null, interpreter.IsActive ? User.TryGetImpersonatorId() : null, interpreter.IsActive ? (DateTimeOffset?)_clock.SwedenNow : null); } else { model.UpdateInterpreter(interpreter); } await _dbContext.SaveChangesAsync(); return(RedirectToAction(nameof(List), new InterpreterListModel { Message = "Tolkinformation har sparats" })); } } } return(View(model)); }
public async Task <ActionResult> Create(CustomerUnitModel model) { if (ModelState.IsValid) { if (!IsUniqueName(model.Name)) { ModelState.AddModelError(nameof(model.Name), $"Namnet används redan för en annan enhet för denna myndighet"); } else if (!_userService.IsUniqueEmail(model.Email)) { ModelState.AddModelError(nameof(model.Email), $"E-postadressen används redan i tjänsten"); } else { int?customerId = User.TryGetCustomerOrganisationId(); var unit = new CustomerUnit(); unit.Create(_clock.SwedenNow, User.GetUserId(), User.TryGetImpersonatorId(), User.GetCustomerOrganisationId(), model.Name, model.Email, model.LocalAdministrator); await _userService.LogCustomerUnitUserUpdateAsync(model.LocalAdministrator, User.GetUserId(), User.TryGetImpersonatorId()); await _dbContext.AddAsync(unit); await _dbContext.SaveChangesAsync(); return(RedirectToAction(nameof(View), new { id = unit.CustomerUnitId })); } } return(View(model)); }
public async Task <IActionResult> Accept([FromBody] ComplaintAcceptModel model) { if (model == null) { return(ReturnError(ErrorCodes.IncomingPayloadIsMissing, nameof(Accept))); } try { var brokerId = User.TryGetBrokerId().Value; var apiUserId = User.UserId(); _ = await _apiOrderService.GetOrderAsync(model.OrderNumber, brokerId); var user = await _apiUserService.GetBrokerUser(model.CallingUser, brokerId); var complaint = await GetCreatedComplaint(model.OrderNumber, brokerId); _complaintService.Accept(complaint, user?.Id ?? apiUserId, user != null ? (int?)apiUserId : null); await _dbContext.SaveChangesAsync(); //End of service return(Ok(new ResponseBase())); } catch (InvalidApiCallException ex) { return(ReturnError(ex.ErrorCode, nameof(Accept))); } }
public async Task <IActionResult> Create(ComplaintModel model) { if (ModelState.IsValid) { var request = await _dbContext.Requests.GetSimpleRequestById(model.RequestId); if ((await _authorizationService.AuthorizeAsync(User, request, Policies.CreateComplaint)).Succeeded) { try { await _complaintService.Create(request, User.GetUserId(), User.TryGetImpersonatorId(), model.Message, model.ComplaintType.Value); await _dbContext.SaveChangesAsync(); } catch (InvalidOperationException ex) { _logger.LogError("Wrong status or complaint exists when trying to Create complaint. Status: {request.Status}, RequestId {request.RequestId}", request.Status, request.RequestId); return(RedirectToAction("Index", "Home", new { errormessage = ex.Message })); } return(RedirectToAction("View", "Order", new { id = request.OrderId, tab = "complaint" })); } return(Forbid()); } return(View(nameof(Create), model)); }
private async Task <IActionResult> CreateUpdateSystemMessage(SystemMessageModel model, bool update) { if (model.DisplayDate.Start > model.DisplayDate.End) { model.SystemMessageTypeValue = EnumHelper.Parse <SystemMessageType>(model.SystemMessageType.SelectedItem.Value); ModelState.AddModelError($"{nameof(model.DisplayDate)}.{nameof(model.DisplayDate.Start)}", "Visningsdatum för nyheten är fel. Från och med datum kan inte vara större än till och med datum."); } else { if (update) { var sysMessage = await _dbContext.SystemMessages.GetSystemMessageById(model.SystemMessageId); sysMessage.Update(_clock.SwedenNow, User.GetUserId(), User.TryGetImpersonatorId(), model.DisplayDate.Start.ToDateTimeOffsetSweden(), model.DisplayDate.End.ToDateTimeOffsetSweden(), model.SystemMessageHeader, model.SystemMessageText, EnumHelper.Parse <SystemMessageType>(model.SystemMessageType.SelectedItem.Value), model.DisplayedForUserTypeGroup); } else { var sysMessage = new SystemMessage(); sysMessage.Create(_clock.SwedenNow, User.GetUserId(), User.TryGetImpersonatorId(), model.DisplayDate.Start.ToDateTimeOffsetSweden(), model.DisplayDate.End.ToDateTimeOffsetSweden(), model.SystemMessageHeader, model.SystemMessageText, EnumHelper.Parse <SystemMessageType>(model.SystemMessageType.SelectedItem.Value), model.DisplayedForUserTypeGroup); await _dbContext.AddAsync(sysMessage); } await _dbContext.SaveChangesAsync(); return(RedirectToAction("List")); } return(View(model)); }
public async Task CallWebHooks() { List <int> callIds = null; using (TolkDbContext context = _options.GetContext()) { callIds = await context.OutboundWebHookCalls .Where(e => e.DeliveredAt == null && e.FailedTries < NumberOfTries && !e.IsHandling) .Select(e => e.OutboundWebHookCallId) .ToListAsync(); if (callIds.Any()) { var calls = context.OutboundWebHookCalls .Where(e => callIds.Contains(e.OutboundWebHookCallId) && e.IsHandling == false) .Select(c => c); await calls.ForEachAsync(c => c.IsHandling = true); await context.SaveChangesAsync(); } } _logger.LogInformation("Found {count} outbound web hook calls to send: {callIds}", callIds.Count, string.Join(", ", callIds)); if (callIds.Any()) { var tasks = new List <Task>(); foreach (var callId in callIds) { tasks.Add(Task.Factory.StartNew(() => CallWebhook(callId), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current)); } await Task.Factory.ContinueWhenAny(tasks.ToArray(), r => { }); } }
public async Task <IActionResult> Process(int id) { var requestGroup = await _dbContext.RequestGroups.GetRequestGroupToView(id); if ((await _authorizationService.AuthorizeAsync(User, requestGroup, Policies.Accept)).Succeeded) { if (!requestGroup.IsToBeProcessedByBroker) { _logger.LogWarning("Wrong status when trying to process request group. Status: {request.Status}, RequestGroupId: {request.RequestGroupId}", requestGroup.Status, requestGroup.RequestGroupId); return(RedirectToAction(nameof(View), new { id })); } if (requestGroup.Status == RequestStatus.Created) { await _requestService.AcknowledgeGroup(requestGroup, _clock.SwedenNow, User.GetUserId(), User.TryGetImpersonatorId()); await _dbContext.SaveChangesAsync(); } OrderGroup orderGroup = await _dbContext.OrderGroups.GetFullOrderGroupById(requestGroup.OrderGroupId); await _orderService.AddOrdersWithListsForGroup(orderGroup); await _requestService.AddListsForRequestGroup(requestGroup); requestGroup.Requests.ForEach(r => r.Order = orderGroup.Orders.Where(o => o.OrderId == r.OrderId).SingleOrDefault()); var model = RequestGroupProcessModel.GetModelFromRequestGroup(requestGroup, Guid.NewGuid(), _options.CombinedMaxSizeAttachments, _options.AllowDeclineExtraInterpreterOnRequestGroups); await _listToModelService.AddInformationFromListsToModel(model, User.GetUserId()); model.CustomerInformationModel.IsCustomer = false; model.CustomerInformationModel.UseSelfInvoicingInterpreter = _cacheService.CustomerSettings.Any(c => c.CustomerOrganisationId == requestGroup.OrderGroup.CustomerOrganisationId && c.UsedCustomerSettingTypes.Any(cs => cs == CustomerSettingType.UseSelfInvoicingInterpreter)); //if not first broker in rank (requests are not answered and have no pricerows) we need to get a calculated price with correct broker fee if (requestGroup.Ranking.Rank != 1) { List <OrderOccasionDisplayModel> tempOccasionList = new List <OrderOccasionDisplayModel>(); foreach (OrderOccasionDisplayModel occasion in model.OccasionList.Occasions) { var request = requestGroup.Requests.Single(r => r.RequestId == occasion.RouteId); tempOccasionList.Add(OrderOccasionDisplayModel.GetModelFromOrder(request.Order, GetPriceinformationOrderToDisplay(request, model.RequestedCompetenceLevels.ToList()), request)); } model.OccasionList.Occasions = tempOccasionList; } return(View(model)); } return(Forbid()); }
public async Task <IActionResult> Approve(ProcessRequestGroupModel model) { var requestGroup = await _dbContext.RequestGroups.GetRequestGroupById(model.RequestGroupId); if ((await _authorizationService.AuthorizeAsync(User, requestGroup.OrderGroup, Policies.Accept)).Succeeded) { if (!requestGroup.CanApprove) { _logger.LogError("Wrong status when trying to Approve request group. Status: {requestGroup.Status}, RequestGroupId: {requestGroup.RequestGroupId}", requestGroup.Status, requestGroup.RequestGroupId); return(RedirectToAction(nameof(View), new { id = requestGroup.OrderGroupId })); } await _orderService.ApproveRequestGroupAnswer(requestGroup, User.GetUserId(), User.TryGetImpersonatorId()); await _dbContext.SaveChangesAsync(); return(RedirectToAction(nameof(View), new { id = requestGroup.OrderGroupId })); } return(Forbid()); }
private async Task <IActionResult> PasswordLogin(LoginViewModel model, Uri returnUrl) { var user = await _userManager.FindByEmailAsync(model.UserName) ?? await _userManager.FindByNameAsync(model.UserName); if (user != null) { var result = await _signInManager.PasswordSignInAsync(user, model.Password, isPersistent : true, lockoutOnFailure : true); if (result.Succeeded) { if (!user.IsActive) { //I want this to be done in two steps, first validating the user, then if valid user but inactive log out again, with proper message. await _signInManager.SignOutAsync(); _logger.LogInformation("Inactivated User {userName} tried to log in.", model.UserName); ModelState.AddModelError(nameof(model.UserName), "Ditt konto är tillfälligt inaktiverat, vänligen kontakta [email protected] för mer information."); return(View(model)); } user.LastLoginAt = _clock.SwedenNow; await _userManager.UpdateAsync(user); await _dbContext.SaveChangesAsync(); await _userService.LogLoginAsync(user.Id); _logger.LogInformation("User {userName} logged in.", model.UserName); return(RedirectToLocal(returnUrl)); } if (result.IsLockedOut) { _logger.LogWarning("User account {userName} locked out.", model.UserName); return(RedirectToAction(nameof(Lockout))); } } //No user found, or wrong password is handled the same ModelState.AddModelError(nameof(model.UserName), "Felaktigt användarnamn eller lösenord."); return(View(model)); }
public async Task <JsonResult> Delete(int id, Guid groupKey) { //this delete is just for deleting attachments added in UI before connected to orders, requests and requisitions var attachment = await _dbContext.Attachments.GetNonConnectedAttachmentById(id); if (attachment != null && attachment.TemporaryAttachmentGroup.TemporaryAttachmentGroupKey == groupKey && (await _authorizationService.AuthorizeAsync(User, attachment, Policies.Delete)).Succeeded) { _dbContext.TemporaryAttachmentGroups.Remove(attachment.TemporaryAttachmentGroup); _dbContext.Attachments.Remove(attachment); await _dbContext.SaveChangesAsync(); } return(Json(new { success = true })); }
public async Task <IActionResult> Process(int id) { var request = await _dbContext.Requests.GetRequestById(id); if ((await _authorizationService.AuthorizeAsync(User, request, Policies.Accept)).Succeeded) { if (!request.IsToBeProcessedByBroker) { _logger.LogWarning("Wrong status when trying to process request. Status: {request.Status}, RequestId: {request.RequestId}", request.Status, request.RequestId); return(RedirectToAction(nameof(View), new { id })); } if (request.Status == RequestStatus.Created) { _requestService.Acknowledge(request, _clock.SwedenNow, User.GetUserId(), User.TryGetImpersonatorId()); await _dbContext.SaveChangesAsync(); } RequestModel model = await GetModel(request); model.FileGroupKey = new Guid(); model.CombinedMaxSizeAttachments = _options.CombinedMaxSizeAttachments; model.ExpectedTravelCosts = null; model.AllowProcessing = !request.RequestGroupId.HasValue; if (model.OrderViewModel.ReplacingOrderId.HasValue) { model.ProcessReplacementRequestViewModel = RequestViewModel.GetModelFromRequest(request, request.Order.AllowExceedingTravelCost); model.ProcessReplacementRequestViewModel.LanguageAndDialect = model.OrderViewModel.LanguageAndDialect; model.ProcessReplacementRequestViewModel.RegionName = model.OrderViewModel.RegionName; model.ProcessReplacementRequestViewModel.TimeRange = model.OrderViewModel.TimeRange; model.ProcessReplacementRequestViewModel.DisplayMealBreakIncluded = model.OrderViewModel.DisplayMealBreakIncludedText; model.ProcessReplacementRequestViewModel.IsReplacingOrderRequest = true; model.ProcessReplacementRequestViewModel.RequirementAnswers = await RequestRequirementAnswerModel.GetFromList(_dbContext.OrderRequirementRequestAnswer.GetRequirementAnswersForRequest(request.RequestId)); } model.OrderViewModel.UseAttachments = true; return(View(model)); } return(Forbid()); }
public async Task <IActionResult> Create([FromBody] RequisitionModel model) { if (model == null) { return(ReturnError(ErrorCodes.IncomingPayloadIsMissing)); } try { var brokerId = User.TryGetBrokerId().Value; var apiUserId = User.UserId(); var order = await _apiOrderService.GetOrderAsync(model.OrderNumber, brokerId); var user = await _apiUserService.GetBrokerUser(model.CallingUser, brokerId); var request = await _dbContext.Requests.GetActiveRequestForApiWithBrokerAndOrderNumber(model.OrderNumber, brokerId); if (request == null) { return(ReturnError(ErrorCodes.RequestNotFound)); } if (!request.IsApprovedOrDelivered) { return(ReturnError(ErrorCodes.RequestNotInCorrectState)); } try { await _requisitionService.Create(request, user?.Id ?? apiUserId, (user != null ? (int?)apiUserId : null), model.Message, model.Outlay, model.AcctualStartedAt, model.AcctualEndedAt, model.WasteTime, model.WasteTimeInconvenientHour, EnumHelper.GetEnumByCustomName <TaxCardType>(model.TaxCard).Value, new List <RequisitionAttachment>(), Guid.NewGuid(), model.MealBreaks.Select(m => new MealBreak { StartAt = m.StartedAt, EndAt = m.EndedAt, }).ToList(), model.CarCompensation, model.PerDiem); await _dbContext.SaveChangesAsync(); } catch (InvalidOperationException) { //TODO: Should log the acctual exception here!! return(ReturnError(ErrorCodes.RequisitionNotInCorrectState)); } return(Ok(new ResponseBase())); } catch (InvalidApiCallException ex) { return(ReturnError(ex.ErrorCode)); } }
[OpenApiIgnore]//Not applicable for broker api, hence hiding it from swagger public async Task <IActionResult> Create([FromBody] CreateOrderModel model) { var method = $"{nameof(OrderController)}.{nameof(Create)}"; _logger.LogDebug($"{method} was called"); if (model == null) { return(ReturnError(ErrorCodes.IncomingPayloadIsMissing, method)); } if (!_tolkBaseOptions.EnableCustomerApi) { _logger.LogWarning($"{model.CallingUser} called {method}, but CustomerApi is not enabled!"); return(BadRequest(new ValidationProblemDetails { Title = "CustomerApi is not enabled!" })); } if (string.IsNullOrEmpty(model.CallingUser)) { return(ReturnError(ErrorCodes.CallingUserMissing, method)); } _logger.LogInformation($"{model.CallingUser} is creating a new order"); if (ModelState.IsValid) { try { var order = await _apiOrderService.GetOrderFromModel(model, User.UserId(), User.TryGetCustomerId().Value); await _orderService.Create(order, model.LatestAnswerBy); await _dbContext.SaveChangesAsync(); _logger.LogInformation($"{order.OrderNumber} was created"); return(Ok(new CreateOrderResponse { OrderNumber = order.OrderNumber, PriceInformation = order.PriceRows.GetPriceInformationModel( order.PriceCalculatedFromCompetenceLevel.GetCustomName(), (await _dbContext.Requests.GetActiveRequestByOrderId(order.OrderId)).Ranking.BrokerFee), })); } catch (InvalidOperationException ex) { return(ReturnError(ErrorCodes.OrderNotValid, method, ex.Message)); } catch (ArgumentNullException ex) { return(ReturnError(ErrorCodes.OrderNotValid, method, ex.Message)); } } return(ReturnError(ErrorCodes.OrderNotValid, method)); }
private async Task <IActionResult> CreateUpdateFaq(FaqModel model, bool update) { Faq faq = new Faq(); var displayForRoles = model.DisplayForRoles.SelectedItems.Select(r => EnumHelper.Parse <DisplayUserRole>(r.Value)); if (update) { var faqDisplayUserRolesWithFaq = await _dbContext.FaqDisplayUserRole.GetFaqWithFaqDisplayUserRolesByFaqId(model.FaqId).ToListAsync(); faq = faqDisplayUserRolesWithFaq.Select(f => f.Faq).First(); faq.Update(_clock.SwedenNow, User.GetUserId(), model.IsDisplayed, model.Question, model.Answer, displayForRoles); } else { faq.Create(_clock.SwedenNow, User.GetUserId(), model.IsDisplayed, model.Question, model.Answer, displayForRoles); await _dbContext.AddAsync(faq); } await _dbContext.SaveChangesAsync(); return(RedirectToAction("List")); }
public async Task CheckForFailuresToReport() { var callIds = await _tolkDbContext.OutboundWebHookCalls .Where(e => e.DeliveredAt == null && e.HasNotifiedFailure == false) .Select(e => e.OutboundWebHookCallId) .ToListAsync(); _logger.LogInformation("Found {count} emails to send: {emailIds}", callIds.Count, string.Join(", ", callIds)); if (callIds.Any()) { foreach (var callId in callIds) { try { var call = await _tolkDbContext.OutboundWebHookCalls .SingleOrDefaultAsync(e => e.OutboundWebHookCallId == callId && e.DeliveredAt == null && e.HasNotifiedFailure == false); if (call == null) { _logger.LogInformation("Call {callId} was in list to be notifed as a failure, but now appears to have been handled.", callId); } else { _logger.LogInformation("Notifying failure on {callId} of type {notificationType}", callId, call.NotificationType); await _notificationService.NotifyOnFailure(callId); call.HasNotifiedFailure = true; await _tolkDbContext.SaveChangesAsync(); } } catch (Exception ex) { _logger.LogError(ex, "Failure Notifying failure on {callId}", callId); } } } }
public async Task <UpdateLanguagesCompetenceResult> UpdateTellusLanguagesCompetenceInfo(bool notify = false) { _logger.LogInformation($"Starting {nameof(UpdateTellusLanguagesCompetenceInfo)}"); if (!_tolkBaseOptions.Tellus.IsLanguagesCompetenceActivated) { return new UpdateLanguagesCompetenceResult { UpdatedLanguages = Enumerable.Empty <Language>(), Message = "Hämtningen av språkkompetenser från Tellus är inte aktiverad, ändra konfigurering för att aktivera." } } ; try { var response = await client.GetAsync(_tolkBaseOptions.Tellus.LanguagesCompetenceInfoUri); string content = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject <TellusLanguagesCompetenceInfoResponse>(content); if (result.Status != 200) { if (notify) { _notificationService.CreateEmail(_tolkBaseOptions.Support.SecondLineEmail, $"Hämtningen av språkkompetenser från Tellus misslyckades!", $"Här kan du testa att köra en hämtning direkt ifrån tjänsten:\n\n{_tolkBaseOptions.TolkWebBaseUrl}Language/UpdateCompetences", null, NotificationType.GetCompetencesFromTellusFailed ); } _logger.LogWarning($"Hämtningen av språkkompetenser från Tellus misslyckades, med status {result.Status}"); return(new UpdateLanguagesCompetenceResult { UpdatedLanguages = Enumerable.Empty <Language>(), Message = $"Hämtningen av språkkompetenser från Tellus misslyckades, med status {result.Status}" }); } var currentTellusLanguages = await _dbContext.Languages.Where(l => !string.IsNullOrWhiteSpace(l.TellusName)).ToListAsync(); var tellusLanguagesWithCompetences = result.Result.Where(t => currentTellusLanguages.Any(l => l.TellusName == t.Id && l.Active)); if (!result.Result.Any() || !tellusLanguagesWithCompetences.Any()) { _logger.LogWarning($"Result of {nameof(UpdateTellusLanguagesCompetenceInfo)} had no active languages"); if (notify) { await _emailService.SendApplicationManagementEmail(result.Result.Any()? "Hämtningen av språkkompetenser från Tellus innehöll endast ej aktiva språk eller Tellusnamn som inte förekommer i tjänsten" : "Hämtningen av språkkompetenser från Tellus innehöll inga språk", $"Här kan du testa att köra en hämtning direkt ifrån tjänsten:\n\n{_tolkBaseOptions.TolkWebBaseUrl}Language/UpdateCompetences"); } return(new UpdateLanguagesCompetenceResult { UpdatedLanguages = Enumerable.Empty <Language>(), Message = result.Result.Any() ? "Hämtningen innehöll endast ej aktiva språk eller Tellusnamn som inte förekommer i tjänsten" : "Hämtningen innehöll inga språk" }); } List <Language> updatedLanguages = new List <Language>(); foreach (TellusLanguagesInfoModel l in tellusLanguagesWithCompetences) { var updates = currentTellusLanguages.Where(ls => ls.TellusName == l.Id && (l.HasLegal != ls.HasLegal || l.HasHealthcare != ls.HasHealthcare || l.HasAuthorized != ls.HasAuthorized || l.HasEducated != ls.HasEducated)).ToList(); updates.ForEach(c => { c.HasLegal = l.HasLegal; c.HasHealthcare = l.HasHealthcare; c.HasAuthorized = l.HasAuthorized; c.HasEducated = l.HasEducated; }); updatedLanguages.AddRange(updates); } await _dbContext.SaveChangesAsync(); _logger.LogInformation($"Update of {nameof(UpdateTellusLanguagesCompetenceInfo)} completed"); return(new UpdateLanguagesCompetenceResult { UpdatedLanguages = updatedLanguages, Message = updatedLanguages.Any() ? string.Empty : "Inga skillnader i kompetenser fanns mellan tjänsten och Tellus" }); } catch (Exception ex) { _logger.LogError(ex, $"Running {nameof(UpdateTellusLanguagesCompetenceInfo)} failed"); await SendErrorMail(nameof(UpdateTellusLanguagesCompetenceInfo), ex); return(new UpdateLanguagesCompetenceResult { UpdatedLanguages = Enumerable.Empty <Language>(), Message = "Hämtningen av språkkompetenser misslyckades." }); } }
public async Task <IActionResult> Create(int orderId) { var request = await _dbContext.Requests.GetRequestForOrderAgreementCreation(orderId); if (!_cacheService.CustomerSettings.Any(c => c.CustomerOrganisationId == request.Order.CustomerOrganisationId && c.UsedCustomerSettingTypes.Any(cs => cs == CustomerSettingType.UseOrderAgreements))) { return(Forbid()); } request.Requisitions = await _dbContext.Requisitions.GetRequisitionsForRequest(request.RequestId).ToListAsync(); request.OrderAgreementPayloads = await _dbContext.OrderAgreementPayloads.GetOrderAgreementPayloadsForRequest(request.RequestId).ToListAsync(); if (request != null && (await _authorizationService.AuthorizeAsync(User, request, Policies.CreateOrderAgreement)).Succeeded) { if (request.AllowOrderAgreementCreation()) { var requisitionId = (await _dbContext.Requisitions.GetRequisitionsForOrder(orderId).Where(r => r.Status == RequisitionStatus.Approved || r.Status == RequisitionStatus.AutomaticGeneratedFromCancelledOrder || r.Status == RequisitionStatus.Created || r.Status == RequisitionStatus.Reviewed).SingleOrDefaultAsync())?.RequisitionId; var previousIndex = request.OrderAgreementPayloads.Max(p => p.Index as int?); int index = 1; string payloadIdentifier = ""; using var memoryStream = new MemoryStream(); using var writer = new StreamWriter(memoryStream, Encoding.UTF8); if (requisitionId.HasValue) { payloadIdentifier = await _orderAgreementService.CreateOrderAgreementFromRequisition(requisitionId.Value, writer, previousIndex); index = previousIndex.HasValue ? previousIndex.Value + 1 : 1; } else { payloadIdentifier = await _orderAgreementService.CreateOrderAgreementFromRequest(request.RequestId, writer); } memoryStream.Position = 0; byte[] byteArray = new byte[memoryStream.Length]; memoryStream.Read(byteArray, 0, (int)memoryStream.Length); memoryStream.Close(); //Save it to db var payload = new OrderAgreementPayload { CreatedBy = User.GetUserId(), ImpersonatingCreatedBy = User.TryGetImpersonatorId(), Payload = byteArray, RequisitionId = requisitionId, CreatedAt = _clock.SwedenNow, Index = index, IdentificationNumber = payloadIdentifier }; request.OrderAgreementPayloads.Add(payload); if (previousIndex.HasValue) { var previous = request.OrderAgreementPayloads.Single(p => p.Index == previousIndex); previous.ReplacedByPayload = payload; } await _dbContext.SaveChangesAsync(); //return a identifier for the saved agreement, to be able to retrieve it. return(RedirectToAction(nameof(View), new { id = payload.OrderAgreementPayloadId })); } } else { //Handle non-allow } return(Forbid()); }
public async Task SendInviteAsync(AspNetUser user) { string subject = null; string body = null; string plainBody = null; string htmlBody = null; NullCheckHelper.ArgumentCheckNull(user, nameof(SendInviteAsync), nameof(UserService)); if (user.InterpreterId.HasValue) { (subject, body) = CreateInterpreterInvite(); if (subject == null || body == null) { throw new NotImplementedException(); } } else { // Not interpreter => must belong to organization. (subject, htmlBody) = CreateOrganizationUserActivation(true); (subject, plainBody) = CreateOrganizationUserActivation(false); if (subject == null || htmlBody == null || plainBody == null) { throw new NotImplementedException(); } } var link = await GenerateActivationLinkAsync(user); plainBody = plainBody.FormatSwedish(link); htmlBody = HtmlHelper.ToHtmlBreak(htmlBody).FormatSwedish(HtmlHelper.GetButtonDefaultLargeTag(link.AsUri(), "Registrera användarkonto"), link); _notificationService.CreateEmail(user.Email, subject, plainBody, htmlBody, NotificationType.UserInvitation); await _dbContext.SaveChangesAsync(); _logger.LogInformation("Sent account confirmation link to {userId} ({email})", user.Id, user.Email); }
private async void Run(bool isInit = false) { _logger.LogTrace("EntityScheduler waking up."); if ((nextDailyRunTime - _clock.SwedenNow).TotalHours > 25 || nextDailyRunTime.Hour != timeToRun) { _logger.LogWarning("nextDailyRunTime set to invalid time, was {0}", nextDailyRunTime); DateTimeOffset now = _clock.SwedenNow; now -= now.TimeOfDay; nextDailyRunTime = now - now.TimeOfDay; nextDailyRunTime = nextDailyRunTime.AddHours(timeToRun); if (_clock.SwedenNow.Hour > timeToRun) { // Next remind is tomorrow nextDailyRunTime = nextDailyRunTime.AddDays(1); } } if (isInit) { using TolkDbContext context = _options.GetContext(); await context.OutboundEmails.Where(e => e.IsHandling == true) .Select(c => c).ForEachAsync(c => c.IsHandling = false); await context.OutboundWebHookCalls.Where(e => e.IsHandling == true) .Select(c => c).ForEachAsync(c => c.IsHandling = false); await context.SaveChangesAsync(); } try { if (nextRunIsNotifications) { //Separate these, to get a better parallellism for the notifications // They fail to run together with the other Continous jobs , due to recurring deadlocks around the email table... List <Task> tasksToRunNotifications = new List <Task> { Task.Factory.StartNew(() => _services.GetRequiredService <EmailService>().SendEmails(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current), Task.Factory.StartNew(() => _services.GetRequiredService <WebHookService>().CallWebHooks(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current) }; await Task.Factory.ContinueWhenAny(tasksToRunNotifications.ToArray(), r => { }); } else { //would like to have a timer here, to make it possible to get tighter runs if the last run ran for longer than 10 seconds or somethng... using var serviceScope = _services.CreateScope(); Task[] tasksToRun; if (_clock.SwedenNow > nextDailyRunTime) { nextDailyRunTime = nextDailyRunTime.AddDays(1); nextDailyRunTime -= nextDailyRunTime.TimeOfDay; nextDailyRunTime = nextDailyRunTime.AddHours(timeToRun); _logger.LogTrace("Running DailyRunTime, next run on {0}", nextDailyRunTime); tasksToRun = new Task[] { RunDailyJobs(serviceScope.ServiceProvider), }; } else { tasksToRun = new Task[] { RunContinousJobs(serviceScope.ServiceProvider), }; } if (!Task.WaitAll(tasksToRun, allotedTimeAllTasks)) { throw new InvalidOperationException($"All tasks instances didn't complete execution within the allotted time: {allotedTimeAllTasks / 1000} seconds"); } } } catch (Exception ex) { _logger.LogCritical(ex, "Entity Scheduler failed ({message}).", ex.Message); _ = _services.GetRequiredService <EmailService>().SendErrorEmail(nameof(EntityScheduler), nameof(Run), ex); } finally { nextRunIsNotifications = !nextRunIsNotifications; if (_services.GetRequiredService <ITolkBaseOptions>().RunEntityScheduler) { await Task.Delay(timeDelayContinousJobs).ContinueWith(t => Run(), TaskScheduler.Default); } } _logger.LogTrace($"EntityScheduler done, scheduled to wake up in {timeDelayContinousJobs / 1000} seconds again"); }
public async Task <Requisition> Create(Request request, int userId, int?impersonatorId, string message, decimal?outlay, DateTimeOffset sessionStartedAt, DateTimeOffset sessionEndedAt, int?timeWasteNormalTime, int?timeWasteIWHTime, TaxCardType interpreterTaxCard, List <RequisitionAttachment> attachments, Guid fileGroupKey, List <MealBreak> mealbreaks, int?carCompensation, string perDiem) { NullCheckHelper.ArgumentCheckNull(request, nameof(Create), nameof(RequisitionService)); request.Requisitions = await _dbContext.Requisitions.GetRequisitionsForRequest(request.RequestId).ToListAsync(); if (!request.CanCreateRequisition) { throw new InvalidOperationException($"Cannot create requisition on order {request.OrderId}"); } request.PriceRows = await _dbContext.RequestPriceRows.GetPriceRowsForRequest(request.RequestId).ToListAsync(); var priceInformation = _priceCalculationService.GetPricesRequisition( sessionStartedAt, sessionEndedAt, request.Order.StartAt, request.Order.EndAt, EnumHelper.Parent <CompetenceAndSpecialistLevel, CompetenceLevel>((CompetenceAndSpecialistLevel)request.CompetenceLevel), request.Order.CustomerOrganisation.PriceListType, request.Ranking.RankingId, out bool useRequestRows, timeWasteNormalTime, timeWasteIWHTime, request.PriceRows.OfType <PriceRowBase>(), outlay, request.Order.ReplacingOrderId.HasValue ? request.Order.ReplacingOrder : null, request.Order.CreatedAt, mealbreaks ); using var transaction = _dbContext.Database.BeginTransaction(); var requisition = new Requisition { Status = RequisitionStatus.Created, CreatedBy = userId, CreatedAt = _clock.SwedenNow, ImpersonatingCreatedBy = impersonatorId, Message = message, SessionStartedAt = sessionStartedAt, SessionEndedAt = sessionEndedAt, TimeWasteNormalTime = timeWasteNormalTime, TimeWasteIWHTime = timeWasteIWHTime, InterpretersTaxCard = interpreterTaxCard, PriceRows = priceInformation.PriceRows.Select(row => DerivedClassConstructor.Construct <PriceRowBase, RequisitionPriceRow>(row)).ToList(), Attachments = attachments, MealBreaks = mealbreaks, CarCompensation = carCompensation, PerDiem = perDiem, RequestOrReplacingOrderPeriodUsed = useRequestRows, }; foreach (var tag in _dbContext.TemporaryAttachmentGroups.Where(t => t.TemporaryAttachmentGroupKey == fileGroupKey)) { _dbContext.TemporaryAttachmentGroups.Remove(tag); } request.CreateRequisition(requisition); await _dbContext.SaveChangesAsync(); var replacingRequisition = request.Requisitions.SingleOrDefault(r => r.Status == RequisitionStatus.Commented && !r.ReplacedByRequisitionId.HasValue); if (replacingRequisition != null) { replacingRequisition.ReplacedByRequisitionId = requisition.RequisitionId; await _dbContext.SaveChangesAsync(); } transaction.Commit(); _logger.LogDebug($"Created requisition {requisition.RequisitionId} for request {request.RequestId}"); _notificationService.RequisitionCreated(requisition); return(requisition); }
public async Task <IActionResult> Answer([FromBody] RequestGroupAnswerModel model) { if (model == null) { return(ReturnError(ErrorCodes.IncomingPayloadIsMissing)); } try { var brokerId = User.TryGetBrokerId().Value; var apiUserId = User.UserId(); var user = await _apiUserService.GetBrokerUser(model.CallingUser, brokerId); var requestGroup = await _dbContext.RequestGroups.GetFullRequestGroupForApiWithBrokerAndOrderNumber(model.OrderGroupNumber, brokerId); if (requestGroup == null) { return(ReturnError(ErrorCodes.RequestGroupNotFound)); } if (!(requestGroup.Status == RequestStatus.Created || requestGroup.Status == RequestStatus.Received)) { return(ReturnError(ErrorCodes.RequestGroupNotInCorrectState)); } var mainInterpreterAnswer = _apiUserService.GetInterpreterModel(model.InterpreterAnswer, brokerId); InterpreterAnswerDto extraInterpreterAnswer = null; requestGroup.OrderGroup.Orders = await _dbContext.Orders.GetOrdersForOrderGroup(requestGroup.OrderGroup.OrderGroupId).ToListAsync(); if (requestGroup.HasExtraInterpreter) { extraInterpreterAnswer = _apiUserService.GetInterpreterModel(model.ExtraInterpreterAnswer, brokerId, false); } var now = _timeService.SwedenNow; if (requestGroup.Status == RequestStatus.Created) { await _requestService.AcknowledgeGroup(requestGroup, now, user?.Id ?? apiUserId, (user != null ? (int?)apiUserId : null)); } try { await _requestService.AcceptGroup( requestGroup, now, user?.Id ?? apiUserId, user != null?(int?)apiUserId : null, EnumHelper.GetEnumByCustomName <InterpreterLocation>(model.InterpreterLocation).Value, mainInterpreterAnswer, extraInterpreterAnswer, //Does not handle attachments yet. new List <RequestGroupAttachment>(), model.LatestAnswerTimeForCustomer, model.BrokerReferenceNumber ); await _dbContext.SaveChangesAsync(); //End of service return(Ok(new GroupAnswerResponse { InterpreterId = mainInterpreterAnswer.Interpreter.InterpreterBrokerId, ExtraInterpreterId = extraInterpreterAnswer?.Interpreter?.InterpreterBrokerId })); } catch (InvalidOperationException ex) { return(ReturnError(ErrorCodes.RequestNotCorrectlyAnswered, ex.Message)); } } catch (InvalidApiCallException ex) { return(ReturnError(ex.ErrorCode)); } catch (Exception ex) { _logger.LogError(ex, "Failed to handle request group answer"); return(ReturnError(ErrorCodes.UnspecifiedProblem)); } }
private async Task CallWebhook(int callId) { using TolkDbContext context = _options.GetContext(); var call = await context.OutboundWebHookCalls .Include(c => c.RecipientUser) .SingleOrDefaultAsync(e => e.OutboundWebHookCallId == callId && e.DeliveredAt == null && e.FailedTries < NumberOfTries); bool success = false; string errorMessage = string.Empty; try { if (call == null) { _logger.LogInformation("Call {callId} was in list to be handled, but seems to have been handled already.", call.OutboundWebHookCallId); } else { //Use short cache, so that each call to the same api user does not have to retrieve claims IEnumerable <IdentityUserClaim <int> > claims = (call.RecipientUser != null) ? await context.UserClaims.GetClaimsForUser(call.RecipientUser.Id) : null; using var requestMessage = new HttpRequestMessage(HttpMethod.Post, call.RecipientUrl); requestMessage.Headers.Add("X-Kammarkollegiet-InterpreterService-Event", call.NotificationType.GetCustomName()); requestMessage.Headers.Add("X-Kammarkollegiet-InterpreterService-Delivery", call.OutboundWebHookCallId.ToSwedishString()); string encryptedCallbackKey = claims?.SingleOrDefault(c => c.ClaimType == "CallbackApiKey")?.ClaimValue; if (!string.IsNullOrWhiteSpace(encryptedCallbackKey)) { requestMessage.Headers.Add("X-Kammarkollegiet-InterpreterService-ApiKey", EncryptHelper.Decrypt(encryptedCallbackKey, _options.PublicOrigin, call.RecipientUser.UserName)); } //Also add cert to call _logger.LogInformation("Calling web hook {recipientUrl} with message {callId}", call.RecipientUrl, call.OutboundWebHookCallId); using var content = new StringContent(call.Payload, Encoding.UTF8, "application/json"); requestMessage.Content = content; var response = await client.SendAsync(requestMessage); success = response.IsSuccessStatusCode; if (!success) { _logger.LogWarning("Call {callId} failed with the following status code: {statusCode}, try number {tries}", call.OutboundWebHookCallId, response.StatusCode, call.FailedTries + 1); errorMessage = $"Call {call.OutboundWebHookCallId} failed with the following status code: {response.StatusCode}, try number {call.FailedTries + 1}"; } } } catch (Exception ex) { _logger.LogError(ex, "Error on this side when calling web hook {callId}, try number {tries}", call.OutboundWebHookCallId, call.FailedTries + 1); errorMessage = $"Error on the \"{Constants.SystemName}\" server side for call {call.OutboundWebHookCallId}. Contact {_options.Support.FirstLineEmail} for more information."; } finally { if (success) { call.DeliveredAt = _clock.SwedenNow; } else { call.FailedTries++; FailedWebHookCall failedCall = new FailedWebHookCall { OutboundWebHookCallId = call.OutboundWebHookCallId, ErrorMessage = errorMessage, FailedAt = _clock.SwedenNow }; context.FailedWebHookCalls.Add(failedCall); if (call.FailedTries == NumberOfTries && call.NotificationType != Enums.NotificationType.ErrorNotification) { call.HasNotifiedFailure = false; } } call.IsHandling = false; await context.SaveChangesAsync(); } }
public async Task <bool> HandleOrderAgreementCreation() { if (!_dateCalculationService.IsWorkingDay(_clock.SwedenNow.UtcDateTime)) { return(false); } var startAtSettings = _cacheService.OrganisationNotificationSettings .Where(n => n.NotificationType == NotificationType.OrderAgreementCreated) .Select(n => new { n.ReceivingOrganisationId, n.StartUsingNotificationAt }).ToList(); var orderAgreementCustomerIds = _cacheService.CustomerSettings .Where(c => c.UsedCustomerSettingTypes.Contains(CustomerSettingType.UseOrderAgreements)) .Select(c => c.CustomerOrganisationId).ToList(); var occasionsEndedAtOrBefore = _dateCalculationService.GetDateForANumberOfWorkdaysAgo(_clock.SwedenNow.UtcDateTime, _options.WorkDaysGracePeriodBeforeOrderAgreementCreation); //1. find all nonhandled requests and requisitions for customers that is set as using order agreements // a. When requisition is Approved or Reviewed date is irrelevant foreach (int customerOrganisationId in orderAgreementCustomerIds) { var validUseFrom = startAtSettings.SingleOrDefault(s => s.ReceivingOrganisationId == customerOrganisationId)?.StartUsingNotificationAt ?? new DateTime(1900, 1, 1); //MOVE GETTER TO EXTENSIONS var baseInformationForOrderAgreementsToCreate = await _tolkDbContext.Requisitions.Where(r => (r.Status == RequisitionStatus.Approved || r.Status == RequisitionStatus.Reviewed) && r.OrderAgreementPayload == null && r.Request.Order.CustomerOrganisationId == customerOrganisationId && r.ProcessedAt > validUseFrom) .Select(r => new OrderAgreementIdentifierModel { RequisitionId = r.RequisitionId, RequestId = r.RequestId }) .ToListAsync(); //b.When requisition is AutomaticGeneratedFromCancelledOrder baseInformationForOrderAgreementsToCreate.AddRange(await _tolkDbContext.Requisitions.Where(r => r.Status == RequisitionStatus.AutomaticGeneratedFromCancelledOrder && r.OrderAgreementPayload == null && r.Request.Order.CustomerOrganisationId == customerOrganisationId && r.CreatedAt > validUseFrom) .Select(r => new OrderAgreementIdentifierModel { RequisitionId = r.RequisitionId, RequestId = r.RequestId }) .ToListAsync()); // c. x workdays after the occasion was ended // - If there is a requisition created, use that, but only if there is no order agreement created on the request before. baseInformationForOrderAgreementsToCreate.AddRange(await _tolkDbContext.Requisitions.Where(r => (r.Status == RequisitionStatus.Created) && r.Request.Order.CustomerOrganisationId == customerOrganisationId && r.OrderAgreementPayload == null && !r.Request.OrderAgreementPayloads.Any() && r.Request.Order.EndAt <occasionsEndedAtOrBefore && r.Request.Order.EndAt> validUseFrom ) .Select(r => new OrderAgreementIdentifierModel { RequisitionId = r.RequisitionId, RequestId = r.RequestId }) .ToListAsync()); //d. x workdays after the occasion was ended // - If there is a no requisition created, use request. baseInformationForOrderAgreementsToCreate.AddRange(await _tolkDbContext.Requests.Where(r => (r.Status == RequestStatus.Delivered || r.Status == RequestStatus.Approved) && r.Order.CustomerOrganisationId == customerOrganisationId && !r.OrderAgreementPayloads.Any() && !r.Requisitions.Any() && r.Order.EndAt <occasionsEndedAtOrBefore && r.Order.EndAt> validUseFrom ) .Select(r => new OrderAgreementIdentifierModel { RequestId = r.RequestId }) .ToListAsync()); _logger.LogInformation("For customer {customerOrganisationId}: Found {count} requests to create order agreements for: {requestIds}", customerOrganisationId, baseInformationForOrderAgreementsToCreate.Count, string.Join(", ", baseInformationForOrderAgreementsToCreate.Select(r => r.RequestId))); foreach (var entity in baseInformationForOrderAgreementsToCreate) { try { if (entity.RequisitionId.HasValue) { await CreateAndStoreOrderAgreementPayload(entity, CreateOrderAgreementFromRequisition); } else { await CreateAndStoreOrderAgreementPayload(entity, CreateOrderAgreementFromRequest); } await _tolkDbContext.SaveChangesAsync(); _logger.LogInformation("Processing completed order agreement for {requestId}.", entity.RequestId); } catch (Exception ex) { _logger.LogError(ex, "Failure processing order agreement creation for {requestId}", entity.RequestId); await SendErrorMail(nameof(HandleOrderAgreementCreation), ex); } } } return(true); }
public async Task SendEmails() { using TolkDbContext context = _options.GetContext(); var emailIds = await context.OutboundEmails .Where(e => e.DeliveredAt == null && !e.IsHandling) .Select(e => e.OutboundEmailId) .ToListAsync(); _logger.LogInformation("Found {count} emails to send: {emailIds}", emailIds.Count, string.Join(", ", emailIds)); if (emailIds.Any()) { try { var emails = context.OutboundEmails .Where(e => emailIds.Contains(e.OutboundEmailId) && e.IsHandling == false) .Select(c => c); await emails.ForEachAsync(c => c.IsHandling = true); await context.SaveChangesAsync(); using var client = new SmtpClient(); await client.ConnectAsync(_options.Smtp.Host, _options.Smtp.Port, _options.Smtp.UseAuthentication?SecureSocketOptions.StartTls : SecureSocketOptions.Auto); if (_options.Smtp.UseAuthentication) { await client.AuthenticateAsync(_options.Smtp.UserName, _options.Smtp.Password); } var from = new MailboxAddress(_senderPrepend + Constants.SystemName, _options.Smtp.FromAddress); foreach (var emailId in emailIds) { var email = await context.OutboundEmails .SingleOrDefaultAsync(e => e.OutboundEmailId == emailId && e.DeliveredAt == null); try { if (email == null) { _logger.LogInformation("Email {emailId} was in list to be sent, but now appears to have been sent.", emailId); } else { email.IsHandling = true; await context.SaveChangesAsync(); _logger.LogInformation("Sending email {emailId} to {recipient}", emailId, email.Recipient); await client.SendAsync(email.ToMimeKitMessage(from)); email.DeliveredAt = _clock.SwedenNow; } } catch (Exception ex) { _logger.LogError(ex, "Failure sending e-mail {emailId}"); } finally { email.IsHandling = false; await context.SaveChangesAsync(); } } } catch (Exception ex) { _logger.LogError(ex, "Something went wrong when sending emails"); } finally { //Making sure no emails are left hanging var emails = context.OutboundEmails .Where(e => emailIds.Contains(e.OutboundEmailId) && e.IsHandling == true) .Select(c => c); await emails.ForEachAsync(c => c.IsHandling = false); await context.SaveChangesAsync(); } } }
public async Task <IActionResult> Answer([FromBody] RequestAnswerModel model) { if (model == null) { return(ReturnError(ErrorCodes.IncomingPayloadIsMissing)); } try { var brokerId = User.TryGetBrokerId(); var apiUserId = User.UserId(); var order = await _apiOrderService.GetOrderAsync(model.OrderNumber, brokerId.Value); if (order.OrderGroupId != null) { return(ReturnError(ErrorCodes.RequestIsPartOfAGroup)); } var user = await _apiUserService.GetBrokerUser(model.CallingUser, brokerId.Value); var request = await _dbContext.Requests.GetActiveRequestForApiWithBrokerAndOrderNumber(model.OrderNumber, User.TryGetBrokerId().Value); if (request == null) { return(ReturnError(ErrorCodes.RequestNotFound)); } if (!request.IsToBeProcessedByBroker) { return(ReturnError(ErrorCodes.RequestNotInCorrectState)); } InterpreterBroker interpreter; try { interpreter = _apiUserService.GetInterpreter(new InterpreterDetailsModel(model.Interpreter), brokerId.Value); } catch (InvalidOperationException) { return(ReturnError(ErrorCodes.InterpreterOfficialIdAlreadySaved)); } //Does not handle Kammarkollegiets tolknummer if (interpreter == null) { //Possibly the interpreter should be added, if not found?? return(ReturnError(ErrorCodes.InterpreterNotFound)); } if (model.Location == null) { return(ReturnError(ErrorCodes.RequestNotCorrectlyAnswered, "Location was missing")); } if (model.CompetenceLevel == null) { return(ReturnError(ErrorCodes.RequestNotCorrectlyAnswered, "CompetenceLevel was missing")); } var now = _timeService.SwedenNow; if (request.Status == RequestStatus.Created) { _requestService.Acknowledge(request, now, user?.Id ?? apiUserId, user != null ? (int?)apiUserId : null); } try { await _requestService.Accept( request, now, user?.Id ?? apiUserId, user != null?(int?)apiUserId : null, interpreter, EnumHelper.GetEnumByCustomName <InterpreterLocation>(model.Location).Value, EnumHelper.GetEnumByCustomName <CompetenceAndSpecialistLevel>(model.CompetenceLevel).Value, model.RequirementAnswers == null?new List <OrderRequirementRequestAnswer>() : model.RequirementAnswers.Select(ra => new OrderRequirementRequestAnswer { Answer = ra.Answer, CanSatisfyRequirement = ra.CanMeetRequirement, OrderRequirementId = ra.RequirementId, }).ToList(), //Does not handle attachments yet. new List <RequestAttachment>(), model.ExpectedTravelCosts, model.ExpectedTravelCostInfo, model.LatestAnswerTimeForCustomer, model.BrokerReferenceNumber ); await _dbContext.SaveChangesAsync(); return(Ok(new AnswerResponse { InterpreterId = interpreter.InterpreterBrokerId })); } catch (InvalidOperationException ex) { return(ReturnError(ErrorCodes.RequestNotCorrectlyAnswered, ex.Message)); } catch (ArgumentNullException ex) { return(ReturnError(ErrorCodes.RequestNotCorrectlyAnswered, ex.Message)); } } catch (InvalidApiCallException ex) { return(ReturnError(ex.ErrorCode)); } }
public async Task ChangeInterpreter( Request request, DateTimeOffset changedAt, int userId, int?impersonatorId, InterpreterBroker interpreter, InterpreterLocation interpreterLocation, CompetenceAndSpecialistLevel competenceLevel, List <OrderRequirementRequestAnswer> requirementAnswers, IEnumerable <RequestAttachment> attachedFiles, decimal?expectedTravelCosts, string expectedTravelCostInfo, DateTimeOffset?latestAnswerTimeForCustomer, string brokerReferenceNumber ) { NullCheckHelper.ArgumentCheckNull(request, nameof(ChangeInterpreter), nameof(RequestService)); NullCheckHelper.ArgumentCheckNull(interpreter, nameof(ChangeInterpreter), nameof(RequestService)); CheckSetLatestAnswerTimeForCustomerValid(latestAnswerTimeForCustomer, nameof(ChangeInterpreter)); request.Order.Requirements = await _tolkDbContext.OrderRequirements.GetRequirementsForOrder(request.Order.OrderId).ToListAsync(); request.Order.InterpreterLocations = await _tolkDbContext.OrderInterpreterLocation.GetOrderedInterpreterLocationsForOrder(request.Order.OrderId).ToListAsync(); request.Order.CompetenceRequirements = await _tolkDbContext.OrderCompetenceRequirements.GetOrderedCompetenceRequirementsForOrder(request.Order.OrderId).ToListAsync(); if (interpreter.InterpreterBrokerId == await GetOtherInterpreterIdForSameOccasion(request) && !(interpreter.Interpreter?.IsProtected ?? false)) { throw new InvalidOperationException("Det går inte att tillsätta samma tolk som redan är tillsatt som extra tolk för samma tillfälle."); } Request newRequest = new Request(request.Ranking, request.ExpiresAt, changedAt, isChangeInterpreter: true, requestGroup: request.RequestGroup) { Order = request.Order, Status = RequestStatus.AcceptedNewInterpreterAppointed }; bool noNeedForUserAccept = await NoNeedForUserAccept(request, expectedTravelCosts); request.Order.Requests.Add(newRequest); VerificationResult?verificationResult = null; if (competenceLevel != CompetenceAndSpecialistLevel.OtherInterpreter && _tolkBaseOptions.Tellus.IsActivated) { //Only check if the selected level is other than other. verificationResult = await _verificationService.VerifyInterpreter(interpreter.OfficialInterpreterId, request.OrderId, competenceLevel); } newRequest.ReplaceInterpreter(changedAt, userId, impersonatorId, interpreter, interpreterLocation, competenceLevel, requirementAnswers, attachedFiles, _priceCalculationService.GetPrices(request, competenceLevel, expectedTravelCosts), noNeedForUserAccept, request, expectedTravelCostInfo, brokerReferenceNumber, verificationResult, latestAnswerTimeForCustomer ); // need requestid for the link await _tolkDbContext.SaveChangesAsync(); if (noNeedForUserAccept) { _notificationService.RequestChangedInterpreterAccepted(newRequest, InterpereterChangeAcceptOrigin.NoNeedForUserAccept); } else { _notificationService.RequestChangedInterpreter(newRequest); } request.Status = RequestStatus.InterpreterReplaced; }