Introduction

SimpleMES is THE open source Manufacturing Execution System (MES). The goal of this open source project is to simplify the complex and time-consuming task of implementing a traditional MES. The main features are:

  • Almost no setup is required.

  • Easy configuration.

  • Easy customization.

SimpleMES can be used with or without an ERP system. You can start without an ERP system and later configure the MES to work with an ERP system. It is possible to mix ERP and non-ERP orders and other features as you need.

For a detailed explanation of the many options and features, see the Reference . The Groovy API for the SimpleMES contains details on all fields and methods for most objects/services.

This MES is built on the Enterprise Framework . Many of the features described here are fully documented by that plugin.

Stable API

Key services in SimpleMES are considered 'Stable APIs' . This means the SimpleMES developers will make every effort to retain backward compatibility with these services. This does not mean that there will be no changes to these APIs. It means that most of the changes will not affect older clients who use these APIs. Typically, later releases will add new, optional fields to the requests. The returned objects may have new fields added or some existing fields may become optional. There is always a chance that a breaking change will be needed, but this will rarely happen.

These Stable APIs are flagged in the Doc pages with the note: Stable API .

Your code should try to use these Stable APIs and the domain objects whenever possible. This will improve the life of your code.

Dependencies

This plugin/application requires a number of plugins to work. Most of these are required by the Enterprise Framework:

You do not have to include these in your build.gradle file. The Enterprise Framework depends on these modules and Gradle will include them in your application.

If you include these in your build.gradle file, then you must make sure the versions are consistent with the versions this framework requires. The specific versions needed are listed in the plugin’s build.gradle file.

Enterprise Framework

The Enterprise Framework plugin is a special dependency. This plugin was developed in conjunction with this MES application. The framework provides much of the 'enterprise' level functionality such as customization, standard GUIs and API support.

Programming Standards

This module conforms to the Enterprise Framework coding standards.

Security

Security is critical in enterprise applications. This MES Core module depends on the Security provided by the enterprise framework. In your application development, you will need to follow the Security Setup notes for the similar setup for the framework.

This MES Core module provides some Roles for application security levels. All controllers will enforce the appropriate security role.

Roles

The roles created automatically by the MES Core module provide the basic security roles for the entire suite of MES Modules . You can add additional roles, but the core controllers will only enforce security using the core roles. If these roles are deleted from the database, then they will be re-created on the next startup.

The roles provided by the core module are:

  • SUPERVISOR - The shop floor line supervisor tasks. Include releasing and managing work on the shop floor.

  • ENGINEER - Designs products and shop floor processes. Includes defining Work Centers and related objects.

  • OPERATOR - Performs most shop floor production, but can’t configure the shop floor or affect production outside of the local area.

  • LEAD - A 'super' operator that does setup or works as a lead over a group of operators.

The admin user will be given these roles on startup, but only if the record version is less than 5. This allows the default admin user to be given roles by modules, but lets you remove them later if needed.

Some of the pages available to each role is shown below (not an full list):

(No Role or Anonymous)

  • Login Pages

  • Overall System Status Pages.

ADMIN

  • Overall administrator over the entire system. This role does not automatically give permission over other roles below. You will need to given your admin-type users each role needed.

SUPERVISOR

Controls overall shop floor actions and manages demand flow on the floor.

  • Defines Orders.

ENGINEER

Designs products and shop floor processes.

  • Defines Work Centers.

  • Defines Products.

  • Defines Routings.

OPERATOR

Performs most shop floor production, but can’t configure the shop floor or affect production outside of the local area.

  • Operator Dashboard.

  • Process work (start/complete/etc).

LEAD

A 'super' operator that does setup or works as a lead over a group of operators.

  • Work Center Setup.

Controller Security

By default all controller methods must be secured. This means adding the @Secured annotation to your controllers:

import io.micronaut.security.annotation.Secured

@Secured('SUPERVISOR')
@Transactional
class OrderController {

  def release() {
    . . .
  }
}

The role chosen can be any of the defined roles. Individual methods can be secured too.

See Controller Testing for use of the ControllerTester to test security on your controllers (recommended for all controllers).

GUIs

Engineer Product

General Task Menu Reports

Dashboards

SimpleMES provides a number of user-level GUIs to help your users define, operate and monitor your shop floor. This includes setup GUIs, operator GUIs and reports.

Operator Dashboard

These dashboards are designed for operators to use on the shop floor. These provide the most common actions available to the operators. The dashboards are based on the framework Dashboards .

Most dashboards can be configured by the end user. The dashboards can use many different activities, but not all activities will work together cleanly. The activities are described in detail in the Dashboard Reference.

Scan Dashboard

This dashboard is different from most of the dashboards provided with SimpleMES. It is designed to work with a very specific flow that is streamlined for barcode scanner use. Many different Barcode Formats are supported.

See the ScanService for more overview on the scanning process and how modules work.

Scan Dashboard

This dashboard detects barcode scans and uses simple logic to process those scans. For example, if an Order is scanned that is in queue, then the Order is started. That order is then used for later actions.

This flow assumes the barcode scanner sends a TAB character after the scan and sends the scanned values through the browser as if typed from the keyboard.

