예제 #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
        public async Task <UserLaneData> CreateLaneAsync(UserLaneData lane, Guid identUserId, string username)
        {
            _securityService.GuardAction(SecurityActions.Loadshop_Ui_Profile_Favorites_Add_Edit);

            ConvertStatesToAbbreviations(lane);
            ValidateUserLane(lane);
            var dbLane = await _context.UserLanes.SingleOrDefaultAsync(x => x.UserLaneId.ToString() == lane.UserLaneId);

            if (dbLane != null)
            {
                throw new Exception($"User Lane already exists");
            }
            if (lane.EquipmentIds?.Count() == 0)
            {
                throw new Exception("Must have at least on equipment type selected");
            }
            var user = await _context.Users.SingleOrDefaultAsync(x => x.IdentUserId == identUserId);

            if (user == null)
            {
                throw new Exception("Invalid userId");
            }

            lane.UserLaneId = Guid.NewGuid().ToString();
            lane.UserId     = user.UserId.ToString();
            dbLane          = _mapper.Map <UserLaneEntity>(lane);
            foreach (var laneNotification in lane.UserLaneMessageTypes)
            {
                if (laneNotification.Selected)
                {
                    var dbLaneNotification = _mapper.Map <UserLaneMessageTypeEntity>(laneNotification);
                    dbLane.UserLaneMessageTypes.Add(dbLaneNotification);
                }
            }
            if (dbLane.UserLaneEquipments == null)
            {
                dbLane.UserLaneEquipments = new List <UserLaneEquipmentEntity>();
            }

            foreach (var equipment in lane.EquipmentIds)
            {
                var e = new UserLaneEquipmentEntity()
                {
                    EquipmentId = equipment
                };
                dbLane.UserLaneEquipments.Add(e);
            }

            _context.UserLanes.Add(dbLane);
            await _context.SaveChangesAsync(username);

            return(await GetSavedLaneAsync(dbLane.UserLaneId));
        }
예제 #3
0
        public async Task <SaveSpecialInstructionResponse> CreateSpecialInstructionAsync(SpecialInstructionData instruction, string username)
        {
            var response = new SaveSpecialInstructionResponse();

            if (instruction == null)
            {
                response.ModelState.AddModelError($"{ErrorPrefix}", "Special Instruction is requred");
                return(response);
            }

            ConvertStatesToAbbreviations(instruction);
            if (instruction.SpecialInstructionId > 0)
            {
                response.ModelState.AddModelError($"{ErrorPrefix}", "Special Instruction should not have an Id assigned when creating.");
                return(response);
            }

            var validationErrorMessage = ValidateSpecialInstruction(instruction);

            if (!string.IsNullOrWhiteSpace(validationErrorMessage))
            {
                response.ModelState.AddModelError($"{ErrorPrefix}", validationErrorMessage);
                return(response);
            }

            instruction.Comments = _htmlSanitizer.Sanitize(instruction.Comments);

            var dbGroup = _mapper.Map <SpecialInstructionEntity>(instruction);

            //Map Equipment Types
            dbGroup.SpecialInstructionEquipment = new List <SpecialInstructionEquipmentEntity>();
            dbGroup.SpecialInstructionEquipment.MapList(instruction.SpecialInstructionEquipment, lcgeEntity => lcgeEntity.SpecialInstructionEquipmentId, lcgeData => lcgeData.SpecialInstructionEquipmentId, _mapper);

            GuardCustomer(dbGroup.CustomerId);

            var dup = await CheckIfDuplicateExists(dbGroup);

            if (dup)
            {
                response.ModelState.AddModelError($"{ErrorPrefix}", GetSpecialInstructionsDupErrorMessage(instruction));
                return(response);
            }

            _context.SpecialInstructions.Add(dbGroup);
            await _context.SaveChangesAsync(username);

            response.SpecialInstructionData = await GetSpecialInstructionAsync(dbGroup.SpecialInstructionId);

            return(response);
        }
