Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Sample Plugin License

Copyright 2021 Agilent Technologies Inc.

Redistribution and use of Sample Plugins in source, executable and binary forms,
with or without modification, are permitted provided that the following
conditions are met:

1. Redistribution of Sample Plugins in source code, executable or binary form
must retain the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided with
the distribution.

2. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products associated with Sample Plugins
without specific prior written permission from Agilent Technologies Inc.

SAMPLE-PLUGINS ARE PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/*
* Copyright 2021 Agilent Technologies Inc.
*/

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
plugin-name: "create-order-and-schedule"
---

# General Introduction
This plugin creates a new order (using the order type from the plugin configuration), links the selected content to the
order, applies a request to each of the selected content (using the requestable type in the plugin configuration), then
schedules the new order.

## Usage: _Content Management_
## Type: *slimsgate*

# Step 1:
## User inputs:
none
## Process
An order is created, the content is linked to the order (by creating OrderContent), requestables are added to each
content record, and then order is scheduled. A feedback map outlining the content and the order is output to the next
step.


# Step 2:
## User inputs:
none
## Process
This step is just for displaying the feedback map.

# Required Configuration
- A valid requestable
- A valid order type

# Parameters description
* (String) **requestableUid**: The UID for the requestable that will be used to create requests for the selected content.
* (String) **orderTypeUid**: The UID for the desired order type for the new order.

# Troubleshooting
The only expected errors include being unable to find the requestable or order type.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2021 Agilent Technologies Inc.
*/

package com.genohm.slims.custom;