The basic flow is as follows:

  1. The user scans an order.

  2. If the order is in queue, then the dashboard starts the order.

  3. The order is now the 'current' order.

  4. The user scans a component product (part number).

  5. The dashboard selects the component in the UI.

  6. The user scans the component lot.

  7. The dashboard uses that lot to assemble the component into the order.

  8. The user scans the barcode for the complete action.

  9. The dashboard completes the order and is ready to start again.

The component steps are supported with the Assembly module.

This is a very opinionated approach to shop floor operator GUIs. It may not work with all of your scenarios, but it will streamline your operations a lot. Some adjustments to the flow are supported, but you can create your own logic as needed in customizations.

Manual Actions - Scan Dashboard

Sometimes a barcode is missing or can’t be scanned. In this case, the operator can just type the value, followed by a TAB key. This value will be display on the screen as they type. Backspace is the only edit key supported.

Typing in the Scan Dashboard

Also, if the keyboard focus is in an input field, then the scanned value is entered into the field and processed for that field only. This allows for some scenarios that require minor user input in the GUI. For example, selecting the component when a component barcode is not available (Assembly module only).

Scan Dashboard - provideScanParameters

Most scan dashboard configurations will implement the concept of a current order or LSN. The user will scan the order/LSN and that will initiate some action (e.g. Start). This will also make it the current order/LSN.

Later scans will need this order/LSN for proper processing (e.g. for component assembly). To make this work, the scan dashboard Javascript library will call the provideScanParameters() method in all current activities. This lets the scan activity provide the current order/LSN for the scan request.

Operator Dashboard

Operator Dashboard

This dashboard provides easy access to the common tasks that a shop floor operator will need. It provide ways to work on orders/LSNs, setup resources and to view status of the operator’s area. This dashboard is configurable. You can decide which actions an operator can execute and how the page looks.

This section will describe the dashboard events and how multiple activities are designed to work together. We will also describe the activities (sub-pages) available to display when a user presses the button and the available default activities for the dashboard.

Most of the communication between activities is done via the provided parameters mechanism. Key values from the input fields are passed to all activities as they are triggered. For example, the Work Center Selection provides the current work center and the value from the order/LSN input field when an activity is triggered by a button.

Dashboard Events

A typical dashboard has a number of dashboard activities displayed at a given time. Your application may need to coordinate behavior between these activities. For example, a selection list may need to inform another activity that the user changed the selection. Dashboard Events are used to allow your activities to communicate these type of changes.

The important events are:

Complete Activity

uri: /work/completeActivity

This Complete activity is a Non-GUI Activity . This means it normally does not display a GUI and just performs the complete action. This activity works with the WorkController complete() method to perform the action.

The complete activity uses the Order/LSN parameter from the Work Center Selection activity and attempts to complete the work on it. Any errors are displayed in the dashboard’s message area.

Start Activity

uri: /work/startActivity

This Start activity is a Non-GUI Activity . This means it normally does not display a GUI and just performs the start action. This activity works with the WorkController start() method to perform the action.

The start activity uses the Order/LSN parameter from the Work Center Selection activity and attempts to start the work on it. Any errors are displayed in the dashboard’s message area.

Reverse Start Activity

uri: /work/reverseStartActivity

This Reverse Start activity is a Non-GUI Activity . This means it normally does not display a GUI and just performs the reverse start action. This activity works with the WorkController reverseStart() method to perform the action.

The reverse start activity uses the Order/LSN parameter from the Work Center Selection activity and attempts to reverse the start on it. Any errors are displayed in the dashboard’s message area.

Reverse Complete Activity

uri: /work/reverseCompleteActivity

This Reverse Complete activity is a Non-GUI Activity . This means it normally does not display a GUI and just performs the reverse complete action. This activity works with the WorkController reverseComplete() method to perform the action.

The reverse complete activity uses the Order/LSN parameter from the Work Center Selection activity and attempts to reverse the complete on it. Any errors are displayed in the dashboard’s message area.

This reverse action will mark the Order/LSN as not done and issue a negative ProductionLog record. This action also places the Qty back in queue. It does not perform a start on the qty.

Work Center Selection

uri: /selection/workCenterSelection

This Work Center Selection activity is designed to be used in the primary section (top) of the dashboard and will allow the operators to select the work center they are working in and enter an order or LSN to process. The buttons that can be added to this activity will let the operator perform common actions on the entered work center, order or LSN.

Dashboard - Work Center Selection

In this dashboard activity, the operator can change the work center by clicking on the work center. This will open a dialog that lets the operator select the work center they are working in. This work center is retained and used as the default the next time the user uses this dashboard.

Work List

uri: /workList/workListActivity

This Work List activity is used to display active or queued work for the operator. The current Work Center (Work Center Selection) is used to filter this work to manageable level, but it is not required.

Dashboard - Work List

As the operator selects entries, the current selection is coordinated with the selection activity to keep the actions in synch.

Task Menu

The task menu provided by this MES application uses the standard framework’s Task Menu logic. The activities provided by this application are assigned specific folders and display orders to organize all application activities in a consistent order across all Modules .

The basic ordering for all modules are:

  • Framework - 1 - 199

  • Dashboards - 200

  • Demand - 500

    • Orders - 510

  • Product - 600

    • Product - 610

    • Routing (Master) - 620

  • Shop Floor - 700

    • Work Center - 710

  • Assembly - 1000 - 1099

  • Defect Tracking - 1100 - 1199

  • Reports (Application) - 5000 - 5999

  • Support Functions (Search, Admin, etc) - 6000 - 9999