예제 #4
0
        public async Task <GenericResponse <decimal?> > GetSmartSpotQuoteAsync(RecaptchaRequest <LoadshopSmartSpotQuoteRequest> request)
        {
            await _recaptchaService.ValidateToken(request);

            AssertConfig();

            var response = new GenericResponse <decimal?>();
            var awsModel = await MapFromLoadshopSmartSpotQuoteRequest(request.Data, response);

            if (!response.IsSuccess)
            {
                return(response);
            }

            response.Data = await RequestQuoteFromAWS(awsModel);

            _db.Add(new SmartSpotPriceQuoteLogEntity
            {
                SmartSpotPriceQuoteLogId = Guid.NewGuid(),
                Miles          = awsModel.DirectMiles,
                Weight         = awsModel.Weight,
                EquipmentId    = awsModel.EquipmentId,
                OrigState      = awsModel.OrigState,
                Orig3Zip       = awsModel.O3Zip,
                DestState      = awsModel.DestState,
                Dest3Zip       = awsModel.D3Zip,
                PkupDate       = awsModel.PkupDate,
                SmartSpotPrice = response.Data ?? 0,
                UserId         = _userContext.UserId
            });
            await _db.SaveChangesAsync(_userContext.UserName);

            return(response);
        }
예제 #5
0
        public async Task AddRatingQuestionAnswer(RatingQuestionAnswerData ratingQuestionAnswer, bool saveChanges = false)
        {
            if (ratingQuestionAnswer.RatingQuestionId == null ||
                ratingQuestionAnswer.RatingQuestionId == Guid.Empty)
            {
                throw new ValidationException("Answer must have a question");
            }

            if (!ratingQuestionAnswer.LoadId.HasValue)
            {
                throw new ValidationException("Answer must have a load attached");
            }

            if (!ratingQuestionAnswer.LoadClaimId.HasValue)
            {
                throw new ValidationException("Answer must be tied to a load claim");
            }

            var entity = _mapper.Map <RatingQuestionAnswerEntity>(ratingQuestionAnswer);

            _context.RatingQuestionAnswers.Add(entity);

            if (saveChanges)
            {
                await _context.SaveChangesAsync();
            }
        }
예제 #6
0
        public async Task UserAgreement()
        {
            // check if its the latest agreement
            var latest = await GetLatestAgreementDocument(AgreementDocumentTypes.TermsAndPrivacy);

            var user = await context.Users.FirstOrDefaultAsync(x => x.IdentUserId == userContext.UserId);

            // record user agreement
            var entity = new UserAgreementDocumentEntity()
            {
                UserId = user.UserId,
                AgreementDocumentId = latest.AgreementDocumentId,
                AgreementDtTm       = DateTime.Now,
                CreateBy            = userContext.UserName,
                LastChgBy           = userContext.UserName,
                CreateDtTm          = DateTime.Now,
                LastChgDtTm         = DateTime.Now
            };

            context.UserAgreements.Add(entity);
            await context.SaveChangesAsync();
        }