public class CreateOrderCustomConfiguration {

private String requestableUid;
private String orderTypeUid;

public CreateOrderCustomConfiguration() {

}

public String getRequestableUid() {
return requestableUid;
}
public String getOrderTypeUid() {
return orderTypeUid;
}

public static CreateOrderCustomConfiguration getDefault() {
CreateOrderCustomConfiguration createOrderCustomConfiguration = new CreateOrderCustomConfiguration();

// used to query for the desired requestable to add to content in the new order
createOrderCustomConfiguration.requestableUid = "rqbl_wf_simplified_workflow_simplified_1";

// used to look up the desired order type for the new order
createOrderCustomConfiguration.orderTypeUid = "rdtp_default_workflow_order";
return createOrderCustomConfiguration;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2021 Agilent Technologies Inc.
*/

package com.genohm.slims.custom;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

/**
* There are cases where you might need to modify this file, but 99% of the time you can just copy it as-is
*/
@Configuration
@ComponentScan("com.genohm.slims.custom")
@ImportResource("classpath:spring/camel-context.xml")
public class SpringConfig {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright 2021 Agilent Technologies Inc.
*/

package com.genohm.slims.custom.beans;

import com.genohm.slims.api.AddRequestService;
import com.genohm.slims.common.model.Content;
import com.genohm.slims.common.model.Order;
import com.genohm.slims.common.model.OrderContent;
import com.genohm.slims.common.model.OrderContentMeta;
import com.genohm.slims.common.model.OrderMeta;
import com.genohm.slims.common.model.OrderType;
import com.genohm.slims.common.model.Requestable;
import com.genohm.slims.common.model.User;
import com.genohm.slims.common.slimsgate.SlimsgateParameter;
import com.genohm.slims.common.util.StringUtil;
import com.genohm.slims.custom.CreateOrderCustomConfiguration;
import com.genohm.slims.server.dao.common.ActiveUser;
import com.genohm.slims.server.dao.common.Dao;
import com.genohm.slims.server.repository.queriers.ContentQueries;
import com.genohm.slims.server.repository.queriers.OrderTypeQueries;
import com.genohm.slims.server.repository.queriers.RequestableQueries;
import com.genohm.slims.server.service.order.ScheduleOrderService;
import com.genohm.slims.server.util.EntityFactoryUtil;
import com.genohm.slimsgate.camel.gatekeeper.SlimsGateErrorException;
import com.genohm.slimsgate.camel.gatekeeper.SlimsGateKeeperConstants;
import com.genohm.slimsgate.camel.gatekeeper.SlimsProxy;
import com.genohm.slimsgateclient.workflow.SlimsFlowInitParam;
import org.apache.camel.Handler;
import org.apache.camel.Header;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class CreateOrderAndSchedule {

@Autowired private CreateOrderCustomConfiguration createOrderCustomConfiguration;

@Autowired private OrderTypeQueries orderTypeQueries;
@Autowired private ContentQueries contentQueries;
@Autowired private RequestableQueries requestableQueries;

@Autowired private Dao<Order> orderDao;
@Autowired private Dao<OrderContent> orderContentDao;
@Autowired private ScheduleOrderService scheduleOrderService;
@Autowired private AddRequestService addRequestService;

@Transactional
@Handler
public Map<String, Object> execute(
@Header(SlimsGateKeeperConstants.SLIMS_PROXY) SlimsProxy slimsProxy,
@Header(SlimsGateKeeperConstants.SLIMS_WORKFLOW_INIT_PARAMETER)
SlimsFlowInitParam initParam) {
// get logger from slimsProxy to allow logging to the UI (vs just to the server log file)
Logger logger = slimsProxy.getLogger(getClass());

// get the user running the plugin so the audit trail shows their user instead of the "Slimsgate" user
User user = ActiveUser.get();

// get content primary keys from the input parameters
Map<String, Object> initParamValues = initParam.getInputParameterValues();
List<Long> samplePks =
Arrays.asList(
StringUtil.getAsLongArray(
initParamValues.get(SlimsgateParameter.SLIMS_SELECT_SAMPLES)));

// query for Content records using the PKs of the selected content
List<Content> sampleContentList = contentQueries.findByPks(samplePks);

// get order type record using the unique identifier in the plugin configuration
OrderType workflowOrderType =
orderTypeQueries
.findByUniqueIdentifier(createOrderCustomConfiguration.getOrderTypeUid())
.toJavaUtil()
.orElseThrow(
() ->
new SlimsGateErrorException(
String.format(
"Could not find the order type with UID %s.",
createOrderCustomConfiguration.getOrderTypeUid())));

// create an order by first making a map and then adding it to the database
Map<String, Object> order = new HashMap<>();
order.put(OrderMeta.FK_ORDER_TYPE, workflowOrderType.getRdtp_pk()); // add the order type PK to the map
Map<String, Object> newOrderMap = orderDao.add(order, user); // commit the order to the database

// convert the order to a SLIMS entity in preparation for adding requests and scheduling
Order newOrder = EntityFactoryUtil.createInstance(Order.class, newOrderMap);

for (Content content : sampleContentList) {
// create a new order content record and add it to the database. This is how the content is linked to the order
Map<String, Object> newOrderContent = new HashMap<>();
newOrderContent.put(OrderContentMeta.FK_CONTENT, content.getCntn_pk());
newOrderContent.put(OrderContentMeta.FK_ORDER, newOrderMap.get(OrderMeta.PK));
orderContentDao.add(newOrderContent, user);

// query for the requestable defined in the configuration
Requestable requestable =
requestableQueries
.findByUniqueIdentifier(createOrderCustomConfiguration.getRequestableUid())
.toJavaUtil()
.orElseThrow(
() ->
new SlimsGateErrorException(
String.format(
"Could not find requestable with UID %s.",
createOrderCustomConfiguration.getRequestableUid())));

// add the request to the content/order
addRequestService.createWorkflowRequest(content, requestable, newOrder, new HashMap<>());
}

// schedule the order
scheduleOrderService.scheduleWorkflowOrder(newOrder, user);

// return the feedback map for display in the last step of the plugin
return createFeedback(newOrder, sampleContentList);
}

private Map<String, Object> createFeedback(Order order, List<Content> samples) {
Map<String, Object> feedback = new HashMap<>();
StringBuilder feedbackSb = new StringBuilder();

feedbackSb.append("<p>Created content barcodes</p>");
feedbackSb.append("<ul>");
samples.forEach(sample -> feedbackSb.append(String.format("<li>%s</li>", sample.getCntn_barCode())));
feedbackSb.append("</ul>");

feedbackSb.append("<br>");

feedbackSb.append("<p>Order barcode</p>");
feedbackSb.append(order.getOrdr_barCode());

feedback.put("results", feedbackSb.toString());
return feedback;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2021 Agilent Technologies Inc.
*/

package com.genohm.slims.custom.beans;

import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CreateOrderAndScheduleBuilder extends RouteBuilder {

@Autowired CreateOrderAndSchedule createOrderAndSchedule;

@Override
public void configure() throws Exception {
from("direct:create-order-and-schedule")
.bean(createOrderAndSchedule)
.routeId("create-order-and-schedule");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#
# Copyright 2021 Agilent Technologies Inc.
#

# This is the classpath of the Configuration class of your plugin, starting from this plugin's src/main/java/ path
config-class=com.genohm.slims.custom.CreateOrderCustomConfiguration
# This is the "type" of plugin it is. Use SLIMSGATE unless you are just creating a library to use as a dependency for other plugins (see library-template)
type=SLIMSGATE
# This is the minimum "minor" version of your SLIMS "major" version that your plugin will run on
# The first two numbers have to match the version of SLIMS where you plan to install the plugin
# If you have 6.8.16, this needs to be 6.8.X, and X must be <= 16 to run on your instance
# The third number should be 0 unless there is a specific minor version where a service that you need to use was added
# 6.9.0 means it will run on any 6.9 minor version
apiVersion=6.9.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!--
~ Copyright 2021 Agilent Technologies Inc.
-->

<slimsgate>
<slimsgate-flow>
<id>create-order-and-schedule</id>
<name>Create order and schedule to workflow</name>
<usage>contentmanagement</usage>
<step>
<name>Create order</name>
<hidden>true</hidden>
<input>
<parameter>
<label>SLIMS_SELECT_SAMPLES</label>
<name>SLIMS_SELECT_SAMPLES</name>
<type>StringArray</type>
<required>true</required>
</parameter>
</input>
<process>
<route>create-order-and-schedule</route>
</process>
<output>
<parameter>
<name>executionFeedback</name>
<type>ValueMap</type>
</parameter>
</output>
</step>
<step>
<name>Feedback</name>
<input>
<parameter>
<label>Plugin results</label>
<name>results</name>
<type>Feedback</type>
<width>500</width>
<referencedDefaultValue>executionFeedback</referencedDefaultValue>
</parameter>
</input>
<process>
<route>slimsgate-dummy-route</route>
</process>
</step>
</slimsgate-flow>
</slimsgate>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
~ Copyright 2021 Agilent Technologies Inc.
-->

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">

<!-- =========== GENERIC ROUTES ================ -->

<camelContext id="camel-context" xmlns="http://camel.apache.org/schema/spring">
<!-- Here, you'll put the name of the RouteBuilder class you defined, camel-case. The first letter is lower-cased
because we are referring to an instance of our Builder class, rather than the Builder class itself. -->
<!-- It is technically possible to build your routes here in this XML instead of using a RouteBuilder, but we
strongly suggest using the RouteBuilder class -->
<routeBuilder ref="createOrderAndScheduleBuilder"/>
</camelContext>

</beans>
Loading