Jump to content

QESTNET Internal:Developer QESTNET Creating A New Workflow: Difference between revisions

From QESTonline
John.meegan (talk | contribs)
No edit summary
John.meegan (talk | contribs)
No edit summary
Line 173: Line 173:


Create an Entity Plan:
Create an Entity Plan:
* These are done in the constructor of the WorkflowFactory
* These names may change so inspect the constructor of the SteelReinforcingWorkflowFactory for an example.
* These are used to specify which Entities need to exist on a Work Order for the Workflow to be valid
* These are used to specify which Entities need to exist on a Work Order for the Workflow to be valid
* They can optionally load the relations/endpoints on the Entities automatically while doing this test. This means you don't have to do it manually later.
* They can optionally load the relations/endpoints on the Entities automatically while doing this test. This means you don't have to do it manually later.
* Use either a LoadableEntityPlan or EntityPlan for this.
* Use either a LoadableEntityPlan or EntityPlan for this.
* These names may change so inspect the constructor of the SteelReinforcingWorkflowFactory for an example.
* See the AsConcreteWorkflowFactory for an example that does not automatically load, which manually loads relations in the CreateWorkflow() function.
* See the AsConcreteWorkflowFactory for an example that does not automatically load, which manually loads relations in the CreateWorkflow() function.
* Note that some relations can't be loaded with a plan, any time the relation is a collection, e.g. specimens. This is because the Workflow will be considered invalid if there are no specimens, and as zero is usually valid, the Workflow will never appear.
* Note that some relations can't be loaded with a plan, any time the relation is a collection, e.g. specimens. This is because the Workflow will be considered invalid if there are no specimens, and as zero is usually valid, the Workflow will never appear.
Line 183: Line 184:
* Find the file in the "/Deployment" folder at the top level named QESTField.Enable_Workflows.XXXXX.sql
* Find the file in the "/Deployment" folder at the top level named QESTField.Enable_Workflows.XXXXX.sql
* Add a line with the Guid in it here
* Add a line with the Guid in it here
Set up Workflow Phases:
* ... more here
===QESTLab.Repository: Work Template / QESTLab.Workflow: Processes===
Create a Work Template for your Workflow:
* This includes all the Entities you need to create when the user creates a new instance of this Workflow
* Copy existing examples to get the idea. You start with a Work Order and add Entities to it.
* In the "Work Templates" folder
Set up processes to invoke the workflow:
* These get turned into buttons in QF
* You may need to make a new bundle if a relevant one does not exist
===QESTLab.Workflow: Container Factories / QESTLab.Models===
Models...
It makes sense to create these together.
* Talk about tags, styles, processes
* Talk about the action transfer to / from functions used on model containers
** 2 important types of containers, regular and model
Container Factories can either by direct mapping or workspaces. We typically call them workspaces although this is not a necessity.
==QESTField==
* Create views
** Views can be tweaked by the styles and tags provided from the container
* Update the global.asax file to include the new view folders (if you created new folders)
* Update the WorkflowController to route any workspace containers to specific views.

Revision as of 04:59, 21 October 2015

This page outlines the steps required to create a new workflow in QESTNET (QN) and QESTField (QF).

Introduction

Workflows are similar to QESTLab (QL) Test Screens, except they can be made up of more than one Document. Workflows encapsulate data entry for a Work Order, an optional Sample, and any number of Documents. A typical Workflow still consists of a Work Order and one parent Sample with one Document on it. When designing a Workflow you must consider how this structure should be set up. A lot of the Workflows have the sample details and test details on one big page. Sometimes it makes more sense to break it up into multiple pages. Sometimes these decisions are customer-driven.

In QN every database table is mapped to an "Entity", which is a Microsoft term used by their Entity Framework technology. As a result; Work Orders, Samples, Documents, etc are really just types of Entities. So Workflows actually just encapsulate data entry for any number of Entities.

Each Workflow is created and edited via buttons in QF. These buttons typically appear on the Work Order Workflow.

[screenshot]

Workflows are broken up into lots of small pieces, rather than being all in one control such as in QL.