Reports

The third-party report engine is provided by the open-source Jasper Reports library. This report engine can generate reports from user-designed reports created in an interactive report designer. You can produce custom reports using this designer. See Report Engine for more details on add-on reports.

This MES core module uses the report engine to produce a number reports on the shop floor activity. These reports are hyper-linked with drill-downs and other links to related reports as shown below:

reportLinks

Controllers

The SimpleMES controllers are almost always thin wrappers around one or more Services. The argument(s) sent to the service are usually single POGO’s, sometimes with references to domain objects.

See the API Groovydoc for details on the methods. Most are not documented in detail in the User Guide or Reference Guide.

Arguments for GET Requests

Most HTTP GET requests use the arguments from the URL parameters. These allow the client to make simple request with 0 or more arguments.

Arguments for POST/PUT Requests

The body of the HTTP POST/PUT request are converted to these argument POGO’s and are passed to the service method. This means all body’s must conform to the normal JSON formatting rules for the framework.

Transactions

Most transactions are initiated by the controller layer. This is needed since most service methods work on domain objects. To properly populate the domain object references, the controller needs a transaction created for the request. It is also used to process the response into JSON in many cases.

Domains

Product Product Routing

Floor WorkCenter

The SimpleMESX data model contains many domain classes to support production operations. The object big picture looks like this:

bigPicture
Figure 1. MES Object Big Picture

Guidelines

The data model and documentation for SimpleMES follows some general guidelines. See also the guidelines from the Enterprise Framework.

Diagrams

There are a number of object diagrams to show you the relationships between various objects. These follow a general shape and color scheme as shown below:

packages
Figure 2. Color and Package Conventions

Name Fields (Primary Keys)

Most top-level objects have a primary key field that is generally referred to as the record’s 'name'. This is usually the primary key for the record. Most objects have just one primary key field. For example, Order has a primary key field 'order'. This field must be unique in most cases. No other Order can have the same order value.

SimpleMES uses the term 'name' as the record’s identifier, as the user sees it. SimpleMES uses this 'name' term to avoid confusion with the ID used in the database.

Some ERP systems use the term 'Internal Reference'. This is the same as the 'name' in SimpleMES.

Most search mechanisms allow you to search on the name and the title.

Title (Short Description)

Most top-level objects have a 'title'. This is normally treated as a one line short title/description for the user. This value does not have to be unique, but it is best if your records have unique titles. This title is frequently used in drop-down lists and other GUI elements.

Some objects have a longer description, but this is not as common. The 'description' field is used for multi-line descriptions that are used in only a few places such as Product.

Status

Status codes use the framework’s Encoded Types capability. These are normal POGO’s with a short string used for storage in a single column in the domain. This also allows modules to add additional status codes.

These statuses are stored as a single field in the domain object they 'control'. The base class defines the methods needed at run-time to operate. For example, the OrderStatus defines a isWorkable() method to determine if the order can be worked. Each status sub-class will will define whether it means the order is workable or not.

An example use of the OrderStatus is shown below:

Example - Order Status Use
class Order {
  String order
  OrderStatus status = OrderStatus.defaultStatus  (1)

  void start() {
    if (!status.isWorkable()) {  (2)
      thrown new BusinessException(. . .)
    }
    . . .
  }
}
1 The default status is provided by the base OrderStatus class.
2 The status is checked to make sure it means the order is workable.

Status Usage

Each domain object will decide which status(es) it will use. The most important objects and statuses used are:

Domain

Status

Default Status Codes

Order

OrderStatus

OrderCreatedStatus, OrderReadyStatus, OrderHoldStatus, OrderDoneStatus

LSN

LSNStatus

LSNReadyStatus, LSNHoldStatus, LSNDoneStatus, LSNScrappedStatus

WorkCenter

Framework BasicStatus

EnabledStatus, DisabledStatus

Custom Field Extensions

Most domain classes in SimpleMES can be extended with a limited number of custom fields. These are marked with the @ExtensibleFieldHolder annotation in the Groovy API documents. See the Field Extension documentation in the Enterprise Framework allows you to add new fields. Most SimpleMES definition GUIs allow you to edit these custom fields:

Demand

The demand package defines the demand for production within the shop floor. This includes key elements such as Orders and Lot/Serial Numbers (LSN).

Order

An Order is a manufacturing order used to produce an (optional) Product. These orders specify the quantity needed and optionally a due date, start date and other information. Orders may use the standard Routing or may have an order-specific Routing.

OrderList

Orders can be created in SimpleMES or they may be imported from an ERP system.

Orders have several statuses that indicate the state of many aspects of the order. The overall status controls the overall availability of the order. It indicates if the order has been released for production, is on hold for some reason or if the order is done.

Orders must be released in order to work them on the shop floor. This done through the GUI or by using the OrderService. The release process moves the quantity to in queue at the appropriate place. If there is a routing, then this quantity is queued at the first operation. If there are LSNs defined, then the quantity is released to an LSN as needed. This depends on the product’s lot size and LSN tracking option.

Orders are considered to be 'Lots' in many cases. For serialized tracking or small lot tracking, LSNs can be used as optional elements of an order.

Processing of the orders (or LSNs) for actual production is done using the WorkService. This allows you to perform work at specific operations on the routing and track what happened to the order/LSN on the shop floor.

Order Object Model

