public async Task <ShippingLoadData> RemoveLoad(Guid loadId, string username) { _securityService.GuardAction(SecurityActions.Loadshop_Ui_Shopit_Load_Manual_Remove); var updateLoad = await _context.Loads .Include(x => x.LoadTransactions) .Include(x => x.CarrierScacs) .Include(x => x.PostedLoadCarrierGroups) .SingleOrDefaultAsync(x => x.LoadId == loadId); if (updateLoad == null) { throw new Exception("Load not found"); } if (!AuthorizedForCustomer(updateLoad.CustomerId)) { throw new UnauthorizedAccessException($"User is not authorized for customer: {updateLoad.CustomerId}"); } if (updateLoad.LoadTransactions == null || updateLoad.LoadTransactions.Count == 0) { throw new Exception($"Load may not be removed - Load {loadId} has no transactions"); } var loadTrans = updateLoad.LoadTransactions .OrderByDescending(x => x.CreateDtTm) .ToList(); if (!_transToProcess.Contains(loadTrans[0].TransactionTypeId)) { throw new Exception("Load may not be removed - not an active Load"); } string initialState = GetLoadInitialState(loadTrans); if (string.IsNullOrWhiteSpace(initialState) || !_initialTransStates.Contains(loadTrans[0].TransactionTypeId)) { var transaction = new LoadTransactionEntity() { LoadId = updateLoad.LoadId, TransactionTypeId = string.IsNullOrWhiteSpace(initialState) ? TransactionTypes.PendingAdd : initialState, CreateDtTm = _dateTime.Now // to support unit testing }; updateLoad.LoadTransactions.Add(transaction); /** * https://kbxltrans.visualstudio.com/Suite/_workitems/edit/38578 * Delete all LoadCarrierScacs associated with this Load */ _context.LoadCarrierScacs.RemoveRange(updateLoad.CarrierScacs); _context.PostedLoadCarrierGroups.RemoveRange(updateLoad.PostedLoadCarrierGroups); _context.Loads.Update(updateLoad); await _context.SaveChangesAsync(username); } return(_mapper.Map <ShippingLoadData>(updateLoad)); }
private void AddLoadTransaction(LoadEntity updateLoad, string transactionType) { var transaction = new LoadTransactionEntity() { LoadId = updateLoad.LoadId, TransactionTypeId = transactionType, CreateDtTm = _dateTime.Now // to support unit testing }; updateLoad.LoadTransactions.Add(transaction); _context.Loads.Update(updateLoad); }
private void CheckLoadsForTopsToGoVisibilityData(LoadViewData load, LoadTransactionEntity lte, string token, ref string topsToGoErrors) { if (string.IsNullOrWhiteSpace(load.BillingLoadDisplay)) { return; } const string mediaType = "application/json"; _client.DefaultRequestHeaders.Clear(); _client.DefaultRequestHeaders.Accept.Clear(); _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaType)); _client.DefaultRequestHeaders.Add("Authorization", token); var url = string.Format(_config.GetValue <string>("MobileApiAddress") + "t2g/api/sms/loadinfo/{0}", load.BillingLoadDisplay); var responseMessage = _client.GetAsync(url, default(CancellationToken)).Result; var responseString = responseMessage.Content.ReadAsStringAsync().Result.Replace("\"e\":", "Errors:").Replace("\"d\":", "Data:").Replace("\"s\":", "Success:"); var response = JsonConvert.DeserializeObject <ResponseMessage <List <TopsToGoDetail> > >(responseString); if (!responseMessage.IsSuccessStatusCode || response == null || response.Success == false || response.Errors.Count > 0) { topsToGoErrors = $"TopsToGo data retrieval failed using endpoint, {url}, for load: {load.ReferenceLoadDisplay}"; if (response != null && response.Errors.Count > 0) { var errors = response.Errors.Aggregate(new StringBuilder(), (s, r) => s.AppendLine(r.Message)).ToString(); topsToGoErrors += " - " + errors; } return; } if (response.Data.Count > 0) { var topsToGoDetailInfo = response.Data[0]; if (topsToGoDetailInfo.AccessExpiredUtc > DateTime.UtcNow) { if (string.IsNullOrWhiteSpace(lte.Claim.VisibilityPhoneNumber) || (lte.Claim.VisibilityChgDtTm.HasValue && lte.Claim.VisibilityChgDtTm.Value < topsToGoDetailInfo.SendUtc.ToLocalTime())) { load.ShowVisibilityWarning = false; load.MobileExternallyEntered = true; load.VisibilityChgDtTm = topsToGoDetailInfo.SendUtc.ToLocalTime(); lte.Claim.MobileExternallyEntered = load.MobileExternallyEntered; lte.Claim.VisibilityChgDtTm = load.VisibilityChgDtTm; } } } }
private void CheckLoadsForProject44VisibilityData(LoadViewData load, LoadTransactionEntity lte, string token, ref string project44Errors) { if (string.IsNullOrWhiteSpace(load.BillingLoadDisplay)) { return; } const string mediaType = "application/json"; string url = _config.GetValue <string>("VisibilityApiAddress") + "asset/find-asset"; var formData = JsonConvert.SerializeObject(new Project44AssetInfo { LoadId = load.BillingLoadId }); var content = new StringContent(formData, Encoding.UTF8, mediaType); _client.DefaultRequestHeaders.Clear(); _client.DefaultRequestHeaders.Add("Authorization", token); var responseMessage = _client.PostAsync(url, content, default(CancellationToken)).Result; var responseString = responseMessage.Content.ReadAsStringAsync().Result; if (!responseMessage.IsSuccessStatusCode) { project44Errors = $"Project44 data retrieval failed using endpoint, {url}, for load: {load.ReferenceLoadDisplay}. Reason: {responseMessage.ReasonPhrase}"; return; } var project44AssetInfo = JsonConvert.DeserializeObject <Project44AssetInfo>(responseString); if (!string.IsNullOrWhiteSpace(project44AssetInfo.AssetId)) { if (string.IsNullOrWhiteSpace(lte.Claim.VisibilityTruckNumber) || (lte.Claim.VisibilityTruckNumber != project44AssetInfo.AssetId && lte.Claim.VisibilityChgDtTm < project44AssetInfo.AssetLastChgDtTm)) { load.ShowVisibilityWarning = false; load.VisibilityTruckNumber = project44AssetInfo.AssetId; load.VisibilityChgDtTm = project44AssetInfo.AssetLastChgDtTm; lte.Claim.VisibilityTruckNumber = load.VisibilityTruckNumber; lte.Claim.VisibilityChgDtTm = load.VisibilityChgDtTm; } } }
public MockDbBuilder WithLoadTransaction(LoadTransactionEntity transaction) { _loadTransactions.Add(transaction); return(this); }
public async Task <PostLoadsResponse> PostLoadsAsync(PostLoadsRequest request) { _securityService.GuardAction(SecurityActions.Loadshop_Ui_Shopit_Load_Post); var response = new PostLoadsResponse(); var userPrimaryCustomerId = _context.Users.SingleOrDefault(u => u.IdentUserId == _userContext.UserId)?.PrimaryCustomerId; // Throw exceptions for non-user errors that the user cannot solve if (request == null) { throw new ArgumentNullException(nameof(request)); } if (!userPrimaryCustomerId.HasValue || userPrimaryCustomerId == Guid.Empty) { throw new ArgumentNullException(nameof(userPrimaryCustomerId)); } if (!AuthorizedForCustomer(userPrimaryCustomerId.Value)) { throw new UnauthorizedAccessException($"User is not authorized for customer: {userPrimaryCustomerId}"); } if (string.IsNullOrWhiteSpace(request.CurrentUsername)) { throw new ArgumentNullException(nameof(request.CurrentUsername)); } if (request.Loads == null || request.Loads.Count <= 0) { response.ModelState.AddModelError($"urn:root", "PostLoads operation requires loads to be posted"); return(response); } var loadIds = request.Loads.Select(x => x.LoadId).ToList(); var dbLoads = await _context.Loads .Include(x => x.LoadTransactions) .Include(x => x.LoadStops) .Include(x => x.CarrierScacs) .Include(x => x.Customer) .Include(x => x.Equipment) .Include(x => x.PostedLoadCarrierGroups) .Include(x => x.LoadServiceTypes) .Where(x => loadIds.Contains(x.LoadId)) .ToListAsync(); var serviceTypes = await _context.ServiceTypes.AsNoTracking().ToListAsync(); //Verify submitting loads for only one customer at a time var groupedLoads = dbLoads.GroupBy(l => l.CustomerId); if (groupedLoads.Count() > 1) { throw new Exception("Cannot post loads from multiple shippers"); } var contractedScacs = _securityService.GetCustomerContractedScacsByPrimaryCustomer(); var bookedTransTypes = new[] { TransactionTypes.Accepted, TransactionTypes.Pending, TransactionTypes.SentToShipperTender, TransactionTypes.PreTender }; foreach (var load in request.Loads) { var dbLoad = dbLoads.FirstOrDefault(x => x.LoadId == load.LoadId); response = ValidatePostedLoad(response, dbLoad, load, bookedTransTypes, serviceTypes); var originalLoadHistory = _mapper.Map <LoadHistoryEntity>(dbLoad); var eligibleScacs = new List <string>(); if (load.CarrierIds.Count > 0) { var carrierScacGroups = contractedScacs .Where(x => load.CarrierIds.Contains(x.CarrierId)) .Where(Utilities.QueryFilters.GetActiveCarrierScacDataFilter(request.RequestTime.Date)) .GroupBy(x => x.CarrierId) .ToList(); var dbCarriers = carrierScacGroups.Select(x => x.Key).ToList(); var missingCarriers = load.CarrierIds.Except(dbCarriers); if (missingCarriers.Any()) { response.ModelState.AddModelError($"urn:load:{load.LoadId}", $"The following carriers have no eligible SCACs defined: {string.Join(", ", missingCarriers)}"); } eligibleScacs = carrierScacGroups.SelectMany(x => x.Select(y => y.Scac)).ToList(); } else { // When no Carriers are provided, we assume that we're posting to ALL eligible carriers for the customer // Right now, TOPS is the only customer, so all Carriers and Scacs are eligible for TOPS, but in the // future we'll require some lookup here to determine which Carriers are associated with the customer eligibleScacs = contractedScacs .Where(x => x.EffectiveDate <= request.RequestTime && (x.ExpirationDate == null || x.ExpirationDate > request.RequestTime)) .Select(x => x.Scac) .ToList(); if (!eligibleScacs.Any()) { response.ModelState.AddModelError($"urn:load:{load.LoadId}", $"No eligible SCACs found"); } } /** * The model state applies to the entire request, so we have to check that errors related to * this load are helping to cause the invalid model state before we skip processing this load. * If this load has no errors, then continue processing it successfully. */ if (!response.ModelState.IsValid && response.ModelState.Keys.Any(x => x.Contains(load.LoadId.ToString()))) { continue; } var postedCarrierGroupEntities = load.CarrierGroupIds.Select(groupId => new PostedLoadCarrierGroupEntity() { LoadId = dbLoad.LoadId, LoadCarrierGroupId = groupId, PostedLoadCarrierGroupId = Guid.NewGuid() }); dbLoad.PostedLoadCarrierGroups.Clear(); dbLoad.PostedLoadCarrierGroups.AddRange(postedCarrierGroupEntities); dbLoad.Comments = load.Comments; dbLoad.Commodity = load.Commodity; dbLoad.LineHaulRate = load.LineHaulRate; dbLoad.FuelRate = load.ShippersFSC; dbLoad.SmartSpotRate = load.SmartSpotRate ?? dbLoad.SmartSpotRate; dbLoad.DATGuardRate = load.DATGuardRate ?? dbLoad.DATGuardRate; dbLoad.MachineLearningRate = load.MachineLearningRate ?? dbLoad.MachineLearningRate; dbLoad.AllCarriersPosted = load.AllCarriersPosted; // remove any existing dbLoad.LoadServiceTypes?.Clear(); if (load.ServiceTypeIds != null && load.ServiceTypeIds.Any()) { if (dbLoad.LoadServiceTypes == null) { dbLoad.LoadServiceTypes = new List <LoadServiceTypeEntity>(); } var loadServiceTypes = load.ServiceTypeIds.Select(x => new LoadServiceTypeEntity() { LoadId = load.LoadId, ServiceTypeId = x }).ToList(); dbLoad.LoadServiceTypes.AddRange(loadServiceTypes); } // Delete all existing LoadCarrierScacs for this load, before inserting new ones var existingCarrierScacs = _context.LoadCarrierScacs.Where(x => x.LoadId == dbLoad.LoadId).ToList(); if (existingCarrierScacs.Count > 0) { _context.LoadCarrierScacs.RemoveRange(existingCarrierScacs); } var carrierScacs = new List <LoadCarrierScacEntity>(); foreach (var scac in eligibleScacs) { var carrierScac = new LoadCarrierScacEntity { LoadId = dbLoad.LoadId, Scac = scac, CreateBy = request.CurrentUsername, CreateDtTm = request.RequestTime, LastChgBy = request.CurrentUsername, LastChgDtTm = request.RequestTime }; carrierScacs.Add(carrierScac); } _context.LoadCarrierScacs.AddRange(carrierScacs); response.LoadCarrierScacs.AddRange(carrierScacs); var postedTx = new LoadTransactionEntity { LoadId = dbLoad.LoadId, TransactionTypeId = TransactionTypes.Posted, CreateBy = request.CurrentUsername, CreateDtTm = request.RequestTime, LastChgBy = request.CurrentUsername, LastChgDtTm = request.RequestTime }; _context.LoadTransactions.Add(postedTx); var newLoadHistory = _mapper.Map <LoadHistoryEntity>(dbLoad); if (_serviceUtilities.HasLoadChanged(originalLoadHistory, newLoadHistory)) { _context.LoadHistories.Add(newLoadHistory); } await _context.SaveChangesAsync(request.CurrentUsername); response.PostedLoads.Add(_mapper.Map <ShippingLoadData>(dbLoad)); } return(response); }