If you review the QESTNET Projects Quick Reference Guide you will see there are 2 types of Entities, for the QESTLab.Data project and the QESTLab.Entities project. When coding Workflows you only concern yourself with the latter type, which is mapped back to the data level automatically.

Work Order Workflows can be created on QF's search screen or in QL. After creating a new Work Order or opening an existing one, other Workflows can be created or edited based on the following criteria:

  • The Workflow has been licensed via a script for the customer, at the laboratory for the Work Order you are viewing. (Details on how to set this up will be covered when creating the WorkflowFactory later.)
  • Each Workflow has a loading plan that lists the required Entities for it to be valid. These Entities must be present under the Work Order somewhere.

Note that this last point means creating a new Workflow with a number of Entities may make multiple other Workflows appear for editing, if they use the same Entities. This allows us to provide multiple ways of editing the same set of data, tailored to specific customer workflows.

The remainder of this guide will cover how to create the required functionality for a Workflow at each level of QN/QF. Almost all of the QN work is done in the QESTNET.Sessions.Lab solution, when searching for where to make changes this is the place to look. You can refer to the following article for an overview of the projects within this solution: QESTNET Projects Quick Reference Guide.


Initial Configuration

Make the usual QL items:

  • Review the specification or standards to understand what needs implementing
  • Create all required qestlab.qes objects (tests, lists, etc.)
    • Here you need to decide if the test should have the "SIUnitsBase" property (or similar name). It is only valid for tests that will not be used in QL. More on units later.
  • Make initial database tables, even if they just have the standard fields

Use the qestnet.upgrade tool:

  • Make sure you have the appropriate qestnet.upgrade branch checked out for making changes on
  • Generate the table and qestObject scripts
  • Selectively commit the lines that are relevant to your changes and no others, for both tables and qestObjects
  • Most tables will be automatically activated for use in QN/QF. Edit the qestnet.upgrade scripts to make any required manual changes either way. Usually there isn't much.
  • Upgrade your development database of choice with these changes

Prepare the QESTNET Schema Generator Tool:

  • This can be found under "QESTNET/QESTNET.Sessions.Lab/QESTLab.SchemaGenerator/QESTLab.SchemaGenerator.sln"
  • Your development database must have some scripts installed for this tool to work, they are found in the "scripts" folder which is next to the solution file above. Run these scripts on your database once, if they haven't already been ran.
  • Add any new test tables to the tool:
    • Open the solution
    • Open the "schema > ConfigHelper.cs" file
    • Add your test to the GetDocumentNames() function
    • You only need list tables in here if you intend to use them with Entities, which we do not 99% of the time, so I do not advise adding list tables.
  • Save and compile the Schema Generator Tool


QESTNET Changes

QESTLab.Data Schema Update

Update the QESTLab.Data schema to match the QL database structure:

  • Run GenerateDataSchema.ps1
  • Build QESTLab.Data project
    • If you receive errors similar to 'Source file "Entities\UserDocument100.cs" could not be found' at this point, right click EntityGenerator.tt, select Run Custom Tool, then rebuild QESTLab.Data.
  • Right click QESTLab_Data_Views.tt and select Run Custom Tool
  • Build QESTLab.Data project

Note that we only include tables we need to in QN. This provides some improved performance and reduces code clutter a bit.

QESTLab.Entities

Create your Entities:

  • Create files in the appropriate folder, following how the others are done.
  • The end of the name should be the type of Entity, Test, Inspection, List, Sample, etc.
  • Entities should not have any real logic in them, except simple properties that are derived from other fields. For example if you need a value, and an inverse of that same value, there is no point saving both. A small property with logic to calculate it can be used instead.
  • The easiest way to add fields is to open the corresponding Entity in the QESTLab.Data project and copy + paste from there.
  • You only need to add fields that are not part of the standard set, as these are covered by the inheritance structure.

Entities represent idealised database tables which means:

  • Field names can be different to what's actually in the database
  • You can have additional fields that don't exist in the database, but are only used in code.

Set the valid QestIDs:

  • At the top of each Entity is a list of the valid QestIDs for that Entity. Add / edit yours.
    • This is stored in what's known as a C# Attribute, this is fancy programming that allows us to write code about our code. C# supports what's known as reflection, a technique to inspect your code with other code. So we can write some behaviour that says "if the user is using this entity, check that it has this QestID". Beyond the scope of what we're doing a bit, but you can Google around for more information.

