public MockDbBuilder WithLoadCarrierScac(LoadCarrierScacEntity item) { _loadCarrierScacs.Add(item); 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); }