示例#1
0
        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));
        }
示例#2
0
        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);
        }
示例#3
0
        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;
                    }
                }
            }
        }
示例#4
0
        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;
                }
            }
        }
示例#5
0
 public MockDbBuilder WithLoadTransaction(LoadTransactionEntity transaction)
 {
     _loadTransactions.Add(transaction);
     return(this);
 }
示例#6
0
        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);
        }