public GenericActionstepRequest(TokenSetQuery tokenSetQuery, string relativeResourcePath, HttpMethod httpMethod, object jsonPayload = null)
 {
     TokenSetQuery        = tokenSetQuery;
     RelativeResourcePath = relativeResourcePath;
     HttpMethod           = httpMethod;
     JsonPayload          = jsonPayload;
 }
예제 #2
0
        public Task Remove(TokenSetQuery tokenSetQuery)
        {
            var itemToRemove = TokenSets.SingleOrDefault(t => t.UserId == tokenSetQuery.UserId && t.OrgKey == tokenSetQuery.OrgKey);

            if (itemToRemove != null)
            {
                TokenSets.Remove(itemToRemove);
            }

            return(Task.CompletedTask);
        }
예제 #3
0
            public async Task <GetActionstepActionsResponse> Handle(GetActionstepActionsCommand command, CancellationToken cancellationToken)
            {
                if (command is null)
                {
                    throw new System.ArgumentNullException(nameof(command));
                }

                var tokenSetQuery = new TokenSetQuery(command.AuthenticatedUser?.Id, command.ActionstepOrgKey);
                var apiParams     = string.Join(",", command.MatterIds);

                return(await _actionstepService.Handle <GetActionstepActionsResponse>(new GenericActionstepRequest(tokenSetQuery, $"rest/actions/{apiParams}", HttpMethod.Get)));
            }
        public async Task <ListDisbursementsResponse> Handle(CreateDisbursementsCommand request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            // Get Actionstep matter info
            var tokenSetQuery = new TokenSetQuery(request.AuthenticatedUser?.Id, request.ActionstepOrg);

            var createDisbursementsRequest = new CreateDisbursementsRequest()
            {
                TokenSetQuery = tokenSetQuery
            };

            createDisbursementsRequest.Disbursements.Add(new Disbursement()
            {
                Date                    = LocalDate.FromDateTime(DateTime.Now),
                Description             = "Premium",
                ImportExternalReference = request.PolicyNumber,
                Quantity                = 1,
                UnitPrice               = request.FirstTitlePrice.Premium,
                UnitPriceIncludesTax    = false,
                Links                   =
                {
                    Action  = 23,
                    TaxCode = 7     // S 10.0
                }
            });

            createDisbursementsRequest.Disbursements.Add(new Disbursement()
            {
                Date                    = LocalDate.FromDateTime(DateTime.Now),
                Description             = "StampDuty",
                ImportExternalReference = request.PolicyNumber,
                Quantity                = 1,
                UnitPrice               = request.FirstTitlePrice.StampDuty,
                UnitPriceIncludesTax    = false,
                Links                   =
                {
                    Action  = 23,
                    TaxCode = 8     // BAS Excluded
                }
            });

            var response = await _actionstepService.Handle <ListDisbursementsResponse>(createDisbursementsRequest);

            return(response);
        }
