/// <summary>
        /// Returns a list of registered transaction types that are applicable based on the current context record and the limitations
        /// imposed by the agent and channel associated with the work session.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="contextRecord"></param>
        /// <returns></returns>
        public IReadOnlyList <ITransactionType> GetAvaialbleTransactionTypes(IProcessExecutionContext executionContext, IWorkSession session, ITransactionContext transactionContext)
        {
            try
            {
                executionContext.Trace("Getting Transaction Types for context record type {0} and status {1}", transactionContext.RecordType, transactionContext.RecordStatus);

                var availableTransactions = RegisteredTransactionTypes
                                            .Where(t => session.SupportsChannel(t.AuthorizedChannels) &&
                                                   session.HasRole(t.AuthorizedRoles) &&
                                                   session.CanOperateAgainstCustomer(transactionContext.Customer) &&
                                                   transactionContext.IsContextType(t.EligibleContexts))
                                            .OrderBy(t => t.Group.DisplayRank)
                                            .ThenBy(t => t.Group.Name)
                                            .ThenBy(t => t.DisplayRank)
                                            .ThenBy(t => t.Name)
                                            .ToList();

                executionContext.Trace("Returning {0} eligible Transaction Types out of {1} registered Transaction Types", availableTransactions.Count, RegisteredTransactionTypes.Count);

                return(availableTransactions);
            }
            catch (Exception)
            {
                throw;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns all registered <see cref="ITransactionProcess"/> items in the system. Each item is fully configured with all associated
        /// <see cref="IProcessStep"/> items.
        /// </summary>
        /// <param name="executionContext"></param>
        /// <param name="cacheTimeout"></param>
        /// <returns></returns>
        private IList <ITransactionProcess> getProcesses(IProcessExecutionContext executionContext, bool useCache)
        {
            try
            {
                IList <ITransactionProcess> registeredProceses = new List <ITransactionProcess>();

                var processes = DataConnector.GetAllTransactionProcesses(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Process records.", processes.Count);

                var processSteps = getProcessSteps(executionContext, useCache);

                foreach (var process in processes)
                {
                    executionContext.Trace("Building Transaction Process {0}", process.Name);

                    var steps = processSteps.Where(s => s.TransactionProcessPointer.Id == process.Id);

                    registeredProceses.Add(
                        this.TransactionProcessFactory.CreateTransactionProcess(
                            executionContext, process,
                            process.Name,
                            process.TransactionTypeId ?? throw TransactionException.BuildException(TransactionException.ErrorCode.ProcessInvalid),
                            process.InitialProcessStepId ?? throw TransactionException.BuildException(TransactionException.ErrorCode.ProcessInvalid),
                            steps,
                            useCache));
                }

                return(registeredProceses);
            }
            catch (Exception)
            {
                throw;
            }
        }
Ejemplo n.º 3
0
        public IAgent BuildAgent(IProcessExecutionContext executionContext, IRecordPointer <Guid> agentId, bool useCache = true)
        {
            try
            {
                if (executionContext is null)
                {
                    throw new ArgumentNullException("executionContext");
                }
                if (agentId is null)
                {
                    throw new ArgumentNullException("agentId");
                }

                var cacheTimeout = useCache ? getCacheTimeout(executionContext) : null;

                useCache = useCache && executionContext.Cache != null && cacheTimeout != null;

                string cacheKey = null;
                if (useCache)
                {
                    cacheKey = CACHE_KEY + ".Agent." + agentId.Id.ToString();
                    if (executionContext.Cache.Exists(cacheKey))
                    {
                        executionContext.Trace("Returning Agent from Cache.");
                        return(executionContext.Cache.Get <IAgent>(cacheKey));
                    }
                }

                var agentRecord = DataConnector.GetAgentRecord(executionContext.DataService, agentId);

                var roles = DataConnector.GetAgentRoles(executionContext.DataService, agentId);

                var authorizedCustomers = DataConnector.GetAgentRoles(executionContext.DataService, agentId);

                var prohibitedCustomers = DataConnector.GetAgentProhibitedCustomers(executionContext.DataService, agentId);

                var agent = new Agent(agentRecord, roles, authorizedCustomers, prohibitedCustomers);

                if (cacheKey != null)
                {
                    executionContext.Trace("Caching Agent for {0}", cacheTimeout.Value);
                    executionContext.Cache.Add <IAgent>(cacheKey, agent, cacheTimeout.Value);
                }

                return(agent);
            }
            catch (Exception)
            {
                throw;
            }
        }
        private IProcessStep getNextStep(IProcessExecutionContext executionContext, ITransaction transaction)
        {
            try
            {
                if (IsLastStep())
                {
                    return(null);
                }

                if (Type.IsConditional)
                {
                    executionContext.Trace("Evaluating {0} conditional branches.", this.AlternateBranches.Count);

                    foreach (var branch in this.AlternateBranches.OrderBy(b => b.EvaluationOrder))
                    {
                        var evaluationResult = branch.Evaluate(executionContext, transaction);
                        if (evaluationResult.Passed)
                        {
                            executionContext.Trace("Selected branch {0}", branch.Name);

                            if (branch.SubsequentStepPointer != null)
                            {
                                var branchStep = transaction.CurrentProcess.ProcessSteps.Where(r => r.Id == branch.SubsequentStepPointer.Id).FirstOrDefault();
                                if (branchStep is null)
                                {
                                    throw TransactionException.BuildException(TransactionException.ErrorCode.ProcessNotFound);
                                }

                                return(branchStep);
                            }

                            break;
                        }
                    }
                }

                var nextStep = transaction.CurrentProcess.ProcessSteps.Where(r => r.Id == this.SubsequentStepPointer.Id).FirstOrDefault();
                if (nextStep == null)
                {
                    throw TransactionException.BuildException(TransactionException.ErrorCode.ProcessStepNotFound);
                }

                return(nextStep);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }
Ejemplo n.º 5
0
        public IAgent BuildAgent(IProcessExecutionContext executionContext, ISystemUser userId, bool useCache = true)
        {
            try
            {
                if (executionContext is null)
                {
                    throw new ArgumentNullException("executionContext");
                }
                if (userId is null)
                {
                    throw new ArgumentNullException("userId");
                }

                var cacheTimeout = useCache ? getCacheTimeout(executionContext) : null;

                useCache = useCache && executionContext.Cache != null && cacheTimeout != null;
                string cacheKey = null;

                IRecordPointer <Guid> agentId = null;

                if (useCache)
                {
                    cacheKey = CACHE_KEY + ".AgentUserMap." + userId.Id.ToString();
                    if (executionContext.Cache.Exists(cacheKey))
                    {
                        agentId = executionContext.Cache.Get <IRecordPointer <Guid> >(cacheKey);
                    }
                }

                if (agentId is null)
                {
                    agentId = DataConnector.GetUserAgentRecord(executionContext.DataService, userId);

                    if (agentId is null)
                    {
                        throw new Exception("The user does not have an assigned Agent record.");
                    }

                    if (useCache)
                    {
                        executionContext.Cache.Add <IRecordPointer <Guid> >(cacheKey, agentId, cacheTimeout.Value);
                        executionContext.Trace("Cached User Agent Map for {0}", cacheTimeout.Value);
                    }
                }

                return(BuildAgent(executionContext, agentId, useCache));
            }
            catch (Exception)
            {
                throw;
            }
        }
Ejemplo n.º 6
0
        public ICustomer CreateCustomer(IProcessExecutionContext executionContext, IRecordPointer <Guid> customerId, bool useCache = true)
        {
            try
            {
                if (executionContext is null)
                {
                    throw new ArgumentNullException("executionContext");
                }
                if (customerId is null)
                {
                    throw new ArgumentNullException("customerId");
                }

                var cacheTimeout = useCache ? getCacheTimeout(executionContext) : null;

                useCache = useCache && executionContext.Cache != null && cacheTimeout != null;
                string cacheKey = null;

                if (useCache)
                {
                    cacheKey = CACHE_KEY + customerId.RecordType + customerId.Id.ToString();

                    if (executionContext.Cache.Exists(cacheKey))
                    {
                        executionContext.Trace("Returning Customer from Cache.");
                        return(executionContext.Cache.Get <ICustomer>(cacheKey));
                    }
                }
                var customerRecord = DataConnector.GetCustomerRecord(executionContext.DataService, customerId);

                var customerClasses = DataConnector.GetCustomerClasses(executionContext.DataService, customerId);


                var customer = new Customer(customerRecord, customerClasses);

                if (cacheKey != null)
                {
                    executionContext.Cache.Add <ICustomer>(cacheKey, customer, cacheTimeout.Value);
                }

                return(customer);
            }
            catch (Exception)
            {
                throw;
            }
        }
        public IList <IChannel> GetChannels(IProcessExecutionContext executionContext, bool useCache = true)
        {
            try
            {
                useCache = useCache && executionContext.Cache != null;

                TimeSpan?cacheTimeout = null;
                string   cacheKey     = null;

                if (useCache)
                {
                    var settings = SettingsFactory.CreateSettings(executionContext.Settings);
                    cacheTimeout = settings.ChannelCacheTimeout;
                    cacheKey     = CACHE_KEY + "GetChannels";

                    if (executionContext.Cache.Exists(cacheKey))
                    {
                        executionContext.Trace("Returned Channels from cache.");
                        return(executionContext.Cache.Get <IList <IChannel> >(cacheKey));
                    }
                }

                var channelRecords = DataConnector.GetChannelRecords(executionContext.DataService);

                var partners = this.GetPartners(executionContext, useCache);

                IList <IChannel> channels = new List <IChannel>();
                foreach (var record in channelRecords)
                {
                    var partner = record.PartnerId is null ? null : partners.Where(r => r.Id == record.PartnerId.Id).FirstOrDefault();
                    channels.Add(new Channel(record, partner));
                }

                if (useCache)
                {
                    executionContext.Cache.Add(cacheKey, channels, cacheTimeout.Value);
                }

                return(channels);
            }
            catch (Exception)
            {
                throw;
            }
        }
Ejemplo n.º 8
0
        public override IUIPointer GetUIPointer(IProcessExecutionContext executionContext, ITransaction transaction, ISerializedParameters parameters)
        {
            try
            {
                var dataRecord = transaction.DataRecord;
                executionContext.Trace("Creating UI Pointer for retrieved data record.");

                return(new UIPointer
                {
                    UIType = eUIStepTypeEnum.DataForm,
                    UIRecordType = dataRecord.RecordType,
                    UIRecordId = dataRecord.Id,
                    UIDefinition = parameters["FormId"]
                });
            }
            catch (Exception ex) {
                throw new Exception(ex.Message, ex);
            }
        }
        public IList <IPartner> GetPartners(IProcessExecutionContext executionContext, bool useCache = true)
        {
            try
            {
                useCache = useCache && executionContext.Cache != null;

                TimeSpan?cacheTimeout = null;
                string   cacheKey     = null;

                if (useCache)
                {
                    var settings = SettingsFactory.CreateSettings(executionContext.Settings);
                    cacheTimeout = settings.PartnerCacheTimeout;
                    cacheKey     = CACHE_KEY + "GetPartners";

                    if (executionContext.Cache.Exists(cacheKey))
                    {
                        executionContext.Trace("Returned Partners from cache.");
                        return(executionContext.Cache.Get <IList <IPartner> >(cacheKey));
                    }
                }

                IList <IPartner> partners = DataConnector.GetPartnerRecords(executionContext.DataService);

                if (useCache)
                {
                    executionContext.Cache.Add(cacheKey, partners, cacheTimeout.Value);
                }

                return(partners);
            }
            catch (Exception)
            {
                throw;
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Builds a new Transaction Service preloaded with all available Transaction Type configurations.
        /// </summary>
        /// <param name="executionContext"></param>
        /// <param name="cacheTimeOut">Sets amount of time to cache the transaction service to service future build requests. When null, caching is not used.</param>
        /// <returns></returns>
        public ITransactionService CreateTransactionService(IProcessExecutionContext executionContext, bool useCache = true)
        {
            try
            {
                useCache = useCache && executionContext.Cache != null;

                if (useCache)
                {
                    if (executionContext.Cache.Exists(CACHE_KEY))
                    {
                        executionContext.Trace("Returning Transaction Service from cache.");
                        return(executionContext.Cache.Get <ITransactionService>(CACHE_KEY));
                    }
                }



                IList <ITransactionType> registeredTransactions = new List <ITransactionType>();

                var transactionTypeRecords = DataConnector.GetAllTransactionTypeRecords(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Type records.", transactionTypeRecords.Count);

                // get all active records that are needed to fully define a transaction type. This includes complex objects for ITransactionProcess
                // and ITransactionRequirements as well as simpler objects for transaction groups, authorized channels, authorized roles,
                // initial fees, and eligible record contexts.
                var processes = getProcesses(executionContext, useCache);

                var requirements = getRequirements(executionContext, useCache);

                var transactionGroups = DataConnector.GetAllTransactionGroups(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Group records.", transactionGroups.Count);

                var authorizedChannels = DataConnector.GetAllTransactionAuthorizedChannels(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Authorized Channel records.", authorizedChannels.Count);

                var authorizedRoles = DataConnector.GetAllAuthorizedRoles(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Authorized Role records.", authorizedRoles.Count);

                var initialFees = DataConnector.GetAllInitialFees(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Initial Fee records.", initialFees.Count);

                var contexts = DataConnector.GetAllTransactionContextTypes(executionContext.DataService);
                executionContext.Trace("Retrieved {0} Transaction Type Context records.", contexts.Count);

                // Create a new TransactionType object for each transaction type retrieved.
                foreach (ITransactionTypeRecord t in transactionTypeRecords)
                {
                    executionContext.Trace("Processing transaction type '{0}'", t.Name);

                    ISerializedParameters dataRecordConfig = null;
                    try
                    {
                        executionContext.Trace("Parsing Data Record Configuration.");
                        dataRecordConfig = this.ParameterSerializer.CreateParamters(t.DataRecordConfiguration);
                        if (!dataRecordConfig.ContainsKey("RecordType"))
                        {
                            throw new Exception("Missing RecordType.");
                        }
                        if (!dataRecordConfig.ContainsKey("CustomerField"))
                        {
                            throw new Exception("Missing Customer Field");
                        }
                        if (!dataRecordConfig.ContainsKey("TransactionField"))
                        {
                            throw new Exception("Missing Transaction Field");
                        }
                        if (!dataRecordConfig.ContainsKey("NameField"))
                        {
                            throw new Exception("Missing Name Field");
                        }
                    }
                    catch (Exception ex)
                    {
                        throw TransactionException.BuildException(TransactionException.ErrorCode.ProcessStepTypeInvalid, ex);
                    }

                    registeredTransactions.Add(new TransactionType(
                                                   t,
                                                   t.Name,
                                                   t.DisplayRank,
                                                   transactionGroups.Where(r => t.TransactionGroupId != null && r.Id == t.TransactionGroupId.Id).FirstOrDefault(),
                                                   t.StartupProcessId ?? throw new Exception("Transaction type is missing a startup process id."),
                                                   dataRecordConfig,
                                                   authorizedChannels.Where(r => r.ParentId.Id == t.Id).Select(r => r.ChannelId),
                                                   authorizedRoles.Where(r => r.ParentId.Id == t.Id).Select(r => r.RoleId),
                                                   processes.Where(r => r.TransactionTypeId.Id == t.Id),
                                                   requirements.Where(r => r.TransactionTypeId.Id == t.Id),
                                                   initialFees.Where(r => r.TransactionTypeId.Id == t.Id).Select(r => r.FeeId),
                                                   contexts.Where(r => r.TransactionTypeId.Id == t.Id)));
                }

                executionContext.Trace("Creating Transaction Service loaded with {0} Transaction Types.", registeredTransactions.Count);

                // Create a new transaction service and pass in required factory and record services.
                var transactionService = new TransactionService(this.DataConnector, this.AgentFactory, this.TransactionFeeListFactory, this.TransactionContextFactory, this.CustomerFactory, this.TransactionDeficienciesFactory,
                                                                this.DocumentService, this.EvidenceService, this.LocationFactory, RequirementEvaluator, this.TransactionHistoryFactory, this.FeeList, registeredTransactions);

                if (useCache)
                {
                    var settings     = SettingsFactory.CreateSettings(executionContext.Settings);
                    var cacheTimeout = settings.PlatformServiceCacheTimeout;

                    executionContext.Cache.Add <ITransactionService>(CACHE_KEY, transactionService, cacheTimeout.Value);
                    executionContext.Trace("Cached Transaction Service for {0}.", cacheTimeout.Value);
                }

                executionContext.TrackEvent("TransactionServiceFactory.BuildTransactionService");

                return(transactionService);
            }
            catch (Exception)
            {
                throw;
            }
        }
        public ITransactionDataRecord LoadTransactionDataRecord(IProcessExecutionContext executionContext, ITransaction transaction)
        {
            try
            {
                if (executionContext is null)
                {
                    throw new ArgumentNullException("executionContext");
                }
                if (transaction is null)
                {
                    throw new ArgumentNullException("transaction");
                }


                var dataRecordConfig = transaction.TransactionType.TransactionDataRecordType;
                if (dataRecordConfig is null)
                {
                    throw TransactionException.BuildException(TransactionException.ErrorCode.ProcessStepTypeInvalid);
                }

                var dataRecordType = dataRecordConfig["RecordType"];

                int    underScoreIndex = dataRecordType.IndexOf("_");
                string prefix          = dataRecordType.Substring(0, underScoreIndex + 1);

                // Get required field names form configuration data if provided, otherwise use conventional field names.
                var nameField        = dataRecordConfig.ContainsKey("NameField") ?  dataRecordConfig["NameField"] : prefix + "name";
                var transactionField = dataRecordConfig.ContainsKey("TransactionField") ?  dataRecordConfig["TransactionField"] : prefix + "transactionid";
                var customerField    = dataRecordConfig.ContainsKey("CustomerField") ?  dataRecordConfig["CustomerField"] : prefix + "customerid";

                var record = DataConnector.GetFirstMatchingTransactionDataRecord(
                    executionContext.DataService,
                    transaction,
                    dataRecordType,
                    nameField,
                    transactionField,
                    customerField);

                if (record is null)
                {
                    // All configuration values that do not represent the record type, name field, transaction field,
                    // and customer field names are assumed to be attribute field names and associated default values.
                    var defaultValues = (dataRecordConfig as IReadOnlyDictionary <string, string>)
                                        .Where(r => r
                                               .Key != "RecordType" &&
                                               r.Key != "NameField" &&
                                               r.Key != "TransactionField" &&
                                               r.Key != "CustomerField" &&
                                               r.Value != null).ToDictionary(r => r.Key, r => r.Value);

                    record = DataConnector.NewTransactionDataRecord(
                        executionContext.DataService,
                        transaction,
                        dataRecordType,
                        nameField,
                        transactionField,
                        customerField,
                        transaction.Name,
                        transaction.Customer,
                        defaultValues);

                    executionContext.Trace("Created new data record of type {0} for transaction {1}", dataRecordType, transaction.Id);
                }

                return(record);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public override ILogicEvaluationResult Evaluate(IProcessExecutionContext executionContext, ISerializedParameters parameters, Platform.ITransaction transaction)
        {
            executionContext.Trace("DataRecordQueryMatchEvaluator is Evaluating.");

            if (executionContext is null)
            {
                throw new ArgumentNullException("executionContext");
            }
            if (executionContext.Container is null)
            {
                throw new ArgumentException("executionContext must provide a Container.");
            }
            if (parameters is null)
            {
                throw new ArgumentNullException("parameters");
            }
            if (transaction is null)
            {
                throw new ArgumentNullException("transaction");
            }
            if (!(transaction is ITransaction))
            {
                throw new ArgumentException("transaction does not represent a valid Process Transaction.");
            }

            ValidateParameters(executionContext, parameters);


            var dataRecord = (transaction as ITransaction).DataRecord;


            var orgService = executionContext.DataService.ToOrgService();

            var fetchXml = parameters["FetchXml"];

            //convert the fetchxml to a query expression
            var req = new FetchXmlToQueryExpressionRequest
            {
                FetchXml = fetchXml
            };

            var resp = (FetchXmlToQueryExpressionResponse)orgService.Execute(req);
            var qry  = resp.Query;

            qry.NoLock = true;

            // Wrap the existing filter criteria with an AND clause where record id is equal to the current record. When
            // the query is run it will either return one record indicating that the current data record matches the filter
            // criteria or it will return zero record indicating that the current record does not match the filter criteria.
            var idFieldName = qry.EntityName + "id";

            FilterExpression wrapperFilter = new FilterExpression {
                FilterOperator = LogicalOperator.And,
                Conditions     =
                {
                    new ConditionExpression
                    {
                        AttributeName = idFieldName,
                        Operator      = ConditionOperator.Equal,
                        Values        = { dataRecord.Id }
                    }
                }
            };

            if (qry.Criteria != null)
            {
                wrapperFilter.Filters.Add(qry.Criteria);
            }

            qry.Criteria = wrapperFilter;

            // Execute the query to see if a record is returned or not
            var results = orgService.RetrieveMultiple(qry);

            executionContext.Trace("DataRecordQueryMatchEvaluator found {0} matching records", results.Entities.Count);

            if (results.Entities.Count == 1)
            {
                return(new LogicEvaluationResult(true, null));
            }

            return(new LogicEvaluationResult(false, null));
        }