The Order object model is somewhat complex. It supports several optional elements (LSNs, routings, etc) at several levels.

The key objects are:

orderModel
Figure 3. MES Order Object Model

The Order can have zero or more LSNs.

The Order will also have a copy of the Product’s effective routing. Upon release, these operations are copied to the order to avoid restrictions on the product definitions once an order is released.

The RouterTrait and OperationTrait classes provide common logic for processing on the shop floor. The OperationTrait is implemented by the ProductOperation,MasterOperation, and OrderOperation.

The current state of the order (or LSN) is stored in the OrderOperState (and LSNOperState).

LSN

An LSN is a portion of an Order. This is the finest level of tracking possible in SimpleMES. An LSN has a quantity that is based on the lot size for the product. If the LSN represents a serial number then the lot size and quantity are usually 1.0.

Orders and LSNs

The relationship between Orders and LSNs is shown below.

orderLSNRelationship
Figure 4. Order/LSN Relationship

LSNs are children of Orders. They are optional and do not need to be created in all cases. See LSN Tracking Option and LSN Creation Options for details.

Non-Unique LSNs

Because this LSN has a combination primary key of order + lsn, the API calls using JSON need to be a little more complex. For example:

Example - Request POGO with Order and LSN
class CompleteRequest {
  @JSONByKey
  Order order

  @JSONByKey
  LSN lsn
}

Then you can reference an LSN in a JSON request as:

Example - LSN JSON Request
{
  "order": "M1001",
  "lsn": "SN2001"
}

If the lsn (SN2001 above) is unique, then you can leave off the order element. If the LSN is not unique, then you may receive an error if you attempt to process the LSN (e.g. Start).

This is a little awkward, but it gives you the ability to re-use the LSN in other orders. This might be useful for RMA processing or returned products. It might also be useful when you have no control over the serial numbers you need to use (e.g. your custom provides the serial numbers).

LSNs may be globally unique or can be unique within a given product or order. SimpleMES will attempt to find the appropriate LSN. This done by the fixLSN() method.

Find any POGO’s that use @JSONByKey on LSN and make sure that all the consumers of those POGO’s use the fixLSN() method.

LSN Tracking Option

Tracking within SimpleMES is performed at the order level or at the LSN level. You must decide how LSNs will be used in producing the orders in SimpleMES. For a given Product, you have these options:

LSN Tracking Option Description

Order Only

No LSN tracking is permitted. The order is processed as one large lot. No LSNs are used.

LSN Allowed

Orders or individual LSNs may be processed. If LSNs exist, SimpleMES can pick LSNs to process if not specified in the request.

LSN Only

Only individual LSNs may be processed. If just and order is specified, then an error will occur in production actions.

The options for tracking these LSNs are defined at the product level, but are copied to the order upon creation. This prevents problems when the tracking option changes later. The tracking option at the order level is the one used during production.

Some production actions can prevent processing by the entire order. This can be used to force use of LSNs in many scenarios.

LSN Creation Options

LSNs may be assigned at order creation time or later as needed. This is configured by assigning an LSN Sequence to the product. See Product for details on how this is configured at the product level. LSNs are only automatically assigned on release when the product’s LSN Tracking Option is set to LSN Only. You can create the LSN yourself using the GUI or API for the other scenarios.

The automatic creation of LSNs is done by SimpleMES during the order release process. See OrderService for details. This only happens when the Order’s effective LSN Tracking Option is set to LSN_ONLY.

LSNs Routings and Quantity Tracking

Depending on the Product’s LSN Tracking Option, individual pieces can be tracked by a unique LSN or as part of a larger lot. These flexible options mean that the quantity to be worked can be tracked at the order level or at the LSN level. This means the quantity is stored in multiple places in SimpleMES. The possible quantity tracking options are shown below:

orderLSNRoutingRelationship
Figure 5. Order/LSN and Routing Relationship

If the routing exists for the product/order, then the quantities are tracked at a routing operation level. Each operation has the qtyInQueue, qtyInWork, etc. The basic relationship of the objects when routings are used are shown below:

orderLSNOperation
Figure 6. Order/LSN and Operation Relationship

If LSN Tracking Option is LSN Allowed or LSN Only, then LSN records will exist for the order. The quantity is then tracked at the LSN level. If LSN Tracking Option is Order Only, then the quantities are tracked at the Order level.

The quantities are always tracked at one level for a given order. The locations are shown in the table below.
LSNMatrix
Figure 7. LSN/Order Quantity Tracking Scenarios

Upon order release, the Order copy of the operations are created. These are copied from the effective routing from the Product or MasterRouting. It is also possible to import an order with its own operations if needed.

The detailed operation states are stored in various places, depending on how work is tracked. All of these places implement the WorkStateTrait . This Trait provides most of the logic and persistent fields needed to track the state. It provides common methods such as queueQty() or startQty().

The various places this state is stored are:

Scenario

Work State Object

No LSN, No Routing

Order

No LSN, Routing

OrderOperState

LSN, No Routing

LSN

LSN, Routing

LSNOperState

CodeSequences

Code Sequences are used to control the creating of unique codes (primary keys) within the MES. This is typically used for Orders and LSNs.

For example, a bicycle serial number based on the date can be generated using the formatString:

${date.format('yyMMdd')}-$currentSequence

This will generate the serial numbers for March 14, 2016:

LSN

160314-001

160314-002

160314-003