예제 #5
0
            public async Task <ActionstepMatterValidationResult> Handle(ValidateActionstepMatterCommand request, CancellationToken cancellationToken)
            {
                if (request is null)
                {
                    throw new ArgumentNullException(nameof(request));
                }
                _validator.ValidateAndThrow(request);

                var  tokenSetQuery = new TokenSetQuery(request.ActionstepUserId, request.ActionstepOrgKey);
                int? matterId      = null;
                bool isMapped      = false;

                // First check for mapping to see if this GlobalX Matter reference has been mapped to another Actionstep Matter ID
                var gxMapping = await _wCADbContext.GlobalXMatterMappings.FindAsync(request.ActionstepOrgKey, request.MatterId);

                if (!(gxMapping is null))
                {
                    matterId = gxMapping.ActionstepMatterId;
                    isMapped = true;
                }
예제 #6
0
            public async Task <ActionstepDocument> Handle(ActionstepSavePDFCommand message, CancellationToken token)
            {
                if (message is null)
                {
                    throw new ArgumentNullException(nameof(message));
                }

                ValidationResult result = _validator.Validate(message);

                if (!result.IsValid)
                {
                    throw new ValidationException("Invalid input.", result.Errors);
                }

                TokenSetQuery tokenSetQuery = new TokenSetQuery(message.AuthenticatedUser?.Id, message.OrgKey);

                var actionResponse = await _actionstepService.Handle <GetActionResponse>(new GetActionRequest(tokenSetQuery, message.MatterId));

                string fileName = $"{message.MatterId}_Settlement Statement_{DateTime.UtcNow.ToString("_yyyy-MM-dd hh-mm", CultureInfo.InvariantCulture)}.pdf";

                UploadFileResponse file = await _actionstepService.UploadFile(tokenSetQuery, fileName, message.FilePath);

                #region Check Documents Folder
                ActionFolder             actionFolder   = new ActionFolder(actionResponse.Action.Id);
                GetActionFolderRequest   folderRequest  = new GetActionFolderRequest(tokenSetQuery, actionFolder);
                ListActionFolderResponse folderResponse = await _actionstepService.Handle <ListActionFolderResponse>(folderRequest);

                var parentFolderId = folderResponse.ActionFolders.Where(af => af.Name == "Documents").Select(af => af.Id).FirstOrDefault();
                #endregion

                ActionDocument            document    = new ActionDocument(actionResponse.Action.Id, fileName, file, parentFolderId);
                SaveActionDocumentRequest saveRequest = new SaveActionDocumentRequest(tokenSetQuery, document);

                var saveResponse = await _actionstepService.Handle <SaveActionDocumentResponse>(saveRequest);

                var fileUrl = new Uri(saveResponse.ActionDocument.SharepointUrl);

                string documentUrl = $"https://{fileUrl.Host}/mym/asfw/workflow/documents/views/action_id/{actionResponse.Action.Id}#mode=browse&view=list&folder={parentFolderId}&drive=DL";

                return(new ActionstepDocument(fileUrl, fileName, new Uri(documentUrl)));
            }
예제 #7
0
        public Task <TokenSet> GetTokenSet(TokenSetQuery tokenSetQuery)
        {
            // Use a separate scope for each method call to prevent DBContext caching
            using var scope     = _serviceScopeFactory.CreateScope();
            using var dbContext = scope.ServiceProvider.GetService <WCADbContext>();

            if (tokenSetQuery is null)
            {
                throw new ArgumentNullException(nameof(tokenSetQuery));
            }

            var userToGetCredentialsFor = tokenSetQuery.UserId;

            // Check to see if there is a substitute
            var substitute = dbContext
                             .ActionstepCredentialSubstitutions
                             .AsNoTracking()
                             .Include(e => e.SubstituteWithOwner)
                             .SingleOrDefault(e => e.ForOwner.Id == tokenSetQuery.UserId);

            if (substitute != null)
            {
                userToGetCredentialsFor = substitute.SubstituteWithOwner.Id;
            }

            var tokenSet = dbContext
                           .ActionstepCredentials
                           .AsNoTracking()
                           .Include(c => c.Owner)
                           .Include(c => c.ActionstepOrg)
                           .ForOwnerAndOrg(userToGetCredentialsFor, tokenSetQuery.OrgKey)
                           .SingleOrDefault();

            if (tokenSet == null)
            {
                return(Task.FromResult <TokenSet>(null));
            }

            return(Task.FromResult(tokenSet.ToTokenSet()));
        }
예제 #8
0
        /// <summary>
        /// Does NOT use substitution.
        /// </summary>
        /// <param name="tokenSetQuery"></param>
        /// <returns></returns>
        public async Task Remove(TokenSetQuery tokenSetQuery)
        {
            // Use a separate scope for each method call to prevent DBContext caching
            using var scope     = _serviceScopeFactory.CreateScope();
            using var dbContext = scope.ServiceProvider.GetService <WCADbContext>();

            if (tokenSetQuery is null)
            {
                throw new ArgumentNullException(nameof(tokenSetQuery));
            }

            var itemToRemove = dbContext
                               .ActionstepCredentials
                               .ForOwnerAndOrg(tokenSetQuery.UserId, tokenSetQuery.OrgKey)
                               .SingleOrDefault();

            if (itemToRemove != null)
            {
                dbContext.ActionstepCredentials.Remove(itemToRemove);
                await dbContext.SaveChangesAsync();
            }
        }
예제 #9
0
        public async Task <FTAttachment> Handle(SavePolicyPDFToActionstepCommand request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            // Get Actionstep matter info
            var tokenSetQuery = new TokenSetQuery(request.AuthenticatedUser?.Id, request.ActionstepOrg);

            var actionResponse = await _actionstepService.Handle <GetActionResponse>(new GetActionRequest(tokenSetQuery, request.MatterId));

            UploadFileResponse file = await _actionstepService.UploadFile(tokenSetQuery, request.FileName, request.FilePath);

            #region Check Documents Folder
            ActionFolder             actionFolder   = new ActionFolder(actionResponse.Action.Id);
            GetActionFolderRequest   folderRequest  = new GetActionFolderRequest(tokenSetQuery, actionFolder);
            ListActionFolderResponse folderResponse = await _actionstepService.Handle <ListActionFolderResponse>(folderRequest);

            var parentFolderId = folderResponse.ActionFolders.Where(af => af.Name == "Documents").Select(af => af.Id).FirstOrDefault();
            #endregion

            ActionDocument            document    = new ActionDocument(actionResponse.Action.Id, request.FileName, file, parentFolderId);
            SaveActionDocumentRequest saveRequest = new SaveActionDocumentRequest(tokenSetQuery, document);

            var saveResponse = await _actionstepService.Handle <SaveActionDocumentResponse>(saveRequest);

            var fileUrl = new Uri(saveResponse.ActionDocument.SharepointUrl);

            string documentUrl = $"https://{fileUrl.Host}/mym/asfw/workflow/documents/views/action_id/{actionResponse.Action.Id}#mode=browse&view=list&folder={parentFolderId}&drive=DL";

            return(new FTAttachment()
            {
                FileName = request.FileName,
                FileUrl = documentUrl
            });
        }
            public async Task <SendMappingsToInfoTrack.SendMappingsToInfoTrackCommand> Handle(GetMappingDataFromActionstepQuery message, CancellationToken token)
            {
                if (message is null)
                {
                    throw new ArgumentNullException(nameof(message));
                }

                telemetryLogger.TrackTrace("GetMappingDataFromActionstep handler called", WCASeverityLevel.Information, null);
                try
                {
                    ValidationResult validationResult = validator.Validate(message);
                    if (!validationResult.IsValid)
                    {
                        throw new ValidationException("Invalid input.", validationResult.Errors);
                    }

                    // If we get this far, we know that the user has permisisons to the Actionstep org.
                    // We must only get InfoTrack credentials if the user
                    var infoTrackCredentials = await infoTrackCredentialRepository.FindCredential(message.ActionstepOrgKey);

                    if (infoTrackCredentials == null)
                    {
                        throw new InfoTrackCredentialsNotFoundException(message.ActionstepOrgKey, message.AuthenticatedUser);
                    }

                    var tokenSetQuery = new TokenSetQuery(message.AuthenticatedUser?.Id, message.ActionstepOrgKey);

                    // Response 1 Get Action Participants
                    var allParticipants = await actionstepService.Handle <ActionParticipantsResponse>(
                        new GenericActionstepRequest(
                            tokenSetQuery,
                            $"/rest/actionparticipants?action={message.MatterId}&include=participantType,participant",
                            HttpMethod.Get));

                    // Response 2 Data collection info
                    var dataCollectionRecordValues = await actionstepService.Handle <dynamic>(
                        new GenericActionstepRequest(
                            tokenSetQuery,
                            "/rest/datacollectionrecordvalues" +
                            $"?action={message.MatterId}" +
                            $"&dataCollectionRecord[dataCollection][name_in]=property,convdet,keydates" +
                            $"&dataCollectionField[name_in]=titleref,lotno,planno,plantype,lotno2,planno2,plantype2,smtdateonly,smttime,purprice" +
                            $"&include=dataCollectionField,dataCollection",
                            HttpMethod.Get));

                    // Prepare result types for population
                    var queryResult = new SendMappingsToInfoTrack.SendMappingsToInfoTrackCommand()
                    {
                        AuthenticatedUser    = message.AuthenticatedUser,
                        InfoTrackCredentials = infoTrackCredentials,
                        InfoTrackMappingData = new InfoTrackMappingData()
                        {
                            ClientReference   = message.MatterId.ToString(CultureInfo.InvariantCulture),
                            RetailerReference = $"WCA_{message.ActionstepOrgKey}|{message.AuthenticatedUser.Id}"
                        }
                    };

                    // Read responses and populate result object
                    if (allParticipants != null)
                    {
                        foreach (var propertyAddressParticipant in FindParticipantsByName(allParticipants, "Property_Address"))
                        {
                            (string streetNumber, string streetName) =
                                AddressHelper.ParseStreetNumber(
                                    propertyAddressParticipant.physicalAddressLine1,
                                    propertyAddressParticipant.physicalAddressLine2);

                            queryResult.InfoTrackMappingData.PropertyDetails.Add(new InfoTrackMappingData.PropertyDetail()
                            {
                                PropertyAddress = new InfoTrackMappingData.Address()
                                {
                                    StreetNumber = streetNumber,
                                    StreetName   = streetName,
                                    Suburb       = propertyAddressParticipant.physicalCity,
                                    State        = propertyAddressParticipant.physicalStateProvince,
                                    PostCode     = propertyAddressParticipant.physicalPostCode
                                }
                            });

                            // We currently want this to be empty as it affects the InfoTrack entrypoint.
                            // This might change in the near future.
                            //queryResult.State = propertyAddressParticipant.physicalStateProvince;

                            // If there are multiple participants in the Property_Address field, we only want the first one
                            break;
                        }

                        //var conveyancerTypeId = allParticipants.linked.participanttypes.FirstOrDefault(t => t.name == "Conveyancer")?.id;
                        var organisationNameSet = false;
                        foreach (var conveyancerParticipant in FindParticipantsByName(allParticipants, "Conveyancer"))
                        {
                            if (!organisationNameSet)
                            {
                                queryResult.InfoTrackMappingData.LawyerDetail.Organisation.Name = conveyancerParticipant.companyName;
                            }

                            (string addressStreetNumber, string addressStreetName) =
                                AddressHelper.ParseStreetNumber(
                                    conveyancerParticipant.physicalAddressLine1,
                                    conveyancerParticipant.physicalAddressLine2);

                            (string mailingStreetNumber, string mailingStreetName) =
                                AddressHelper.ParseStreetNumber(
                                    conveyancerParticipant.mailingAddressLine1,
                                    conveyancerParticipant.mailingAddressLine2);

                            queryResult.InfoTrackMappingData.LawyerDetail.ContactDetails.Add(new InfoTrackMappingData.Contactdetail()
                            {
                                Email      = conveyancerParticipant.email,
                                Phone      = GetBestPhoneForParticipant(conveyancerParticipant),
                                Fax        = conveyancerParticipant.fax,
                                Individual = new InfoTrackMappingData.Individual()
                                {
                                    Title       = conveyancerParticipant.salutation,
                                    GivenName   = conveyancerParticipant.firstName,
                                    GivenName2  = conveyancerParticipant.middleName,
                                    Surname     = conveyancerParticipant.lastName,
                                    Gender      = conveyancerParticipant.gender,
                                    DateOfBirth = ParseDateForInfoTrack(conveyancerParticipant.birthTimestamp),
                                },
                                Address = new InfoTrackMappingData.Address()
                                {
                                    StreetNumber = addressStreetNumber,
                                    StreetName   = addressStreetName,
                                    Suburb       = conveyancerParticipant.physicalCity,
                                    State        = conveyancerParticipant.physicalStateProvince,
                                    PostCode     = conveyancerParticipant.physicalPostCode,
                                },
                                PoBoxAddress = new InfoTrackMappingData.Poboxaddress()
                                {
                                    PoBoxType = mailingStreetName,
                                    Number    = mailingStreetNumber,
                                    Suburb    = conveyancerParticipant.mailingCity,
                                    State     = conveyancerParticipant.mailingStateProvince,
                                    PostCode  = conveyancerParticipant.mailingPostCode
                                }
                            });
                        }

                        foreach (var buyerParticipant in FindParticipantsByName(allParticipants, "Buyer"))
                        {
                            (string addressStreetNumber, string addressStreetName) =
                                AddressHelper.ParseStreetNumber(
                                    buyerParticipant.physicalAddressLine1,
                                    buyerParticipant.physicalAddressLine2);

                            if (queryResult.InfoTrackMappingData.PropertyDetails.Count < 1)
                            {
                                queryResult.InfoTrackMappingData.PropertyDetails.Add(new InfoTrackMappingData.PropertyDetail());
                            }

                            queryResult.InfoTrackMappingData.PropertyDetails[0].Purchasers.Add(new InfoTrackMappingData.Purchaser()
                            {
                                Organisation = new InfoTrackMappingData.Organisation()
                                {
                                    Name     = buyerParticipant.companyName,
                                    AcnOrAbn = buyerParticipant.taxNumber,
                                    Abn      = buyerParticipant.taxNumber
                                },
                                Email      = buyerParticipant.email,
                                Phone      = GetBestPhoneForParticipant(buyerParticipant),
                                Fax        = buyerParticipant.fax,
                                Individual = new InfoTrackMappingData.Individual()
                                {
                                    Title       = buyerParticipant.salutation,
                                    GivenName   = buyerParticipant.firstName,
                                    GivenName2  = buyerParticipant.middleName,
                                    Surname     = buyerParticipant.lastName,
                                    Gender      = buyerParticipant.gender,
                                    DateOfBirth = ParseDateForInfoTrack(buyerParticipant.birthTimestamp)
                                },
                                Address = new InfoTrackMappingData.Address()
                                {
                                    StreetNumber = addressStreetNumber,
                                    StreetName   = addressStreetName,
                                    Suburb       = buyerParticipant.physicalCity,
                                    State        = buyerParticipant.physicalStateProvince,
                                    PostCode     = buyerParticipant.physicalPostCode
                                }
                            });
                        }

                        foreach (var sellerParticipant in FindParticipantsByName(allParticipants, "Seller"))
                        {
                            (string addressStreetNumber, string addressStreetName) =
                                AddressHelper.ParseStreetNumber(
                                    sellerParticipant.physicalAddressLine1,
                                    sellerParticipant.physicalAddressLine2);

                            if (queryResult.InfoTrackMappingData.PropertyDetails.Count < 1)
                            {
                                queryResult.InfoTrackMappingData.PropertyDetails.Add(new InfoTrackMappingData.PropertyDetail());
                            }

                            queryResult.InfoTrackMappingData.PropertyDetails[0].Vendors.Add(new InfoTrackMappingData.Vendor()
                            {
                                Organisation = new InfoTrackMappingData.Organisation()
                                {
                                    Name     = sellerParticipant.companyName,
                                    AcnOrAbn = sellerParticipant.taxNumber,
                                    Abn      = sellerParticipant.taxNumber
                                },
                                Email      = sellerParticipant.email,
                                Phone      = GetBestPhoneForParticipant(sellerParticipant),
                                Fax        = sellerParticipant.fax,
                                Individual = new InfoTrackMappingData.Individual()
                                {
                                    Title       = sellerParticipant.salutation,
                                    GivenName   = sellerParticipant.firstName,
                                    GivenName2  = sellerParticipant.middleName,
                                    Surname     = sellerParticipant.lastName,
                                    Gender      = sellerParticipant.gender,
                                    DateOfBirth = ParseDateForInfoTrack(sellerParticipant.birthTimestamp),
                                },
                                Address = new InfoTrackMappingData.Address()
                                {
                                    StreetNumber = addressStreetNumber,
                                    StreetName   = addressStreetName,
                                    Suburb       = sellerParticipant.physicalCity,
                                    State        = sellerParticipant.physicalStateProvince,
                                    PostCode     = sellerParticipant.physicalPostCode
                                }
                            });
                        }
                    }

                    if (queryResult.InfoTrackMappingData.PropertyDetails.Count < 1)
                    {
                        queryResult.InfoTrackMappingData.PropertyDetails.Add(new InfoTrackMappingData.PropertyDetail());
                    }

                    if (dataCollectionRecordValues != null && dataCollectionRecordValues.datacollectionrecordvalues != null)
                    {
                        int?propertyDataCollectionId = ((IEnumerable <dynamic>)dataCollectionRecordValues?.linked?.datacollections)?.FirstOrDefault(d => d.name == "property")?.id;
                        if (propertyDataCollectionId.HasValue)
                        {
                            // Get Title Reference and copy it to PropertyReferences
                            var titleReference = ReadDataCollectionRecordValueString("titleref", propertyDataCollectionId.Value, dataCollectionRecordValues);
                            queryResult.InfoTrackMappingData.PropertyDetails[0].PropertyReferences.Add(
                                new InfoTrackMappingData.PropertyReference()
                            {
                                Reference = titleReference
                            });

                            // Lot details and copy them to the first property
                            queryResult.InfoTrackMappingData.PropertyDetails[0].PropertyAddress.LotNumber = ReadDataCollectionRecordValueString("lotno", propertyDataCollectionId.Value, dataCollectionRecordValues);
                            queryResult.InfoTrackMappingData.PropertyDetails[0].LotPlans.Add(new InfoTrackMappingData.Lotplan()
                            {
                                Lot            = queryResult.InfoTrackMappingData.PropertyDetails[0].PropertyAddress.LotNumber,
                                PlanNumber     = ReadDataCollectionRecordValueString("planno", propertyDataCollectionId.Value, dataCollectionRecordValues),
                                PlanType       = ReadDataCollectionRecordValueString("plantype", propertyDataCollectionId.Value, dataCollectionRecordValues),
                                TitleReference = titleReference
                            });

                            var lot2 = new InfoTrackMappingData.Lotplan()
                            {
                                Lot            = ReadDataCollectionRecordValueString("lotno2", propertyDataCollectionId.Value, dataCollectionRecordValues),
                                PlanNumber     = ReadDataCollectionRecordValueString("planno2", propertyDataCollectionId.Value, dataCollectionRecordValues),
                                PlanType       = ReadDataCollectionRecordValueString("plantype2", propertyDataCollectionId.Value, dataCollectionRecordValues),
                                TitleReference = titleReference
                            };

                            if (lot2.ContainsLotData())
                            {
                                queryResult.InfoTrackMappingData.PropertyDetails[0].LotPlans.Add(lot2);
                            }
                        }

                        int?convdetDataCollectionId = ((IEnumerable <dynamic>)dataCollectionRecordValues?.linked?.datacollections)?.FirstOrDefault(d => d.name == "convdet")?.id;
                        if (convdetDataCollectionId.HasValue)
                        {
                            queryResult.InfoTrackMappingData.PropertyDetails[0].SettlementTime = ReadDataCollectionRecordValueString("smttime", convdetDataCollectionId.Value, dataCollectionRecordValues);
                            queryResult.InfoTrackMappingData.PropertyDetails[0].PurchasePrice  = ReadDataCollectionRecordValueString("purprice", convdetDataCollectionId.Value, dataCollectionRecordValues);
                        }

                        int?keydatesDataCollectionId = ((IEnumerable <dynamic>)dataCollectionRecordValues?.linked?.datacollections)?.FirstOrDefault(d => d.name == "keydates")?.id;
                        if (keydatesDataCollectionId.HasValue)
                        {
                            queryResult.InfoTrackMappingData.PropertyDetails[0].SettlementDate = ParseDateForInfoTrack(ReadDataCollectionRecordValueString("smtdateonly", keydatesDataCollectionId.Value, dataCollectionRecordValues));
                        }
                    }

                    return(queryResult);
                }
                catch (Exception ex)
                {
                    telemetryLogger.TrackTrace(
                        "Unexpected exception getting InfoTrack mapping URL",
                        WCASeverityLevel.Error,
                        new Dictionary <string, string>()
                    {
                        { "Actionstep Org", message.ActionstepOrgKey },
                        { "Matter", message.MatterId.ToString(CultureInfo.InvariantCulture) },
                        { "User", message.AuthenticatedUser.Id },
                        { "Exception Message", ex.Message },
                        { "Stack Trace", ex.StackTrace }
                    });

                    throw;
                }
            }
예제 #11
0
 public GetActionRequest(TokenSetQuery tokenSetQuery, int actionId)
 {
     TokenSetQuery = tokenSetQuery;
     ActionId      = actionId;
 }
        public static async Task CanCreateAndReadDisbursement(this IActionstepService actionstepService, int actionId, TokenSetQuery tokenSetQuery)
        {
            if (actionstepService is null)
            {
                throw new ArgumentNullException(nameof(actionstepService));
            }
            if (tokenSetQuery is null)
            {
                throw new ArgumentNullException(nameof(tokenSetQuery));
            }

            var newDisbursement = new Disbursement()
            {
                Description = "Test from API",
                Links       =
                {
                    Action = actionId
                }
            };

            var newDisbursementRequest = new CreateDisbursementsRequest()
            {
                Disbursements = { newDisbursement },
                TokenSetQuery = tokenSetQuery
            };

            var result = await actionstepService.Handle <ListDisbursementsResponse>(newDisbursementRequest);
        }
예제 #13
0
 public Task <UploadFileResponse> UploadFile(TokenSetQuery tokenSetQuery, string fileName, Stream stream)
 {
     throw new NotImplementedException();
 }
예제 #14
0
        public Task <PEXAWorkspaceCreationRequestWithActionstepResponse> Handle(PEXAWorkspaceCreationRequestFromActionstepQuery request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            // Get Actionstep matter info
            var tokenSetQuery = new TokenSetQuery(request.AuthenticatedUser?.Id, request.ActionstepOrg);

            try
            {
                // New token refresh handling means these can run in parallel.
                var actionResponseTask = _actionstepService.Handle <GetActionResponse>(new GetActionRequest
                {
                    ActionId      = request.MatterId,
                    TokenSetQuery = tokenSetQuery
                });

                var actionParticipantsResponseTask = _actionstepService.Handle <ListActionParticipantsResponse>(new ListActionParticipantsRequest
                {
                    ActionstepId  = request.MatterId,
                    TokenSetQuery = tokenSetQuery
                });

                var dataCollectionRecordValuesResponseTask = _actionstepService.Handle <ListDataCollectionRecordValuesResponse>(new ListDataCollectionRecordValuesRequest
                {
                    ActionstepId              = request.MatterId,
                    TokenSetQuery             = tokenSetQuery,
                    DataCollectionRecordNames = { "property", "convdet", "keydates" },
                    DataCollectionFieldNames  = { "titleref", "lotno", "planno", "plantype", "smtdateonly", "smttime", "purprice", "ConveyType" }
                });

                Task.WaitAll(actionResponseTask, actionParticipantsResponseTask, dataCollectionRecordValuesResponseTask);

                // Transform Actionstep matter info into generic WCA Conveyancing Matter type
                // using specific configuration for this client (to account for Actionstep
                // action type configuration).
                var wCAConveyancingMatter = _actionstepToWCAMapper.MapFromActionstepTypes(
                    actionResponseTask.Result,
                    actionParticipantsResponseTask.Result,
                    dataCollectionRecordValuesResponseTask.Result);

                PEXAWorkspaceCreationRequestWithActionstepResponse pexaWorkspaceRequestWithActionstepData = new PEXAWorkspaceCreationRequestWithActionstepResponse
                {
                    CreatePexaWorkspaceCommand = new CreatePexaWorkspaceCommand()
                    {
                        PexaWorkspaceCreationRequest = new WorkspaceCreationRequest(),
                        OrgKey   = request.ActionstepOrg,
                        MatterId = request.MatterId
                    },
                    PexaRoleSpecified = true,
                    ActionstepData    = wCAConveyancingMatter
                };


                var landTitle = _mapper.Map <PropertyDetails, WorkspaceCreationRequestTypeLandTitleDetailsLandTitle>(wCAConveyancingMatter.PropertyDetails);

                pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.ParticipantSettlementAcceptanceStatus = "Accepted";
                pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.LandTitleDetails = new WorkspaceCreationRequestTypeLandTitleDetails();
                pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.LandTitleDetails.LandTitle.Add(landTitle);

                var actionTypeAlias = String.Empty;
                switch (wCAConveyancingMatter.ActionType)
                {
                case "Conveyancing - NSW":
                    actionTypeAlias = "NSW";
                    break;

                case "Conveyancing  - Queensland":
                    actionTypeAlias = "QLD";
                    break;

                case "Conveyancing - Victoria":
                    actionTypeAlias = "VIC";
                    break;

                default:
                    actionTypeAlias = String.Empty;
                    break;
                }

                if (!string.IsNullOrEmpty(actionTypeAlias))
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.Jurisdiction = actionTypeAlias;
                }

                if (wCAConveyancingMatter.ConveyancingType == ConveyancingType.Purchase)
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.Role = PexaRole.Incoming_Proprietor;
                }
                else if (wCAConveyancingMatter.ConveyancingType == ConveyancingType.Sale)
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.Role = PexaRole.Proprietor_on_Title;
                }
                else
                {
                    pexaWorkspaceRequestWithActionstepData.PexaRoleSpecified = false;
                }

                if (!string.IsNullOrEmpty(request.ActionstepOrg) && request.MatterId > 0)
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.SubscriberReference = ActionstepMatter.ConstructId(request.ActionstepOrg, request.MatterId);
                }

                if (wCAConveyancingMatter.SettlementDate != null)
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.SettlementDate = wCAConveyancingMatter.SettlementDate.ToDateTimeUnspecified();
                }

                if (pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.SettlementDate == DateTime.MinValue)
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.SettlementDate = null;
                }

                if (pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.Role == PexaRole.Consentor || pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.Role == PexaRole.CT_Controller)
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.LandTitleDetails.ParentTitle = "No";
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.RequestLandTitleData         = "No";
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.FinancialSettlement          = "Yes";
                }
                else
                {
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.LandTitleDetails.ParentTitle = "No";
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.RequestLandTitleData         = "Yes";
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.FinancialSettlement          = "Yes";
                }

                pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.PartyDetails = new Collection <WorkspaceCreationRequestTypePartyDetailsParty>();

                foreach (var buyer in wCAConveyancingMatter.Buyers)
                {
                    var buyerPartyDetails = MapPartyDetails(buyer, "Incoming Proprietor");
                    pexaWorkspaceRequestWithActionstepData.CreatePexaWorkspaceCommand.PexaWorkspaceCreationRequest.PartyDetails.Add(buyerPartyDetails);
                }

                return(Task.FromResult(pexaWorkspaceRequestWithActionstepData));
            }
            catch (AggregateException ex)
            {
                if (ex.InnerExceptions.All(e => e is InvalidTokenSetException || e is InvalidCredentialsForActionstepApiCallException))
                {
                    throw ex.InnerExceptions.FirstOrDefault();
                }

                throw ex;
            }
        }