예제 #7
0
        /// <summary>
        /// Uploads a document to the KBX Document Service and stores metadata in Loadshop
        /// </summary>
        /// <param name="uploadPayload"></param>
        /// <returns></returns>
        public async Task <LoadDocumentMetadata> UploadDocument(LoadDocumentUploadData uploadPayload)
        {
            securityService.GuardAction(SecurityActions.Loadshop_Ui_Carrier_MyLoads_Documents_Attach);

            if (uploadPayload.LoadDocumentType == null || uploadPayload.LoadDocumentType.Id < 1)
            {
                throw new ValidationException("Invalid load document type");
            }

            var load = await context.Loads.AsNoTracking().FirstOrDefaultAsync(x => x.LoadId == uploadPayload.LoadId);

            if (load == null)
            {
                throw new ValidationException("Load not found");
            }

            var billingLoadId = await context.LoadTransactions.AsNoTracking()
                                .Include(x => x.Claim)
                                .Where(x => x.TransactionTypeId == TransactionTypes.Accepted)
                                .Where(x => x.LoadId == load.LoadId)
                                .Select(x => x.Claim.BillingLoadId)
                                .FirstOrDefaultAsync();

            // copy stream to request
            var stream = new FileMemoryStream();
            await uploadPayload.File.CopyToAsync(stream);

            // reset position to ensure http request sends payload
            stream.Position           = 0;
            stream.FileName           = uploadPayload.File.FileName;
            stream.ContentDisposition = uploadPayload.File.ContentDisposition;
            stream.ContentType        = uploadPayload.File.ContentType;

            // we hold all metadata in loadshop; however we will include some fields in case TOPS needs to query anything from there in the future
            var request = new DocumentService.SDK.Version.V1.Model.DocumentCreate()
            {
                Properties = new List <DocPropertyData>()
                {
                    new DocPropertyData()
                    {
                        PropertyValue = load.LoadId.ToString(),
                        PropertyName  = DocumentServiceConstants.Property_Name_LoadshopLoadId
                    },
                    new DocPropertyData()
                    {
                        PropertyValue = load.PlatformPlusLoadId?.ToString(),
                        PropertyName  = DocumentServiceConstants.Property_Name_PlatformPlusLoadId
                    },
                    new DocPropertyData()
                    {
                        PropertyValue = load.ReferenceLoadId?.ToString(),
                        PropertyName  = DocumentServiceConstants.Property_Name_ReferenceLoadId
                    },
                    new DocPropertyData()
                    {
                        PropertyValue = billingLoadId,
                        PropertyName  = DocumentServiceConstants.Property_Name_BillingLoadId
                    }
                },
                DocTypeId       = uploadPayload.LoadDocumentType.Id,
                CreatedBy       = userContext.UserName,
                CreatedDateTime = DateTime.Now,
                DocumentFile    = stream
            };

            try
            {
                // upload file to document API
                var uploadResult = await documentApiClient.CreateDocument(request);

                if (uploadResult.Status.Equals("Error", StringComparison.CurrentCultureIgnoreCase))
                {
                    throw new Exception($"Error while upload document to Document Service: {uploadResult.Result}");
                }

                var entity = new LoadDocumentEntity()
                {
                    LoadDocumentId              = Guid.NewGuid(),
                    DocumentServiceDocHeaderId  = uploadResult.ResultData.DocHeaderId.Value,
                    DocumentServiceDocContentId = uploadResult.ResultData.DocContentId.Value,
                    DocumentServiceDocumentType = uploadPayload.LoadDocumentType.Id,
                    FileName    = uploadPayload.File.FileName,
                    Comment     = uploadPayload.Comment,
                    LoadId      = load.LoadId,
                    CreateBy    = userContext.UserName,
                    CreateDtTm  = DateTime.Now,
                    LastChgBy   = userContext.UserName,
                    LastChgDtTm = DateTime.Now
                };

                // add the new entity and in order for the DB to generate the doc id, use that to pass to the document service
                context.LoadDocuments.Add(entity);
                await context.SaveChangesAsync();

                return(mapper.Map <LoadDocumentMetadata>(entity));
            }
            catch (Exception e)
            {
                // if any errors occured, we dont want to show the record in loadshop, so remove the attachment record and return error
                logger.LogError($"Error while uploading document: {e.Message}", e);
            }
            return(null);
        }