Set the relations or endpoints between Entities:

  • Relation and Endpoint are mostly the same thing, but terminology will be used interchangably.
  • Each entity is linked to others. The historical example is Work Orders have child Samples, that have child Tests.
  • Unlike QL's tree structure, QN allows a graph structure - every Entity can link to an arbitrary number of others.
    • We mostly stick to trees for simplicity
    • For QESTLab compatibility you must stick to trees, and to the "Work Order - Sample - Document" structure.
  • Follow the style of the existing Entities to create your required relationships.
  • The [QestParent] attribute specifies which relationship points to a parent. So for example the Sample will have [QestParent] on the Work Order relation. Set parents for QL compatibility and for setting the database fields QestParentID, QestUniqueParentID.
  • An Entity can either be linked to 1 or many other Entities of a similar kind, for example Work Orders have multiple Samples. You need to specify the relationship type here.
  • Relations are manually loaded to avoid loading too much into memory. This will be discussed more later.
  • You get some extra relations for free because of the inheritance on Entities.

Replace all field types with Units of Measure (UOM) unit types:

  • UOM allows us to use things like "Mass" rather than "double" for a field type
  • This allows us to optionally save the data in SI units, as well as display it in various forms like kilograms, grams, etc.
  • Replace where relevant "double?"s with Mass?, Length?, Pressure?, Force?, etc.
    • Note the "?" means it is allowed to be null, most database fields are nullable so this should be included.

QESTLab.Repository: Update for the new Entities

At the time of writing, a lot of code is not yet automated to allow Entities to run seamlessly. Follow these steps to make the Entities you have created functional.

This project will expose you to the Entity Context, this is similar to the QLO in QL. All tests in the database can be accessed and loaded here, along with a number of other things.

In the respository project...

Update the Entity Mappings:

  • This is used to map your QESTLab.Entities Entity to the QESTLab.Data Entity.
  • In the Entity Mappings folder is 3 files
  • Copy the existing style to add your entities in here
  • Any Entity that uses UOM needs special handling to include a UOM mapper, you will notice properties that have this on the end: ".Include(units[typeof(Torvane).Name])".
  • Look at similar Entities to figure out how to do this
  • You will need special handling here if you have:
    • Created Entity field names that are different from the database field names
    • Created additional properties or methods on the Entity

Update the Entity Queries:

  • In the Entity Queries folder there is 1 file
  • This file helps load relationships between Entities
  • Follow how the other code is done here, make similar code for your Entities. Keep in mind the relationship between two Entities can either be 1 or Many. The functions here need to change depending on which it is.

Update the Unit Mappings:

  • In the "Unit Mappings" folder.
  • By this point you should know if you're going to be saving all values in SI Base, or if it needs to work in QL as well.
  • Under the "Entities" sub-folder, a class needs to be created for each Entity you have with UOM units on it:
    • These provide default configuration for the units.
    • Copy the way others are done.
    • The main thing to remember is for compatibility with QL screens, we provide a set of defaults for the units for each field in the database. For example, traditionally MDD tests have saved masses in grams so we set grams as the default for each of the mass fields. In contrast to this an SI base test would save these values in kilograms. These defaults are set by logic so you can have different defaults for IP units, different QestIDs, etc.
    • Implement applicable methods: GetSIBase(), GetMetric(), GetIP(), etc. Each defines what each unit is used for storing in the database. The dictionary that is chosen for a test depends on what units that test stores in its database fields.
    • Modify GetUnits appropriately
  • Add call in UnitMapper.SetupUnits
  • Add code to UnitsDataConfiguration and UnitsToEntityConfiguration
  • The following commit is a good example: https://github.com/spectraqest/qestnet/commit/f78e8112969ada3c21bbb7c700155b28e0a4719f


We hope to automate a lot of this work eventually.


QESTLab.Entities.Rules

This step can optionally be done last if it's easier to get a "dumb" workflow up and running just to test everything. It is fairly isolated from the rest of the process.