예제 #15
0
            protected override async Task Handle(SaveResourcesCommand message, CancellationToken token)
            {
                if (message is null)
                {
                    throw new ArgumentNullException(nameof(message));
                }

                ValidationResult result = _validator.Validate(message);

                if (!result.IsValid)
                {
                    throw new ValidationException("Unable to save Property Resources, the command message was invalid.", result.Errors);
                }

                using (var request = new HttpRequestMessage(HttpMethod.Get, message.ResourceURL))
                {
                    var byteArray = Encoding.ASCII.GetBytes($"{message.InfoTrackCredentials.Username}:{message.InfoTrackCredentials.Password}");
                    request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

                    using (var infoTrackFileDownloadResponse = await _infoTrackService.Client.SendAsync(request))
                    {
                        infoTrackFileDownloadResponse.EnsureSuccessStatusCode();

                        using (var infoTrackFileStream = await infoTrackFileDownloadResponse.Content.ReadAsStreamAsync())
                        {
                            if (infoTrackFileStream.Length <= 0)
                            {
                                throw new HttpRequestException($"Unable to download the resource from InfoTrack.");
                            }
                            else
                            {
                                var tokenSetQuery = new TokenSetQuery(message.AuthenticatedUser?.Id, message.ActionstepOrgKey);

                                var fileNameWithExtension = DetermineBestFileNameWithExtension(message, infoTrackFileDownloadResponse);

                                var fileUploadResponse = await _actionstepService.UploadFile(tokenSetQuery, fileNameWithExtension, infoTrackFileStream);

                                if (fileUploadResponse == null)
                                {
                                    throw new Exception("Unknown error uploading document to Actionstep.");
                                }

                                // Get all folders for matter and check to see if the specified folder exists. If it does, we need its ID.
                                var actionFolder     = new ActionFolder(message.MatterId);
                                var getFolderRequest = new GetActionFolderRequest(tokenSetQuery, actionFolder);
                                var folderResponse   = await _actionstepService.Handle <ListActionFolderResponse>(getFolderRequest);

                                /// Will be null if <see cref="SaveResourcesCommand.FolderName"/> wasn't found. In which case the document will be saved at the root of the matter.
                                var parentFolderId = folderResponse.ActionFolders.FirstOrDefault(af => af.Name == message.FolderName)?.Id;

                                /// <see cref="ActionstepDocument"/> represents the object in "Matter Documents", as opposed to the file content from above (which is just in a big bucket).
                                var document = new ActionDocument(message.MatterId, fileNameWithExtension, fileUploadResponse, parentFolderId);

                                var saveRequest = new SaveActionDocumentRequest(tokenSetQuery, document);

                                await _actionstepService.Handle <SaveActionDocumentResponse>(saveRequest);
                            }
                        }
                    }
                }
            }
 public SaveActionDocumentRequest(TokenSetQuery tokenSetQuery, ActionDocument actionDocument)
 {
     TokenSetQuery  = tokenSetQuery;
     ActionDocument = actionDocument;
 }