예제 #8
0
        public async Task <BaseServiceResponse> AddInTransitStatus(LoadStatusInTransitData inTransitData)
        {
            await _securityService.GuardActionAsync(SecurityActions.Loadshop_Ui_My_Loads_Status_Update);

            var(load, scac) = await GetLoadAndScac(inTransitData.LoadId, includeStops : false);

            //Adjust the time if it's close to current
            bool inFuture;

            (inTransitData.LocationTime, inFuture) = AdjustLocationTime(inTransitData.LocationTime, inTransitData.Latitude, inTransitData.Longitude);

            var response = new BaseServiceResponse();

            if (inTransitData.LocationTime == null)
            {
                response.AddError($"urn:root:{nameof(LoadStatusInTransitData.LocationTime)}", "Status Date/Time is required");
            }
            else if (inFuture)
            {
                response.AddError($"urn:root:{nameof(LoadStatusInTransitData.LocationTime)}", "Status Date/Time must be in the past");
            }

            if (inTransitData.Latitude == null)
            {
                response.AddError($"urn:root:{nameof(LoadStatusInTransitData.Latitude)}", "Location is required");
            }
            else if (inTransitData.Longitude == null)
            {
                response.AddError($"urn:root:{nameof(LoadStatusInTransitData.Longitude)}", "Location is required");
            }

            if (!response.IsSuccess)
            {
                return(response);
            }

            var currentTime = DateTimeOffset.UtcNow;
            var lst         = new LoadStatusTransactionEntity
            {
                LoadId          = load.LoadId,
                TransactionDtTm = currentTime.DateTime//this may not be needed anymore if we can send the MessageTime
            };

            var eventResponse = await _carrierWebAPIService.Send(new LoadStatusEvent <InTransitLoadData>
            {
                MessageType = "LoadLocation",
                MessageId   = Guid.NewGuid(),
                MessageTime = DateTimeOffset.Now,
                ApiVersion  = "1.1",
                Payload     = new InTransitLoadData
                {
                    Loads = new InTransitEventData[]
                    {
                        new InTransitEventData
                        {
                            LoadNumber   = load.LatestLoadTransaction.Claim.BillingLoadId ?? load.PlatformPlusLoadId ?? load.ReferenceLoadId,
                            Latitude     = inTransitData.Latitude.Value,
                            Longitude    = inTransitData.Longitude.Value,
                            LocationTime = inTransitData.LocationTime?.ToString("yyyy-MM-ddTHH:mm:ss"),
                            IsLocalTime  = true, //Always true if in local status time
                            Scac         = scac
                        }
                    }
                }
            });

            lst.MessageId   = eventResponse.MessageId;
            lst.MessageTime = eventResponse.MessageTime;
            _context.LoadStatusTransactions.Add(lst);
            await _context.SaveChangesAsync(_userContext.UserName);

            return(response);
        }
        public async Task <UserProfileData> GetUserProfileAsync(Guid identUserId)
        {
            var user = await _context.Users
                       .Include(u => u.PrimaryScacEntity.Carrier)
                       .Include(x => x.UserNotifications)
                       .ThenInclude(x => x.MessageType)
                       .Include(u => u.UserShippers)
                       .ThenInclude(userShipper => userShipper.Customer)
                       .Include(u => u.PrimaryCustomer)
                       .SingleOrDefaultAsync(x => x.IdentUserId == identUserId);

            if (user == null)
            {
                // Throw exception so we can catch it and add the user
                throw new EntityNotFoundException($"UserProfile not found for id {identUserId}");
            }

            var userProfile = _mapper.Map <UserProfileData>(user);

            // Add missing notification types the user does not have set yet
            var messageTypes = await _context.MessageTypes.Where(x => x.MessageTypeId != MessageTypeConstants.Email_SingleCarrierScac).ToListAsync();

            foreach (var messageType in messageTypes)
            {
                var userMessageyTypeExists = userProfile.UserNotifications.Any(x => x.MessageTypeId.Equals(messageType.MessageTypeId, StringComparison.OrdinalIgnoreCase));
                if (userMessageyTypeExists)
                {
                    continue;
                }

                if (messageType.MessageTypeId.Equals(MessageTypeConstants.Email))
                {
                    // add a record using the user's identity email as a default
                    var entity = new UserNotificationEntity()
                    {
                        MessageTypeId       = MessageTypeConstants.Email,
                        UserId              = user.UserId,
                        IsDefault           = true,
                        NotificationValue   = _userContext.Email,
                        CreateBy            = user.Username,
                        CreateDtTm          = DateTime.Now,
                        LastChgBy           = user.Username,
                        LastChgDtTm         = DateTime.Now,
                        NotificationEnabled = true
                    };
                    _context.UserNotifications.Add(entity);
                    await _context.SaveChangesAsync();

                    userProfile.UserNotifications.Add(_mapper.Map <UserNotificationData>(entity));
                }
                else
                {
                    userProfile.UserNotifications.Add(_mapper.Map <UserNotificationData>(messageType));
                }
            }

            // check if the user has agreed to the latest terms and privacy
            userProfile.HasAgreedToTerms = await _agreementDocumentService.HasUserAgreedToLatestTermsAndPrivacy(user.UserId);

            SetSecurityProperties(user, userProfile);
            userProfile.CarrierVisibilityTypes = _commonService.GetCarrierVisibilityTypes(user.Username, user.PrimaryScacEntity?.CarrierId);

            return(userProfile);
        }