Sequences are stored in the Database and have a specific set of objects they are used with. User-defined sequences are possible, but new functional behavior requires custom logic. The general features of the code sequences are covered in CodeSequence.

The sequences used by the MES core module include:

Product Definition

The product package defines the products (materials or part numbers) to be be produced. This also includes details on how to build the products.

Product

A Product is a part or object that is produced on your shop floor or purchased from external sources. This is sometimes known as a part number or model number. This product defines the optional Routing needed to produce the product.

An Order is used to manufacture the product as needed.

For detailed field information, see the API Documentation at: Product .

If assembly is required for the product, then refer to the Assembly module.

Routing

A Routing is a sequence of operations needed to manufacture a Product. These operations can be simple actions such as ASSEMBLE or TEST. They may also be a composite operation that is made up of several actions that are not tracked within SimpleMES.

Some examples are:

  • 10 - ASSEMBLE

  • 20 - PAINT

  • 30 - PACK

  • 40 - TEST

The routing may be a master routing that can be used on multiple products or it may be specific to a single product. This decision is made when defining the product.

Operations can be optionally defined to execute within a WorkCenter. This is useful to limit where specific operations can be performed.

For detailed field information, see the API Documentation at: Routing .

Routing Object Model

The routing-related object model is somewhat complex. It supports routings at two levels: MasterRouting and Product. There is also a copy of the routing at the order level.

The key objects are:

routingModel
Figure 8. MES Routing Object Model

A product can refer to a MasterRouting or have its own routing. When released, the Order will have a copy of the routing operations from the product/master routings.

Each routing has a list of operations. These operations all implement the OperationTrait. When released, the Order or LSN will have an operation state record created for each operation on the routing. See Order Object Model for details.

Floor

The floor package defines elements on the shop floor, such as Work Centers.

WorkCenter

A WorkCenter is a machine or location where a manufacturing operation is performed. It can also refer to the people at a location where the operation is performed.

The core work center domain class is fairly simple with just the normal fields (e.g. title) and a basic overall status.

Some examples include:

  • CELL27

  • BENCH43

  • TESTER

  • ASSEMBLY CELL 12

  • FINAL PACKAGING AREA

For detailed field information, see the API Documentation at: WorkCenter

Additional functionality for the work center to perform assembly is covered in the module Assembly .

Tracking

The tracking package defines domains that track activity on the shop floor.

ActionLog

The ActionLog class represents a single action by a user on the shop floor. Typically, this is written when an order/LSN acted on in any way.

These records are designed to exist as long as the owning objects (e.g. Order) are in the database. The records are archived when the owning objects are archived. This is something the Order object handles with its findRelatedRecords() method to find the ActionLog records.

For detailed field information, see the API Documentation at: ActionLog .

ProductionLog

The ProductionLog class represents the result of a production action on the shop floor. Typically, this is written when the order/LSN is taken out of work so that the elapsed time can be calculated. This includes actions like complete and reverse start.

These records are designed to exist without direct references to other domain objects. This means the references use the primary key field for the object (e.g. Order, LSN, etc). Those referenced objects can be archived and these production log records can be kept in the database longer than the other domain objects if needed.

For detailed field information, see the API Documentation at: ProductionLog .

Production Log Archiving

By default, these records are automatically archived after 6 months. You can alter these settings by changing the Background Task for the production log archiver. This task has these options:

Field Description

ageDays

The age to archive old records from the production log (Default: 180 days).

batchSize

Number of records to archive in one batch. This sets the database transaction size and the size of the archive JSON file created (Default: 500).

delete

If checked, then the production log records will be delete instead of writing to an archive JSON file (Default: unchecked).

When checked, the Delete option means the old records are deleted with no copy of the records kept by the system.
When archiving these records, there is no ArchiveLog record created and the JSON is not verified. These features are disabled automatically, no matter how the application.yml configuration is set. This improves the performance.

The archive JSON files are created using the ProductionLog.toShortString() method to form the file name. This contains the date/time of the first production log record in the archive. For example:

ProductionLog-2018-04-18-15-42-35.arc

There is no ordering within the archive files, so it is possible for records from other date/times to be stored in the file.

System

The system package defines common domains used by other packages or that support the general setup of the application.

Services

System Services ScanService

Tracking Services ProductionLogService

Introduction

SimpleMES provides much of the business logic using services. These services use the domain objects to affect the persistent state of objects. Most of the complex MES business logic is handled in the services.

Domain Objects and Services

Domain objects are used to store/retrieve properties of the SimpleMES objects. The domain objects are responsible for persistence and ensuring data integrity. This includes basic validations, but does not include cross-object validation except in the cases of child objects.

Services orchestrate various domain objects and other services to provide higher level services. In general, you should not directly use the domain objects in place of the appropriate service. For example, if you wish to start a quantity on an order, you should not use the Order object to adjust the quantity directly. You should use the WorkService to perform the start work action. This ensures proper logging, security and validation with all of the appropriate objects.

You can use domain objects directly in a few cases. In most cases, reading values is acceptable. Some direct updates make sense, but do not use direct updates to avoid the business logic in the services. Some domain methods are exposed in the service layer. We recommend that you use the service layer method when possible.

Service Input Arguments

Most services take one or more POGOs (Plain of Groovy Objects) as input arguments. These POGOs are simple containers that hold values used by the service. A good example is the start() method:

Example Service Argument
  class StartRequest {
    Order order
    WorkCenter workCenter
    BigDecimal qty
    . . .
  }

This StartRequest POGO provides the fields needed to perform the start. Some fields are simple values (e.g. qty) and others are domain objects themselves. You will use Groovy/GORM features to populate these values.

If the POGO contains domain objects, then you will need to make sure you pass them from inside of a transaction. Even if the service method is marked as @Transactional, you need to make sure the transaction/session is the same for the service method as the code that read the domain object.

Example

A short example to start work on an order is shown below:

Example Service Use
@Singleton
@Transactional
class AnotherService {

  @Inject
  def workService      (1)

  StartRequest startRequest = new StartRequest()
  startRequest.order = Order.findByOrder('M0001')
  startRequest.qty = 1.0
  workService.start(startRequest)

  . . .

}
1 Injected automatically by @javax.inject.Inject at run time.

This example uses the WorkService, which is injected by Micronaut with the annotation. This code then finds the order using its key value ('M0001') and sets the quantity to start to 1.0. It then calls the service. The WorkService in this case moves the quantity to in work and logs a record to the ActionLog.

If the service fails, then it will throw an exception and the transaction will be rolled back.

Transactions

Services follow the normal framework transaction logic. See Enterprise Framework for details.

Service Extension Points

Many other modules may need to extend core methods with module-specific logic. We allow this using the framework’s Extension Points feature. The extension points this module supports include:

Unresolved directive in guide/services/introToServices.adoc - include::../../../../../../build/generated/extensions.adoc[]

Demand Services

This demand package provides objects to handle demand for production within the shop floor. This includes handle work on the shop floor and dealing with orders from customers.

OrderService

The OrderService is used to perform key actions on the entire Order. This includes releasing the order and other global tasks. Additional information can be found in the Groovydoc OrderService .

This service’s methods are exposed by the OrderController . This controller supports the request/response POGOs in JSON format.

release()

The release() method is used to release an order to the shop floor for processing. The entire order or a portion of the order can be released. Automatic LSN generation, if needed, occurs at release time. See LSN (Lot/Serial Number) for details on when LSNs are automatically generated.

This method is part of the Stable API .

This method is exposed via HTTP in the /order/release URI. See OrderController .

Request and Response

This method takes a request object OrderReleaseRequest and returns the response OrderReleaseResponse .

archiveOld()

Archiving is used to move an order to an JSON file to reduce the amount of data in the database. This will archive a single order and all of its children and history records at a time.

The archiveOld() method is used to archive old, done orders based on the date that they were completed. There are options for the age (days) and the max number of orders to archive in one batch (transaction). There is also an option to limit the number batches archived at a time. This last option is used to limit the slowdown from archiving during 'catch-up' scenarios when archiving has not been run recently.

The archive feature is described in more details at Archiving(framework) .

ResolveService

The ResolveService is used to find the right objects/records to process on the shop floor. This service allows you to find the right order/LSN when given limited information. This means you can try to start work on an order without knowing the specific operation to start.

Most SimpleMES production service methods will call the ResolveService.resolveProductionRequest() method at the start of the action. This will fill in the missing fields in the request. You normally won’t need to call this method yourself.

Basic Scenarios

Many common scenarios involve trying to start work on orders with limited information. This happens frequently with automated machines on the shop floor. The machines can read a barcode as the product enters the machine, but the machine has no real knowledge of SimpleMES data or what the barcode really means. It could be an order or an LSN.

To help with these cases, the Resolve service gives you methods to find the right records in SimpleMES to process. In most cases, the caller uses the Resolve service to determine the records for you. There may be times when you need to use this resolving logic yourself. The Resolve service can be used to 'fill in' the missing data in many of the services requests.

For example, the WorkService.start() method uses a StartRequest . The resolveProductionRequest() method will automatically fill in any missing information. You do not need to call the resolveProductionRequest() yourself in most cases.

The supported scenarios are:

Table 1. Supported Resolve Scenarios
Scenario Description

Barcode Only

Only a generic barcode or user input string is provided. The resolveProductionRequest() method will try to interpret this as an LSN first, then as an Order.

Order Only

Only an Order is provided. The resolveProductionRequest() method will attempt to find the appropriate LSN and operation to process.

LSN Only

Only an LSN is provided. The resolveProductionRequest() method will attempt to find the appropriate Order and operation to process.

LSN+Order

Both an Order and LSN are provided. The resolveProductionRequest() method will attempt to find the appropriate operation to process.

In all of these scenarios, the operation sequence and work center can be provided too. If not provided, the service will attempt to find the right operation to process (if any). In some cases, the work center may also help narrow down the list of possible choices.

Not Enough Information

*TBD: Add notes on missing data exceptions *

See the MissingDataException in the Enterprise Framework documentation.

resolveProductionRequest()

The resolveProductionRequest() method is used to fill in any missing information in most production requests. It will use the information already in the request and narrow down to a specific object to process.

For example, order M001 has a routing with 3 operations: 1,2,3. A start() request with only the barcode='M001' can be used to start the order at the current operation. This means the resolveProductionRequest) will find the proper order and the operation with a quantity in queue.

This method operates on production request POGOs that have the following fields:

Table 2. Important Fields - resolveProductionRequest
Field Description

barcode

A generic barcode or user input that can be an order or LSN.

order

The Order to be processed.

lsn