예제 #17
0
            protected override async Task Handle(UpdateOrderCommand command, CancellationToken token)
            {
                if (command is null)
                {
                    throw new ArgumentNullException(nameof(command));
                }

                var infoTrackOrderUpdateMessage = _wCADbContext.InfoTrackOrderUpdateMessageHistory.Find(command.InfoTrackOrderUpdateMessageId);

                infoTrackOrderUpdateMessage.MarkProcessInProgress();
                await _wCADbContext.SaveChangesAsync();

                var executionId = Guid.NewGuid();

                _telemetryLogger.TrackTrace(
                    $"{typeof(Handler).FullName}: Entered UpdateOrder.",
                    WCASeverityLevel.Information,
                    new Dictionary <string, string>()
                {
                    { "InfoTrackOrderId", infoTrackOrderUpdateMessage.InfoTrackOrderId.ToString(CultureInfo.InvariantCulture) },
                    { "Actionstep matter", infoTrackOrderUpdateMessage.InfoTrackClientReference },
                    { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                    { "ExecutionId", executionId.ToString() }
                });

                int matterId = int.Parse(infoTrackOrderUpdateMessage.InfoTrackClientReference, CultureInfo.InvariantCulture);

                string[] retailerReference = infoTrackOrderUpdateMessage.InfoTrackRetailerReference.Split('|');
                var      orgKey            = string.Empty;
                var      wcaUserId         = string.Empty;

                if (retailerReference.Length >= 2)
                {
                    // Substring removes the "WCA_" prefix. We know the prefix is present because
                    // the message passed Validation to get here.
                    orgKey    = retailerReference[0].Substring(4);
                    wcaUserId = retailerReference[1];
                }

                if (string.IsNullOrEmpty(wcaUserId))
                {
                    throw new InvalidInfoTrackOrderUserException(
                              "InfoTrack order information was supplied without WCA user ID. " +
                              "Cannot process the order.");
                }

                var userWhoPlacedOrder = await _wCADbContext.Users.FindAsync(wcaUserId);

                if (userWhoPlacedOrder == null)
                {
                    throw new InvalidInfoTrackOrderUserException(
                              "InfoTrack order information was supplied with an invalid WCA user ID. " +
                              "Cannot process the order.");
                }

                // Update the current record for this order
                var infoTrackOrder = await _wCADbContext.InfoTrackOrders.FindAsync(infoTrackOrderUpdateMessage.InfoTrackOrderId);

                if (infoTrackOrder == null)
                {
                    infoTrackOrder = new InfoTrackOrder();
                    infoTrackOrder.DateCreatedUtc = DateTime.UtcNow;
                    infoTrackOrder.LastUpdatedUtc = infoTrackOrder.DateCreatedUtc;
                    infoTrackOrder.CreatedBy      = userWhoPlacedOrder;
                    infoTrackOrder.UpdatedBy      = userWhoPlacedOrder;
                    await _wCADbContext.AddAsync(infoTrackOrder);
                }

                var previousFileHash           = infoTrackOrder.InfoTrackFileHash;
                var previousOrderTotalFeeTotal = infoTrackOrder.InfoTrackTotalFeeTotal;

                infoTrackOrder = _mapper.Map(infoTrackOrderUpdateMessage, infoTrackOrder);
                infoTrackOrder.OrderedByWCAUser   = userWhoPlacedOrder;
                infoTrackOrder.ActionstepMatterId = matterId;
                infoTrackOrder.LastUpdatedUtc     = DateTime.UtcNow;

                var existingOrg = await _wCADbContext.ActionstepOrgs.FindAsync(orgKey);

                infoTrackOrder.ActionstepOrg = existingOrg
                                               ?? throw new InvalidOperationException(
                                                         "InfoTrack order information references an invalid Actonstep org key. " +
                                                         "WCA doesn't have any information or API credentials for the specified " +
                                                         "org key. Cannot continue.");

                // Update current record with values from history - checkpoint
                await _wCADbContext.SaveChangesAsync();

                var tokenSetQuery = new TokenSetQuery(userWhoPlacedOrder.Id, orgKey);

                var processingErrors = new StringBuilder();

                // Save InfoTrack Title Order Resources (Files) to Actionstep
                // We only want to upload documents if the filehash has changed, and if there's
                // actually a download url.
                if (string.IsNullOrEmpty(infoTrackOrderUpdateMessage.InfoTrackDownloadUrl))
                {
                    _telemetryLogger.TrackTrace(
                        $"{typeof(Handler).FullName}: InfoTrackDownloadUrl is empty. No document to upload.",
                        WCASeverityLevel.Verbose,
                        new Dictionary <string, string>()
                    {
                        { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                        { "Actionstep org key", orgKey },
                        { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                        { "ExecutionId", executionId.ToString() }
                    });

                    infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                    infoTrackOrder.ActionstepDocumentUploadStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                    infoTrackOrder.ActionstepDocumentUploadStatus           = ActionstepDocumentUploadStatus.NotApplicable;
                    await _wCADbContext.SaveChangesAsync();
                }
                else if (previousFileHash == infoTrackOrderUpdateMessage.InfoTrackFileHash)
                {
                    _telemetryLogger.TrackTrace(
                        $"{typeof(Handler).FullName}: FileHash has not changed. Skipping document upload.",
                        WCASeverityLevel.Verbose,
                        new Dictionary <string, string>()
                    {
                        { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                        { "Actionstep org key", orgKey },
                        { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                        { "ExecutionId", executionId.ToString() }
                    });

                    // Don't update ActionstepDocumentUploadStatus here because the existing status on the record
                    // is still valid and informative.
                }
                else
                {
                    // If we're here, we have a download url, and the FileHash is new (either becaues it's changed or
                    // there was no prior FileHash).
                    try
                    {
                        infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                        infoTrackOrder.ActionstepDocumentUploadStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                        infoTrackOrder.ActionstepDocumentUploadStatus           = ActionstepDocumentUploadStatus.UploadInProgress;
                        await _wCADbContext.SaveChangesAsync();

                        var infoTrackCredentials = await _infoTrackCredentialRepository.FindCredential(orgKey);

                        await _mediator.Send(new SaveResources.SaveResourcesCommand
                        {
                            AuthenticatedUser    = userWhoPlacedOrder,
                            MatterId             = matterId,
                            ActionstepOrgKey     = orgKey,
                            InfoTrackCredentials = infoTrackCredentials,
                            ResourceURL          = infoTrackOrderUpdateMessage.InfoTrackDownloadUrl,
                            FolderName           = "_SEARCHES",
                            FileNameWithoutExtensionIfNotAvailableFromHeader = infoTrackOrder.InfoTrackServiceName,
                            FileNameAddition = " - Updated at " + DateTime.UtcNow.ToString("dd MMM yyyy hh-mm tt", CultureInfo.InvariantCulture)
                        });

                        infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                        infoTrackOrder.ActionstepDocumentUploadStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                        infoTrackOrder.ActionstepDocumentUploadStatus           = ActionstepDocumentUploadStatus.UploadedSuccessfully;
                        await _wCADbContext.SaveChangesAsync();
                    }
                    catch (Exception ex)
                    {
                        infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                        infoTrackOrder.ActionstepDocumentUploadStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                        infoTrackOrder.ActionstepDocumentUploadStatus           = ActionstepDocumentUploadStatus.UploadFailed;
                        await _wCADbContext.SaveChangesAsync();

                        var message = $"Failed to upload InfoTrack document to Actionstep for ID: {command.InfoTrackOrderUpdateMessageId}";
                        _logger.LogError(ex, message, null);
                        _telemetryLogger.TrackTrace(
                            message,
                            WCASeverityLevel.Error,
                            new Dictionary <string, string>()
                        {
                            { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                            { "Actionstep org key", orgKey },
                            { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                            { "Exception Message", ex.Message },
                            { "Stack Trace", ex.StackTrace.ToString(CultureInfo.InvariantCulture) },
                            { "ExecutionId", executionId.ToString() }
                        });

                        processingErrors.Append(message + "<br/>");
                    }
                }

                if (infoTrackOrder.ActionstepDisbursementStatus == ActionstepDisbursementStatus.CreatedSuccessfully)
                {
                    _telemetryLogger.TrackTrace(
                        $"{typeof(Handler).FullName}: ActionstepDisbursementStatus is CreatedSucessfully, skipping processing of disbursements.",
                        WCASeverityLevel.Information,
                        new Dictionary <string, string>()
                    {
                        { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                        { "Actionstep org key", orgKey },
                        { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                        { "ExecutionId", executionId.ToString() }
                    });
                }
                else
                {
                    ValidateFees(infoTrackOrderUpdateMessage);

                    // Negative values are allowed as this represents a refund.
                    if (infoTrackOrderUpdateMessage.InfoTrackTotalFeeTotal != 0)
                    {
                        _telemetryLogger.TrackTrace(
                            $"{typeof(Handler).FullName}: Disbursements have not yet been created and TotalFeeTotal != 0. Processing disbursements now.",
                            WCASeverityLevel.Information,
                            new Dictionary <string, string>()
                        {
                            { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                            { "Actionstep org key", orgKey },
                            { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                            { "InfoTrackTotalFeeTotal", infoTrackOrderUpdateMessage.InfoTrackTotalFeeTotal.ToString(CultureInfo.InvariantCulture) },
                            { "ExecutionId", executionId.ToString() }
                        });

                        try
                        {
                            infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                            infoTrackOrder.ActionstepDisbursementStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                            infoTrackOrder.ActionstepDisbursementStatus           = ActionstepDisbursementStatus.CreationInProgress;
                            await _wCADbContext.SaveChangesAsync();

                            (int?gstTaxCodeId, int?nonGstTaxCodeId) = await GetTaxCodeIds(
                                _actionstepService,
                                tokenSetQuery,
                                _telemetryLogger,
                                infoTrackOrderUpdateMessage.InfoTrackOrderId,
                                orgKey,
                                matterId,
                                executionId);

                            // Save under disbursments
                            // If GST values match, we'll create a single disbursement. If they don't match,
                            // we need to create two different disbursements to account for the differing GST amounts.
                            dynamic disbursement;

                            // If they have the same GST status, then we can combine to a single disbursement.
                            // I.e. either if they both have GST, or if neither of them have GST.
                            bool retailerHasGST     = infoTrackOrderUpdateMessage.InfoTrackRetailerFeeGST != 0;
                            bool supplierHasGST     = infoTrackOrderUpdateMessage.InfoTrackSupplierFeeGST != 0;
                            bool splitDisbursements = false;
                            if (retailerHasGST == supplierHasGST)
                            {
                                disbursement = PrepareSingleDisbursement(infoTrackOrderUpdateMessage, matterId, gstTaxCodeId, nonGstTaxCodeId);
                            }
                            else
                            {
                                splitDisbursements = true;
                                disbursement       = PrepareSplitDisbursements(infoTrackOrderUpdateMessage, matterId, gstTaxCodeId, nonGstTaxCodeId);
                            }

                            if (disbursement != null)
                            {
                                _telemetryLogger.TrackTrace(
                                    $"{typeof(Handler).FullName}: Creating disbursements.",
                                    WCASeverityLevel.Information,
                                    new Dictionary <string, string>()
                                {
                                    { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                                    { "Actionstep org key", orgKey },
                                    { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                                    { "InfoTrackTotalFeeTotal", infoTrackOrderUpdateMessage.InfoTrackTotalFeeTotal.ToString(CultureInfo.InvariantCulture) },
                                    { "SplitDisbursements", splitDisbursements.ToString(CultureInfo.InvariantCulture) },
                                    { "ExecutionId", executionId.ToString() }
                                });

                                var response = await _actionstepService.Handle <dynamic>(new GenericActionstepRequest(
                                                                                             tokenSetQuery,
                                                                                             $"/rest/disbursements",
                                                                                             HttpMethod.Post,
                                                                                             disbursement));

                                infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                                infoTrackOrder.ActionstepDisbursementStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                                infoTrackOrder.ActionstepDisbursementStatus           = ActionstepDisbursementStatus.CreatedSuccessfully;
                                await _wCADbContext.SaveChangesAsync();
                            }
                            else
                            {
                                _telemetryLogger.TrackTrace(
                                    $"{typeof(Handler).FullName}: After processing it was determined that no disbursements need to be created.",
                                    WCASeverityLevel.Information,
                                    new Dictionary <string, string>()
                                {
                                    { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                                    { "Actionstep org key", orgKey },
                                    { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                                    { "InfoTrackTotalFeeTotal", infoTrackOrderUpdateMessage.InfoTrackTotalFeeTotal.ToString(CultureInfo.InvariantCulture) },
                                    { "ExecutionId", executionId.ToString() }
                                });

                                infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                                infoTrackOrder.ActionstepDisbursementStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                                infoTrackOrder.ActionstepDisbursementStatus           = ActionstepDisbursementStatus.NotApplicable;
                                await _wCADbContext.SaveChangesAsync();
                            }
                        }
                        catch (Exception ex)
                        {
                            infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                            infoTrackOrder.ActionstepDisbursementStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                            infoTrackOrder.ActionstepDisbursementStatus           = ActionstepDisbursementStatus.CreationFailed;
                            await _wCADbContext.SaveChangesAsync();

                            var message = $"Failed to process disbursements for InfoTrack order for ID: {command.InfoTrackOrderUpdateMessageId}";
                            _logger.LogError(ex, message, null);
                            _telemetryLogger.TrackTrace(
                                message,
                                WCASeverityLevel.Error,
                                new Dictionary <string, string>()
                            {
                                { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                                { "Actionstep org key", orgKey },
                                { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                                { "Exception Message", ex.Message },
                                { "Stack Trace", ex.StackTrace.ToString(CultureInfo.InvariantCulture) },
                                { "ExecutionId", executionId.ToString() }
                            });

                            processingErrors.Append(message + "<br/>");
                        }
                    }
                    else
                    {
                        _telemetryLogger.TrackTrace(
                            $"{typeof(Handler).FullName}: Disbursement amounts remain at 0. Skipping disbursements.",
                            WCASeverityLevel.Information,
                            new Dictionary <string, string>()
                        {
                            { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                            { "Actionstep org key", orgKey },
                            { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                            { "InfoTrackTotalFeeTotal", infoTrackOrderUpdateMessage.InfoTrackTotalFeeTotal.ToString(CultureInfo.InvariantCulture) },
                            { "ExecutionId", executionId.ToString() }
                        });

                        infoTrackOrder.LastUpdatedUtc = DateTime.UtcNow;
                        infoTrackOrder.ActionstepDisbursementStatusUpdatedUtc = infoTrackOrder.LastUpdatedUtc;
                        infoTrackOrder.ActionstepDisbursementStatus           = ActionstepDisbursementStatus.NotApplicable;
                        await _wCADbContext.SaveChangesAsync();
                    }
                }

                var errorMessage = processingErrors.ToString();
                var processingErrorsEncountered = !String.IsNullOrEmpty(errorMessage);

                if (processingErrorsEncountered)
                {
                    infoTrackOrderUpdateMessage.MarkProcessedWithErrors();
                }
                else
                {
                    infoTrackOrderUpdateMessage.MarkProcessed();
                }

                await _wCADbContext.SaveChangesAsync();

                _telemetryLogger.TrackTrace(
                    processingErrorsEncountered ? $"{typeof(Handler).FullName}: Finished UpdateOrder with errors." : $"{typeof(Handler).FullName}: Finished UpdateOrder.",
                    WCASeverityLevel.Information,
                    new Dictionary <string, string>()
                {
                    { "InfoTrackOrderUpdateMessageId", command.InfoTrackOrderUpdateMessageId.ToString(CultureInfo.InvariantCulture) },
                    { "Actionstep org key", orgKey },
                    { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                    { "ExecutionId", executionId.ToString() }
                });

                if (processingErrorsEncountered)
                {
                    var ex = new ApplicationException("Errors were encountered while processing message");
                    ex.Data.Add("message", errorMessage);
                    ex.Data.Add("contentType", "text/html");
                    throw ex;
                }
            }
예제 #18
0
            private async Task <(int?gstTaxCodeId, int?nonGstTaxCodeId)> GetTaxCodeIds(
                IActionstepService actionstepService,
                TokenSetQuery tokenSetQuery,
                ITelemetryLogger telemetryLogger,
                int infoTrackOrderId,
                string orgKey,
                int matterId,
                Guid executionId)
            {
                // Get GST and Non GST tax codes for disbursement creation

                var taxCodeInfo = await actionstepService.Handle <dynamic>(new GenericActionstepRequest(tokenSetQuery, $"/rest/taxcodes?fields=code", HttpMethod.Get));

                var gstTaxCodeNames = new[] { "S 10.0", "GST" };
                int?gstTaxCodeId    = LookupTaxCodeId(taxCodeInfo?.taxcodes, gstTaxCodeNames);

                if (gstTaxCodeId == null)
                {
                    telemetryLogger.TrackTrace(
                        "Couldn't determine GST Tax Code when creating InfoTrack disbursement. " +
                        "Actionstep default will be used instead.",
                        WCASeverityLevel.Warning,
                        new Dictionary <string, string>()
                    {
                        { "GST Tax Code names attempted", string.Join(", ", gstTaxCodeNames) },
                        { "InfoTrack Order ID", infoTrackOrderId.ToString(CultureInfo.InvariantCulture) },
                        { "Actionstep org key", orgKey },
                        { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                        { "ExecutionId", executionId.ToString() }
                    });
                }

                var nonGstTaxCodeNames = new[] { "N-T", "GST Free", "Other GST Free", "No Tax" };

                // TODO: Make this properly configurable! This is just a quick hack :(
                // See:
                //  - PBI:    https://dev.azure.com/workcloudapps/WorkCloudApps/_backlogs/backlog/WorkCloudApps%20Team/Backlog%20items/?workitem=700
                //  - Ticket: https://workcloud.freshdesk.com/a/tickets/10010?note=6238878382
                if (!string.IsNullOrEmpty(orgKey) && orgKey.Equals("swslawyers", StringComparison.InvariantCulture))
                {
                    nonGstTaxCodeNames = new[] { "BAS Excluded", "N-T", "GST Free", "Other GST Free", "No Tax" };
                }

                int?nonGstTaxCodeId = LookupTaxCodeId(taxCodeInfo.taxcodes, nonGstTaxCodeNames);

                if (nonGstTaxCodeId == null)
                {
                    telemetryLogger.TrackTrace(
                        "Couldn't determine Non-GST Tax Code when creating InfoTrack disbursement. " +
                        "Actionstep default will be used instead.",
                        WCASeverityLevel.Warning,
                        new Dictionary <string, string>()
                    {
                        { "Non-GST Tax Code names attempted", string.Join(", ", nonGstTaxCodeNames) },
                        { "InfoTrack Order ID", infoTrackOrderId.ToString(CultureInfo.InvariantCulture) },
                        { "Actionstep org key", orgKey },
                        { "Actionstep matter", matterId.ToString(CultureInfo.InvariantCulture) },
                        { "ExecutionId", executionId.ToString() }
                    });
                }

                return(gstTaxCodeId, nonGstTaxCodeId);
            }
        public Task <FirstTitlePolicyRequestFromActionstepResponse> Handle(FirstTitlePolicyRequestFromActionstepQuery request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            // Get Actionstep matter info
            var tokenSetQuery = new TokenSetQuery(request.AuthenticatedUser?.Id, request.OrgKey);

            try
            {
                // New token refresh handling means these can run in parallel.
                var actionResponseTask = _actionstepService.Handle <GetActionResponse>(new GetActionRequest
                {
                    ActionId      = request.MatterId,
                    TokenSetQuery = tokenSetQuery
                });

                var actionParticipantsResponseTask = _actionstepService.Handle <ListActionParticipantsResponse>(new ListActionParticipantsRequest
                {
                    ActionstepId  = request.MatterId,
                    TokenSetQuery = tokenSetQuery
                });

                var dataCollectionRecordValuesResponseTask = _actionstepService.Handle <ListDataCollectionRecordValuesResponse>(new ListDataCollectionRecordValuesRequest
                {
                    ActionstepId              = request.MatterId,
                    TokenSetQuery             = tokenSetQuery,
                    DataCollectionRecordNames = { "property", "convdet", "keydates" },
                    DataCollectionFieldNames  = { "titleref", "lotno", "planno", "plantype", "smtdateonly", "smttime", "purprice", "ConveyType" }
                });

                Task.WaitAll(actionResponseTask, actionParticipantsResponseTask, dataCollectionRecordValuesResponseTask);

                // Transform Actionstep matter info into generic WCA Conveyancing Matter type
                // using specific configuration for this client (to account for Actionstep
                // action type configuration).
                var wCAConveyancingMatter = _actionstepToWCAMapper.MapFromActionstepTypes(
                    actionResponseTask.Result,
                    actionParticipantsResponseTask.Result,
                    dataCollectionRecordValuesResponseTask.Result);

                var asSourceProperty = wCAConveyancingMatter.PropertyAddresses.FirstOrDefault();
                var sourceProperty   = asSourceProperty == default(Domain.Conveyancing.Party) ? new FTParty() : FTParty.FromASParty(asSourceProperty);

                var actionstepData = new FTActionstepMatter()
                {
                    Title = new FTTitle()
                    {
                        TitleInfoType  = TitleInfoType.Reference,
                        TitleReference = wCAConveyancingMatter.PropertyDetails.TitleReference
                    },
                    SourceProperty = sourceProperty,
                    PurchasePrice  = wCAConveyancingMatter.PurchasePrice,
                    SettlementDate = wCAConveyancingMatter.SettlementDate.ToDateTimeUnspecified()
                };

                foreach (var buyer in wCAConveyancingMatter.Buyers)
                {
                    actionstepData.Buyers.Add(FTParty.FromASParty(buyer));
                }

                FirstTitlePolicyRequestFromActionstepResponse firstTitlePolicyRequestFromActionstepResponse = new FirstTitlePolicyRequestFromActionstepResponse
                {
                    ActionstepData       = actionstepData,
                    RequestPolicyOptions = new RequestPolicyOptions()
                };

                return(Task.FromResult(firstTitlePolicyRequestFromActionstepResponse));
            }
            catch (UnauthorizedAccessException uax)
            {
                throw new InvalidCredentialsForActionstepApiCallException(string.Empty, uax)
                      {
                          ActionstepOrgKey = request.OrgKey,
                          User             = request.AuthenticatedUser,
                      };
            }
        }
예제 #20
0
        public async Task <RequestPropertyInformationFromActionstepResponse> Handle(ConveyancingDataFromActionstepQuery request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            // Get Actionstep matter info
            var tokenSetQuery = new TokenSetQuery(request.AuthenticatedUser?.Id, request.OrgKey);

            try
            {
                // New token refresh handling means these can run in parallel.
                var actionResponseTask = _actionstepService.Handle <GetActionResponse>(new GetActionRequest
                {
                    ActionId      = request.MatterId,
                    TokenSetQuery = tokenSetQuery
                });

                var actionParticipantsResponseTask = _actionstepService.Handle <ListActionParticipantsResponse>(new ListActionParticipantsRequest
                {
                    ActionstepId  = request.MatterId,
                    TokenSetQuery = tokenSetQuery
                });

                var dataCollectionRecordValuesResponseTask = _actionstepService.Handle <ListDataCollectionRecordValuesResponse>(new ListDataCollectionRecordValuesRequest
                {
                    ActionstepId              = request.MatterId,
                    TokenSetQuery             = tokenSetQuery,
                    DataCollectionRecordNames = { "property", "convdet", "keydates" },
                    DataCollectionFieldNames  = { "titleref", "lotno", "planno", "plantype", "smtdateonly", "smttime", "purprice", "ConveyType" }
                });

                Task.WaitAll(actionResponseTask, actionParticipantsResponseTask, dataCollectionRecordValuesResponseTask);

                // Transform Actionstep matter info into generic WCA Conveyancing Matter type
                // using specific configuration for this client (to account for Actionstep
                // action type configuration).
                var wCAConveyancingMatter = _actionstepToWCAMapper.MapFromActionstepTypes(
                    actionResponseTask.Result,
                    actionParticipantsResponseTask.Result,
                    dataCollectionRecordValuesResponseTask.Result);

                var state = State.Unknown;
                switch (wCAConveyancingMatter.ActionType)
                {
                case "Conveyancing - NSW":
                    state = State.NSW;
                    break;

                case "Conveyancing  - Queensland":
                    state = State.QLD;
                    break;

                case "Conveyancing - Victoria":
                    state = State.Vic;
                    break;

                default:
                    state = State.Unknown;
                    break;
                }

                var matter = new Matter
                {
                    MatterReference = request.MatterId.ToString(CultureInfo.InvariantCulture),
                    MatterEntity    = new RealProperty
                    {
                        TitleReference = wCAConveyancingMatter?.PropertyDetails?.TitleReference,
                        LotPlan        = new LotPlan()
                        {
                            Lot = wCAConveyancingMatter?.PropertyDetails?.LotNo
                        },
                    }
                };

                var version = new WCA.GlobalX.Client.Version
                {
                    ModelVersion       = "http://globalx.com.au/common/model/matter/2013/07/31",
                    ApplicationName    = "Konekta",
                    ApplicationVersion = "1.0"
                };

                var settings = new JsonSerializerSettings {
                    SerializationBinder = new GXSerializationBinder(),
                    TypeNameHandling    = TypeNameHandling.All
                };

                var entryPoint = string.IsNullOrEmpty(request.EntryPoint) ? "web" : request.EntryPoint;
                var response   = new RequestPropertyInformationFromActionstepResponse
                {
                    Matter  = JsonConvert.SerializeObject(matter, settings),
                    Version = JsonConvert.SerializeObject(version, settings),
                    GXUri   = new Uri(_globalXService.BaseWebUrl, $"{entryPoint}?embed={request.Embed}&state={state}")
                };

                return(response);
            }
            catch (AggregateException ex)
            {
                if (ex.InnerExceptions.All(e => e is InvalidTokenSetException || e is InvalidCredentialsForActionstepApiCallException))
                {
                    throw ex.InnerExceptions.FirstOrDefault();
                }

                throw;
            }
        }
            public async Task <DocumentRelationship> Handle(CopyDocumentVersionToActionstepCommand request, CancellationToken cancellationToken)
            {
                if (request is null)
                {
                    throw new System.ArgumentNullException(nameof(request));
                }
                _validator.ValidateAndThrow(request);

                var tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
                DocumentFileInfo globalXDocumentFileInfo;

                var tokenSetQuery = new TokenSetQuery(request.ActionstepUserId, request.ActionstepOrgKey);

                // Check to make sure this matter exists first. This will throw if it's not found.
                var matterInfo = await _actionstepService.Handle <GetActionResponse>(new GetActionRequest(tokenSetQuery, request.ActionstepMatterId));

                if (matterInfo is null)
                {
                    throw new InvalidActionstepMatterException($"Matter '{request.ActionstepMatterId}' was not found in Actionstep.");
                }

                try
                {
                    try
                    {
                        globalXDocumentFileInfo = await _globalXService.DownloadDocument(
                            request.DocumentVersion.DocumentId.Value,
                            request.DocumentVersion.DocumentVersionId.Value,
                            tempFilePath,
                            request.GlobalXUserId);
                    }
                    catch (Exception ex)
                    {
                        throw new FailedToDownloadGlobalXDocumentException(ex);
                    }

                    try
                    {
                        var fileName = !string.IsNullOrEmpty(globalXDocumentFileInfo?.FileName)
                            ? globalXDocumentFileInfo.FileName
                            : request.DocumentVersion.DocumentName;

                        var fileUploadResponse = await _actionstepService.UploadFile(tokenSetQuery, fileName, tempFilePath);

                        if (fileUploadResponse is null)
                        {
                            throw new Exception("Unknown error uploading document to Actionstep.");
                        }

                        // Get all folders for matter and check to see if the specified folder exists. If it does, we need its ID.
                        var actionFolder     = new ActionFolder(request.ActionstepMatterId);
                        var getFolderRequest = new GetActionFolderRequest(tokenSetQuery, actionFolder);
                        var folderResponse   = await _actionstepService.Handle <ListActionFolderResponse>(getFolderRequest);

                        /// Will be null if the folder name wasn't found. In which case the document will be saved at the root of the matter.
                        var parentFolderId = folderResponse?.ActionFolders?.FirstOrDefault(af => af.Name == ActionstepFolderFirstPreference)?.Id ??
                                             folderResponse?.ActionFolders?.FirstOrDefault(af => af.Name == ActionstepFolderSecondPreference)?.Id;

                        /// <see cref="ActionstepDocument"/> represents the object in "Matter Documents", as opposed to the file content from above (which is just in a big bucket).
                        var document = new ActionDocument(request.ActionstepMatterId, fileName, fileUploadResponse, parentFolderId);
                        var saveActionDocumentRequest = new SaveActionDocumentRequest(tokenSetQuery, document);

                        var saveActionDocumentResponse = await _actionstepService.Handle <SaveActionDocumentResponse>(saveActionDocumentRequest);

                        return(new DocumentRelationship(
                                   request.DocumentVersion.DocumentId.Value,
                                   request.DocumentVersion.DocumentVersionId.Value,
                                   fileName,
                                   request.DocumentVersion.MimeType,
                                   request.ActionstepOrgKey,
                                   request.ActionstepMatterId,
                                   saveActionDocumentResponse.ActionDocument.Id,
                                   new Uri(saveActionDocumentResponse.ActionDocument.SharepointUrl)));
                    }
                    catch (InvalidTokenSetException ex)
                    {
                        throw new FailedToUploadGlobalXDocumentToActionstepException(
                                  $"Invalid Actionstep Token, unable to upload document. Token revoked at '{ex.TokenSet?.RevokedAt}', Token ID '{ex.TokenSet?.Id}'.",
                                  ex);
                    }
                    catch (Exception ex)
                    {
                        throw new FailedToUploadGlobalXDocumentToActionstepException(ex.Message, ex);
                    }
                }
                finally
                {
                    if (File.Exists(tempFilePath))
                    {
                        File.Delete(tempFilePath);
                    }
                }
            }
예제 #22
0
 public Task <TokenSet> GetTokenSet(TokenSetQuery tokenSetQuery)
 {
     return(Task.FromResult(TokenSets.SingleOrDefault(t => t.UserId == tokenSetQuery.UserId && t.OrgKey == tokenSetQuery.OrgKey)));
 }
예제 #23
0
 public GetCurrentUserRequest(TokenSetQuery tokenSetQuery)
 {
     TokenSetQuery = tokenSetQuery;
 }
예제 #24
0
 public Task <UploadFileResponse> UploadFile(TokenSetQuery tokenSetQuery, string fileName, string tempContentFilePath)
 {
     throw new NotImplementedException();
 }
        public async Task <bool> Handle(StorePexaWorkspaceIdInActionstepMatterCommand command, CancellationToken cancellationToken)
        {
            if (command is null)
            {
                throw new System.ArgumentNullException(nameof(command));
            }

            var tokenSetQuery = new TokenSetQuery(command.AuthenticatedUser?.Id, command.ActionstepOrg);

            var actionResponse = await _actionstepService.Handle <GetActionResponse>(new GetActionRequest
            {
                TokenSetQuery = tokenSetQuery,
                ActionId      = command.MatterId
            });

            var convdetDataCollectionFields = await _actionstepService.Handle <ListDataCollectionFieldResponse>(new ListDataCollectionFieldsRequest
            {
                DataCollectionNames = { "convdet" },
                TokenSetQuery       = tokenSetQuery,
                ActionTypes         = { actionResponse.Action.Links.ActionType }
            });

            if (!convdetDataCollectionFields.DataCollectionFields.Exists(f => f.Name == "pexa_workspace_id"))
            {
                var createDataCollectionFieldRequest = new CreateDataCollectionFieldRequest();
                var dataCollectionId = convdetDataCollectionFields.Linked.DataCollections.Single().Id;

                var dataCollectionField = new DataCollectionField
                {
                    Id              = dataCollectionId + "--pexa_workspace_id",
                    Name            = "pexa_workspace_id",
                    DataType        = "String",
                    Label           = "Pexa Workspace ID",
                    CustomHtmlAbove = "",
                    CustomHtmlBelow = "",
                    Description     = "",
                    Links           = new DataCollectionFieldLink
                    {
                        DataCollection = dataCollectionId.ToString(CultureInfo.InvariantCulture)
                    }
                };

                createDataCollectionFieldRequest.DataCollectionFields.Add(dataCollectionField);
                createDataCollectionFieldRequest.TokenSetQuery = tokenSetQuery;

                var listActionstepUsersRequest = new ListActionstepUsersRequest();
                listActionstepUsersRequest.TokenSetQuery = tokenSetQuery;

                // Add a filter to get only the authorized users
                listActionstepUsersRequest.Filter = "hasAuthority_eq=T";

                var listActionstepUsers = await _actionstepService.Handle <ListActionstepUsersResponse>(listActionstepUsersRequest);

                if (listActionstepUsers == null)
                {
                    throw new UnauthorizedAccessException("No ActionstepCredential available to create the field!");
                }
                var currentUser = listActionstepUsers.Users.FirstOrDefault(u => u.EmailAddress == command.AuthenticatedUser?.Email);

                if (currentUser == default(ActionstepUser))
                {
                    var actionstepCredential = _wCADbContext.ActionstepCredentials.FirstOrDefault(ac =>
                                                                                                  ac.ActionstepOrg.Key == command.ActionstepOrg &&
                                                                                                  listActionstepUsers.Users.Any(au => au.EmailAddress == ac.Owner.Email)
                                                                                                  );

                    if (actionstepCredential == default(ActionstepCredential))
                    {
                        throw new UnauthorizedAccessException("No ActionstepCredential available to create the field!");
                    }

                    var newTokenSetQuery = new TokenSetQuery(actionstepCredential.Owner.Id, command.ActionstepOrg);
                    createDataCollectionFieldRequest.TokenSetQuery = newTokenSetQuery;
                }

                await _actionstepService.Handle(createDataCollectionFieldRequest);
            }

            var dataCollectionRecordValuesResponse = await _actionstepService.Handle <ListDataCollectionRecordValuesResponse>(new ListDataCollectionRecordValuesRequest
            {
                ActionstepId              = command.MatterId,
                TokenSetQuery             = tokenSetQuery,
                DataCollectionRecordNames = { "convdet" },
                DataCollectionFieldNames  = { "pexa_workspace_id" }
            });

            dataCollectionRecordValuesResponse["convdet", "pexa_workspace_id"] = command.WorkspaceId;

            var updateDataCollectionRecordValuesRequest = new UpdateDataCollectionRecordValuesRequest();

            updateDataCollectionRecordValuesRequest.TokenSetQuery = tokenSetQuery;

            foreach (var recordValue in dataCollectionRecordValuesResponse.DataCollectionRecordValues)
            {
                updateDataCollectionRecordValuesRequest.DataCollectionRecordValues.Add(recordValue);
            }

            await _actionstepService.Handle(updateDataCollectionRecordValuesRequest);

            return(true);
        }
예제 #26
0
 public GetActionFolderRequest(TokenSetQuery tokenSetQuery, ActionFolder actionFolder)
 {
     TokenSetQuery = tokenSetQuery;
     ActionFolder  = actionFolder;
 }
예제 #27
0
        public async Task <string> Handle(SettlementCalculatorUrlQuery request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            string resultUrl     = string.Empty;
            var    tokenSetQuery = new TokenSetQuery(request.AuthenticatedUser?.Id, request.OrgKey);

            var actionResponse = await _actionstepService.Handle <GetActionResponse>(new GetActionRequest
            {
                TokenSetQuery = tokenSetQuery,
                ActionId      = request.MatterId
            });

            var action = actionResponse.Action;

            if (actionResponse.ActionTypeName.Equals("Conveyancing - Victoria", StringComparison.OrdinalIgnoreCase))
            {
                resultUrl += _settings.SettlementCalculatorBaseUrlVIC;
            }
            // The Konekta add-on uses "Conveyancing - NSW"
            // bytherules use "NSW Conveyancing"
            // Not using property address state as it's a free text field, to avoid issues with typos etc.
            else if (actionResponse.ActionTypeName.Equals("Conveyancing - NSW", StringComparison.OrdinalIgnoreCase) ||
                     actionResponse.ActionTypeName.Equals("NSW Conveyancing", StringComparison.OrdinalIgnoreCase))
            {
                resultUrl += _settings.SettlementCalculatorBaseUrlNSW;
            }
            else
            {
                // The QLD Action Type display name is "Conveyancing  - Queensland" (yes, with the double space).
                // The Conveyancing Action Type for BTR's org "dv4642" is just "Conveyancing".
                // However, we'll just fallback to QLD by default which will catch both of these and any others.
                resultUrl += _settings.SettlementCalculatorBaseUrlQLD;
            }

            var dataCollectionRecordValueResponse = await _actionstepService.Handle <ListDataCollectionRecordValuesResponse>(new ListDataCollectionRecordValuesRequest
            {
                TokenSetQuery             = tokenSetQuery,
                ActionstepId              = action.Id,
                DataCollectionRecordNames = { "property", "convdet", "keydates" },
                DataCollectionFieldNames  = { "lotno", "purprice", "depamount", "adjustdate", "smtdateonly", "smtven", "smttime" }
            });

            var actionParticipantsResponse = await _actionstepService.Handle <ListActionParticipantsResponse>(new ListActionParticipantsRequest
            {
                TokenSetQuery = tokenSetQuery,
                ActionstepId  = request.MatterId
            });

            var settlementVenueRawValue = dataCollectionRecordValueResponse["convdet", "smtven"];
            var settlementVenueString   = string.Empty;

            if (int.TryParse(settlementVenueRawValue, out int settlementVenueParticipantId))
            {
                var settlementVenueParticipantResponse = await _actionstepService.Handle <GetParticipantResponse>(new GetParticipantRequest
                {
                    TokenSetQuery = tokenSetQuery,
                    Id            = settlementVenueParticipantId
                });

                settlementVenueString = settlementVenueParticipantResponse?.Participant?.DisplayName;
            }

            var orgParticipantResponse = await _actionstepService.Handle <GetParticipantResponse>(new GetParticipantRequest
            {
                TokenSetQuery = tokenSetQuery,
                Id            = 4
            });

            var conveyancer     = actionParticipantsResponse["Conveyancer"].FirstOrDefault();
            var propertyAddress = actionParticipantsResponse["Property_Address"].FirstOrDefault();

            if (!resultUrl.EndsWith("/", StringComparison.OrdinalIgnoreCase))
            {
                resultUrl += "/";
            }

            resultUrl += $"{action.Id}_{request.OrgKey}";
            resultUrl += $"?id={action.Id}_{request.OrgKey}";
            resultUrl += ParamValueOrAsterisks("&matter", action.Name);
            resultUrl += ParamValueOrAsterisks("&address", propertyAddress?.DisplayName);
            resultUrl += ParseAndFormatCurrencyParam("&purprice", dataCollectionRecordValueResponse["convdet", "purprice"]);
            resultUrl += ParseAndFormatCurrencyParam("&depamount", dataCollectionRecordValueResponse["convdet", "depamount"]);
            resultUrl += ParseAndFormatDateParam("&adjustdate", dataCollectionRecordValueResponse["keydates", "adjustdate"]);
            resultUrl += ParseAndFormatDateParam("&settledate", dataCollectionRecordValueResponse["keydates", "smtdateonly"]);
            resultUrl += ParamValueOrAsterisks("&lc", conveyancer?.Email);
            resultUrl += ParamValueOrAsterisks("&div", orgParticipantResponse?.Participant?.CompanyName);
            resultUrl += ParamValueOrAsterisks("&smtloc", settlementVenueString);
            resultUrl += ParamValueOrAsterisks("&smttime", dataCollectionRecordValueResponse["convdet", "smttime"]);

            return(resultUrl);
        }