Rules are similar to QL BusinessRules.

Each Entity has a Master Rule:

  • This rule invokes all the individual calculations as necessary
  • This rule should have the MasterRule attribute applied to the class's definition, eg:
    • [MasterRule(typeof(DailyFieldInspection))]
    • public sealed class RuleDailyFieldInspection : CodeActivity
  • There are some standard things in every rule (or most rules):
    • Run RuleSetPerformedBy - Required if you need to work with TestStages or if you need to set the completion status, this applies to most tests. Each test has its own RuleSetPerformedBy that you have to make.
    • Check loaded endpoint relations - Rules should only run if all the Entities and their relationships have been loaded, otherwise you'll get null pointer exceptions.
    • Propogate delete actions - Because our Entity relationships make a graph not a tree structure, it is difficult to know what should be deleted when a single test is deleted. The rules for a single Entity should propogate a delete to all related Entities where it makes sense.

Rules need to run fast which means:

  • They should be written wisely, they could be run multiple times each calculate
  • Use Change Tracking to check what the user has changed, to see if rules need to be run at all

Rules have 2 input variables:

  • The context, or QestEntityContext. This is similar to the QLO and gives you access to things like loading lists, running procedures on the database, loading additional Entities, Documents, database data, etc.
  • The Entity that the rule applies to. You can still read/write to related Entities however, but be careful to do so only when it makes sense. It is usually better to only affect the Entity the rule is for.

Create your entity rules:

  • Break up the the calculations in a logical way
  • Use one class for each calculation
  • Namespace the rules appropriately
  • Look at others for examples


QESTLab.Workflow: Workflow Factory

Create a new Workflow Factory:

  • In the Workflow Factories folder
  • Find a good spot, copy an existing example. Some are Fugro-specific these are not usually useful for other customers.
  • You can create a separate factory for each Method you want to create, if they all use the same basica Workflow and Entities. See the SteelReinforcingWorkflowFactory for an example. Each Method has its own Guid so the methods can be individually licensed.
  • Generate a new GUID attribute for the WorkflowFactory - this is the ID used in licensing the Workflow
    • This can be done in Visual Studio by going to "Tools > Create Guid"

Create an Entity Plan:

  • These are done in the constructor of the WorkflowFactory
  • These names may change so inspect the constructor of the SteelReinforcingWorkflowFactory for an example.
  • These are used to specify which Entities need to exist on a Work Order for the Workflow to be valid
  • They can optionally load the relations/endpoints on the Entities automatically while doing this test. This means you don't have to do it manually later.
  • Use either a LoadableEntityPlan or EntityPlan for this.
  • See the AsConcreteWorkflowFactory for an example that does not automatically load, which manually loads relations in the CreateWorkflow() function.
  • Note that some relations can't be loaded with a plan, any time the relation is a collection, e.g. specimens. This is because the Workflow will be considered invalid if there are no specimens, and as zero is usually valid, the Workflow will never appear.

Update the customer's license script to include the new Workflow Guid:

  • Find the file in the "/Deployment" folder at the top level named QESTField.Enable_Workflows.XXXXX.sql
  • Add a line with the Guid in it here

Set up Workflow Phases:

  • ... more here


QESTLab.Repository: Work Template / QESTLab.Workflow: Processes

Create a Work Template for your Workflow:

  • This includes all the Entities you need to create when the user creates a new instance of this Workflow
  • Copy existing examples to get the idea. You start with a Work Order and add Entities to it.
  • In the "Work Templates" folder

Set up processes to invoke the workflow:

  • These get turned into buttons in QF
  • You may need to make a new bundle if a relevant one does not exist


QESTLab.Workflow: Container Factories / QESTLab.Models

Models...

It makes sense to create these together.

  • Talk about tags, styles, processes
  • Talk about the action transfer to / from functions used on model containers
    • 2 important types of containers, regular and model

Container Factories can either by direct mapping or workspaces. We typically call them workspaces although this is not a necessity.


QESTField

  • Create views
    • Views can be tweaked by the styles and tags provided from the container
  • Update the global.asax file to include the new view folders (if you created new folders)
  • Update the WorkflowController to route any workspace containers to specific views.