The LSN (Lot/Serial Number) to be processed.

qty

The number of pieces to be processed.

operationSequence

The sequence of the operation (step) the order/LSN is to be processed at.

workCenter

The WorkCenter this work is being performed at.

All of these fields are individually optional, but you must provide enough information for the action to be performed. In some cases, a barcode alone will be enough to handle the action. There is also an option on this resolveProductionRequest) method to indicate if preference should be given to entities with a quantity in queue or quantity in work. For example, the start() method prefers to operate on quantities in queue.

The service will attempt to fill in the missing information using the following rules to fill in the missing information:

Table 3. Precedence for resolveProductionRequest()
Field Precedence

Order

  1. If an LSN is given, then use the LSN’s order.

  2. If barcode is given, then use that if there is only one order with the same barcode.

LSN

  1. If barcode is given, then use that if there is only one LSN with the same barcode.

  2. If Order is given, then use first LSN with the quantity in queue (or work).

Qty

  1. Use the current quantity in queue or in work, based on the preference parameter.

Operation Sequence

  1. Use the first operation with a quantity in queue or in work, based on the preference parameter.

Work Center

  1. If an operation is known, then use the work center from the routing operation.

resolveWorkable()

The resolveWorkable() to find the right level to process a given order and/or LSN. This is based on the Product settings and the current state of this order. This finds where the in work, in queue and other quantities are handled for these cases.

This method operates on a ResolveWorkableRequest POGO that have the following fields:

Table 4. Important Fields - resolveWorkable
Field Description

order

The Order to be processed.

lsn

The LSN (Lot/Serial Number) to be processed.

qty

The number of pieces to be processed.

operationSequence

The sequence of the operation (step) the order/LSN is to be processed at.

All of these fields are individually optional, but you must provide enough information to find the workable unit (LSN or order).

fixLSN()

This fixLSN() method is used to make sure the given object’s order and LSN are consistent. A common use is when receiving a request POGO with the LSN and optional order. This looks something like this:

Example - Request POGO with Order and LSN
class CompleteRequest {
  @JSONByKey
  Order order

  @JSONByKey
  LSN lsn
}

You will then de-serialize the given JSON:

Example - LSN JSON Request
{
  "order": "M1001",
  "lsn": "SN2001"
}

The normal JSON de-serialization (using the framework @JSONByKey) will find the first LSN that matches 'SN2001'. This works great until you have duplicate serial number for another order. The de-serialization might find the wrong LSN.

To handle this, we have the fixLSN() method:

Example - fixLSN()
def completeRequest = new CompleteRequest(...)
resolveService.fixLSN(completeRequest)  (1)
1 Verifies that LSN/Order are consistent. Will also populate Order if null.

This method takes anu object with order and lsn fields that are domain object references. This method will throw an exception if the order/lsn combination is nor correct and the right LSN can’t be found.

WorkListService

The WorkListService is used to find work that is available (in queue) or in work. This list can be restricted to work in a work center or global. This can show Orders and/or LSNs.

This service’s methods are exposed by the WorkListController . This controller supports the request/response POGOs in JSON format.

findWork()

This is the primary method in this services. It finds work that is in queue or in work with various filter criteria. This method returns a list of Orders/LSNs that match the criteria. The list is row-limited with the normal offset and max settings. This response also includes the total number of rows available, for support of paging.

This method performs 4 queries to find all types of work needed:

  • Orders with no routing.

  • Orders with a routing.

  • LSNs with no routing.

  • LSNs with a routing.

Most customers will use one of these combinations, but the MES will not limit you to just one. This means all four queries will be executed and combined.

This method is part of the Stable API .
Request and Response

This method takes a request object FindWorkRequest and returns the response FindWorkResponse .

WorkService

The WorkService is used to start and complete work on some portion of a product on the shop floor. This contains most of the business logic that controls and tracks these production operator actions.

Common Work Service Features

Most of the production work service methods use a similar format for the request POGOs:

Table 5. Important Fields - Common WorkService Fields
Field Description

barcode

A generic barcode or user input that can be an order or LSN.

order

The Order to be processed.

lsn

The LSN (Lot/Serial Number) to be processed.

qty

The number of pieces to be processed.

operationSequence

The sequence of the operation (step) the order/LSN is to be processed at.

workCenter

The WorkCenter this work is being performed at.

All of these fields are individually optional, but you must provided enough information for the action to be performed. In some cases, a barcode alone will be enough to handle the action. The Work service will attempt to fill in the missing information using the ResolveService. You normally don’t need to use the Resolve Service directly, but it is available for your use. The guide will give you some idea of the logic used to resolve to specific values in most requests.

The actual data required to perform the action depends on the configuration of your data. If you have no routings, then an operationSequence is not needed. If you do not use LSNs, then no LSN is needed. In many cases, SimpleMES can guess what you wish operate on, even if you do not provide all of the information.

A typical scenario is that you have a semi-unique barcode string to start work on, but you do not have the specific LSN, order or operation sequence to process. SimpleMES uses the ResolveService to narrow this down to a specific Workable object to process. In the case of multiple operations on a routing, SimpleMES will try to use the operation where the quantity is in queue for a start() action.

Most Work Service methods will automatically call the ResolveService.resolveProductionRequest() method at the start of the action. This will fill in the missing fields in the request.

Some of the key business logic for these Work Service methods is implemented in the WorkStateTrait . This includes the manipulation of the qty’s and dates in the workable object.

start()

The Start method is used to begin work on an order or LSN. This can be the entire order, one LSN or just a portion. The work is performed at an optional work center and is logged to the action log.

The StartRequest object is the main argument for the start(). This is a simple POGO that you must populate before you perform the start. This method returns the order/LSN that was started.

The start() finds the appropriate Workable that matches the start request’s inputs (e.g. an Order or sub-element that can be started). The Work service then calls the startQty() on that Workable. This then validates that the Qty can be started.

If everything passes the validation, then the WorkService will log the start via the ActionLog. There is a corresponding reverseStart() method to "un-start" the work.

This method is part of the Stable API .

complete()

The complete() method is used to finish work on an order or LSN. This can be the entire order, one LSN or just a portion. The work is performed at an optional work center and is logged to the action log and ProductionLog.

This method returns the order/LSN that was completed.

This method is part of the Stable API .

The complete() finds the appropriate Workable that matches the request’s inputs (e.g. an Order or sub-element that can be completed). The Work service then calls the completeQty() on that Workable. This then validates that the Qty can be completed.

If everything passes the validation, then the WorkService will log the start via the ActionLog.

System Services

This system package provides objects to handle generic actions within the MES.

ScanService

The ScanService is used resolve a barcode input to a Scan Dashboard and perform an action on that input. This action can be to start an Order/LSN or to press a button on the dashboard.

This service’s methods are exposed by the ScanController . This controller supports the request/response POGOs in JSON format.

The scan service resolves a barcode input using a basic simple search routine. The optional Modules can add additional types of objects support by the scan service using method extensions. The core search routine follows this search order:

  1. Internal Barcode Format (delimited with ^).

  2. Configured Barcode Format (TBD).

  3. Intelligent search routine:

    1. LSN

    2. Order

    3. (Module-specific objects such as Component, Location)

Once the barcode content is determined, then the scan service will optionally perform an action on the scanned object.

Once any action is completed, the result is returned to the dashboard for display and possible additional GUI actions such as:

  • Dashboard Button Press

  • GUI Refresh

  • Module-Specific actions (e.g. start assembly process by selecting a component).

Scan - Order/LSN Processing

The MES core logic will start the Order/LSN if it is in queue. This start can be reversed with the normal dashboard Undo feature.

Scan - Architecture and Modules

The Scan Dashboard is designed to work with optional modules. These optional modules can change the default flow and add more options to the dashboard behavior. To make this work, the scan dashboard and related objects work together to handle scans and update the dashboard as needed. The basic flow of a scan (Order scan) is shown below:

scanDashboardFlow

The scan request is sent to the server, which determines what the scan is and what to do with it. In this case, it is an order that is in queue and the server starts the order. After the start, a response is returned to the client that tells the dashboard to update the UI for the started order.

Handling Other Objects

The default core logic attempts to resolve inputs using the following precedence:

  1. LSN

  2. Order

The optional Modules can add objects to this list before or after the core objects.

To handle additional objects, the module should define a post method extension on the ScanService.scan() method as shown above. The Assembly module adds components to the search list (after the core objects). The extension looks for components to be assembled. It can then open an activity to collect other barcode inputs for the assembly data needed for that component.

The core dashboard logic will handle LSN and order scanning. Once resolved, the scanned order/LSN will become the 'current' order/LSN. This will be passed with the scan request so that the module can use this to help narrow down the choices for the scanned item. This helps find components required for a given order.

Barcode Formats

Barcode formats come in many shapes and sizes. SimpleMES does not require any specific format or scanner. The main requirements are:

  • The scanner sends the data to the browser as keyboard input.

  • The scanner sends a TAB character as the suffix after the data is sent.

Additional barcode format details are supported including:

  • Data only (e.g. The order ID is the only value encoded in the barcode: 'M1001').

  • Internal Structure (Delimited data using ^ as a delimiter: '^PRD^BIKE-27A').

  • Configurable formats (TBD)

The scan service will use any formatted barcode values to determine the type of object scanned. If no formatting is used, then the intelligent search logic will find the right object that matches the scanned value. The precedence in the core MES module is:

  1. LSN

  2. Order

The optional Modules can add objects to this list before or after the core objects. For example, the Assembly module adds component to the search list (after the core objects).

Scan Actions

For every scan, there is a ScanResponseInterfaces returned. This response contains a list of ScanActions that indicate what should be performed on the client.

These actions are POGOs that must contain a type, which indicates what the event is or action is. It is up to the client to determine how to process them. Each scan action will be sent to all dashboard activities as Dashboard Events.

See Scan Actions for specific details on the actions.

Tracking Services

This tracking package provides services/domains to track shop floor activity.

ProductionLogService

The ProductionLogService is a simple service that provides a way to log production actions on the shop floor for use in reporting. This typically helps provide the production rates and yield data for common reports.

The key methods for this service are:


Table 6. ASCIIDOCTOR Attributes

asciidoctor-version

2.0.10

safe-mode-name

unsafe

docdir

/home/runner/work/simplemes-core/simplemes-core/mes-core/src/main/docs/asciidoc

docfile

/home/runner/work/simplemes-core/simplemes-core/mes-core/src/main/docs/asciidoc/guide.adoc

doctype

book

imagesdir-build

images

imagesdir-src

images

imagesdir

images