Compare commits
24 commits
dynamixs-a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 637a3f65e6 | |||
| ec49e84f53 | |||
| 2f6144fc35 | |||
| 66e7257e65 | |||
| a1760da2b3 | |||
| f8a258a1f7 | |||
| b5bb9ac635 | |||
| 4498f23458 | |||
| c1b9b621f6 | |||
| 26d9e8a807 | |||
| dd48226be5 | |||
| c93d148bc2 | |||
| 391da04900 | |||
| 72b29632b4 | |||
| 1c4af10c34 | |||
| f26c503b50 | |||
| a8950c433e | |||
| a98b30cbbd | |||
| f0e52d8bd1 | |||
| b4b0f6f8f5 | |||
| 8ced4940b7 | |||
| 18199c8f8f | |||
| 72de18959a | |||
| 97a0118c6a |
6
.env
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Docker Config
|
||||
PROJECT_PREFIX=dynamixs-ai-super-office
|
||||
|
||||
# LLM Config
|
||||
LLM_API_ENDPOINT=https://api.llama.cpp.imixs.com/
|
||||
LLM_API_KEY=7fdb663fa87ea16731c1e0ece8ad3214e358423eabf2403188110c731ce07321
|
||||
10
Dockerfile
|
|
@ -1,13 +1,7 @@
|
|||
#FROM imixs/imixs-office-workflow:5.1.5-wildfly-29.0.1.Final-jdk17
|
||||
FROM imixs/imixs-office-workflow:5.1.6-SNAPSHOT-wildfly-29.0.1.Final-jdk17
|
||||
|
||||
# Debug
|
||||
# Setup configuration
|
||||
#COPY ./docker/configuration/wildfly/standalone-debug.xml /opt/jboss/wildfly/standalone/configuration/
|
||||
|
||||
FROM ghcr.io/dynamixs-ai/ai-platform:latest
|
||||
|
||||
# Deploy artefact
|
||||
RUN rm -r /opt/jboss/wildfly/standalone/deployments/*
|
||||
# Deploy artefact
|
||||
ADD ./dynamixs-ai-app/target/dynamixs-ai*.war /opt/jboss/wildfly/standalone/deployments/
|
||||
COPY ./target/*.war /opt/jboss/wildfly/standalone/deployments/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#FROM imixs/imixs-office-workflow:5.1.5-wildfly-29.0.1.Final-jdk17
|
||||
FROM imixs/imixs-office-workflow:5.1.6-SNAPSHOT-wildfly-29.0.1.Final-jdk17
|
||||
FROM ghcr.io/dynamixs-ai/ai-platform:latest
|
||||
|
||||
# Deploy artefact
|
||||
RUN rm -r /opt/jboss/wildfly/standalone/deployments/*
|
||||
COPY ./target/*.war /opt/jboss/wildfly/standalone/deployments/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
# Dynamixs AI
|
||||
|
||||
Dies ist das interne Super Office von Dynamixs.ai
|
||||
|
||||
Wir verwenden OIDC / Keyclaok für die Anmeldung
|
||||
|
||||
This repository contains the source code as also build scripts to setup an Dynamixs AI instance.
|
||||
|
||||
**Topics**
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
/****************************************************************************
|
||||
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* This Source Code may also be made available under the terms of the
|
||||
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
|
||||
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
****************************************************************************/
|
||||
|
||||
package ai.dynamixs.cognition;
|
||||
|
||||
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_DEADLOCK;
|
||||
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_ENABLED;
|
||||
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_INITIALDELAY;
|
||||
import static org.imixs.workflow.engine.AsyncEventSchedulerConfig.ASYNCEVENT_PROCESSOR_INTERVAL;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.imixs.workflow.engine.AsyncEventService;
|
||||
import org.imixs.workflow.engine.EventLogService;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.annotation.security.DeclareRoles;
|
||||
import jakarta.annotation.security.RunAs;
|
||||
import jakarta.ejb.Singleton;
|
||||
import jakarta.ejb.Startup;
|
||||
import jakarta.ejb.Timeout;
|
||||
import jakarta.ejb.Timer;
|
||||
import jakarta.ejb.TimerConfig;
|
||||
import jakarta.ejb.TimerService;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The CognitoEventScheduler starts a scheduler service to process cognition
|
||||
* events in an asynchronous way by calling the CognitoEventService.
|
||||
* <p>
|
||||
* The Scheduler runs on a non-persistent ejb timer with the same interval
|
||||
* settings as the AsyncEventProcessor
|
||||
* <p>
|
||||
* Configuration is read from the environment variables
|
||||
* 'ASYNCEVENT_PROCESSOR_INTERVAL' and an optional delay defined by
|
||||
* 'ASYNCEVENT_PROCESSOR_INITIALDELAY'. To enable the processor
|
||||
* 'ASYNCEVENT_PROCESSOR_ENABLED' must be set to true (default=false).
|
||||
* 'ASYNCEVENT_PROCESSOR_DEADLOCK' deadlock timeout
|
||||
* <p>
|
||||
* In a clustered environment this timer runs in each cluster member that
|
||||
* contains the EJB. So this means the non-persistent EJB Timer scales
|
||||
* horizontal within a clustered environment – e.g. a Kubernetes cluster.
|
||||
*
|
||||
* @see AsyncEventService
|
||||
* @version 1.1
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
|
||||
@Startup
|
||||
@Singleton
|
||||
public class CognitoEventScheduler {
|
||||
|
||||
// enabled
|
||||
@Inject
|
||||
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_ENABLED, defaultValue = "false")
|
||||
boolean enabled;
|
||||
|
||||
// timeout interval in ms
|
||||
@Inject
|
||||
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_INTERVAL, defaultValue = "1000")
|
||||
long interval;
|
||||
|
||||
// initial delay in ms
|
||||
@Inject
|
||||
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_INITIALDELAY, defaultValue = "0")
|
||||
long initialDelay;
|
||||
|
||||
// deadlock timeout interval in ms
|
||||
@Inject
|
||||
@ConfigProperty(name = ASYNCEVENT_PROCESSOR_DEADLOCK, defaultValue = "60000")
|
||||
long deadLockInterval;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CognitoEventScheduler.class.getName());
|
||||
|
||||
@Resource
|
||||
TimerService timerService;
|
||||
|
||||
@Inject
|
||||
CognitoEventService cognitoEventService;
|
||||
|
||||
@Inject
|
||||
EventLogService eventLogService;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (enabled) {
|
||||
|
||||
// Registering a non-persistent Timer Service.
|
||||
final TimerConfig timerConfig = new TimerConfig();
|
||||
timerConfig.setInfo("Dynamixs AI CognitoEventScheduler");
|
||||
timerConfig.setPersistent(false);
|
||||
timerService.createIntervalTimer(initialDelay, interval, timerConfig);
|
||||
logger.log(Level.INFO, "├── ✅ Started CognitoEventScheduler - initalDelay={0} inverval={1}",
|
||||
new Object[] { initialDelay, interval });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method delegates the event processing to the stateless ejb
|
||||
* AsyncEventProcessor.
|
||||
* <p>
|
||||
* Before processing the eventLog the method releases possible dead locks first.
|
||||
* Both methods are running in separate transactions
|
||||
*
|
||||
*/
|
||||
@Timeout
|
||||
public void run(Timer timer) {
|
||||
eventLogService.releaseDeadLocks(deadLockInterval,
|
||||
CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT,
|
||||
CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE);
|
||||
cognitoEventService.processEventLog();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
/****************************************************************************
|
||||
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* This Source Code may also be made available under the terms of the
|
||||
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
|
||||
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
****************************************************************************/
|
||||
|
||||
package ai.dynamixs.cognition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.imixs.ai.ImixsAIContextHandler;
|
||||
import org.imixs.ai.workflow.OpenAIAPIConnector;
|
||||
import org.imixs.ai.workflow.OpenAIAPIService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.AsyncEventScheduler;
|
||||
import org.imixs.workflow.engine.EventLogService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.engine.jpa.EventLog;
|
||||
import org.imixs.workflow.exceptions.AdapterException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
import jakarta.annotation.security.DeclareRoles;
|
||||
import jakarta.annotation.security.RunAs;
|
||||
import jakarta.ejb.LocalBean;
|
||||
import jakarta.ejb.Stateless;
|
||||
import jakarta.ejb.TransactionAttribute;
|
||||
import jakarta.ejb.TransactionAttributeType;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.persistence.OptimisticLockException;
|
||||
|
||||
/**
|
||||
* The CognitoEventService is responsible to process Dynamixs-AI Cognito events
|
||||
* in an asynchronous batch process. The CognitoEventService automatically
|
||||
* lookup eventLog entries of the topic "rag.event.*". The RAGEventService is
|
||||
* called only by the RAGEventScheduler which is implementing a
|
||||
* ManagedScheduledExecutorService.
|
||||
* <p>
|
||||
* The CognitoEventService reacts on events from the following types:
|
||||
* <ul>
|
||||
* <li>cognito.event.prompt - resoles the llm prompt based on the given workitem
|
||||
* and creates a cache event</li>
|
||||
* <li>cognito.event.cache - indicates that this entry is still cached in the
|
||||
* event log database</li>
|
||||
* </ul>
|
||||
* The processor look up the workItem by the $uniqueId.
|
||||
* <p>
|
||||
* To prevent concurrent processes to handle the same workitems the batch
|
||||
* process uses a Optimistic lock strategy. After fetching new event log entries
|
||||
* the processor updates the eventLog entry in a new transaction and set the
|
||||
* topic to 'batch.process.lock'. After that update we can be sure that no other
|
||||
* process is dealing with these entries. After completing the processing step
|
||||
* the eventlog entry will be removed.
|
||||
* <p>
|
||||
* To avoid ad deadlock the processor set an expiration time on the lock, so the
|
||||
* lock will be auto-released after 1 minute (batch.processor.deadlock).
|
||||
*
|
||||
* @see AsyncEventScheduler
|
||||
* @version 1.0
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
|
||||
@Stateless
|
||||
@LocalBean
|
||||
public class CognitoEventService {
|
||||
|
||||
public static final String EVENTLOG_TOPIC_COGNITO_PROMPT = "cognito.event.prompt";
|
||||
public static final String EVENTLOG_TOPIC_COGNITO_CACHE = "cognito.event.cache";
|
||||
|
||||
public static final String ITEM_PROMPT_DEFINITION = "prompt.definition";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CognitoEventService.class.getName());
|
||||
|
||||
@Inject
|
||||
EventLogService eventLogService;
|
||||
|
||||
@Inject
|
||||
private WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
private OpenAIAPIService llmService;
|
||||
|
||||
@Inject
|
||||
ImixsAIContextHandler imixsAIContextHandler;
|
||||
|
||||
@Inject
|
||||
CognitoLockHandler cognitoLockHandler;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = OpenAIAPIConnector.ENV_LLM_SERVICE_ENDPOINT)
|
||||
Optional<String> serviceEndpoint;
|
||||
|
||||
/**
|
||||
* The method lookups for cognito prompt event log entries and updates the ....
|
||||
* information
|
||||
* <p>
|
||||
* Each eventLogEntry provides optional a prompt template
|
||||
*
|
||||
*/
|
||||
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
|
||||
public void processEventLog() {
|
||||
long l = System.currentTimeMillis();
|
||||
|
||||
// test for new event log entries by timeout...
|
||||
List<EventLog> events = eventLogService.findEventsByTimeout(100,
|
||||
CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT, CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE);
|
||||
|
||||
if (events.size() > 0) {
|
||||
logger.log(Level.INFO, "├── 🔃 processing {0} Cognito events....", events.size());
|
||||
|
||||
// do we know the endpoint?
|
||||
if (!serviceEndpoint.isPresent()) {
|
||||
logger.log(Level.WARNING,
|
||||
"├── ⚠️ Missing environment var 'llm.service.endpoint' - can not process cognito events!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (EventLog eventLogEntry : events) {
|
||||
try {
|
||||
boolean llmAPIDebug = true;
|
||||
logger.log(Level.INFO,
|
||||
"│ ├── Event: " + eventLogEntry.getTopic() + " - " + eventLogEntry.getRef());
|
||||
// first try to lock the eventLog entry....
|
||||
if (eventLogService.lock(eventLogEntry)) {
|
||||
|
||||
// Index / Update event?
|
||||
ItemCollection workitem = workflowService.getWorkItem(eventLogEntry.getRef());
|
||||
if (workitem == null) {
|
||||
logger.log(Level.WARNING, "│ ├── ⚠️ unable to read workitem: " + eventLogEntry.getRef());
|
||||
eventLogService.removeEvent(eventLogEntry.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemCollection promptItemCol = new ItemCollection(eventLogEntry.getData());
|
||||
|
||||
switch (eventLogEntry.getTopic()) {
|
||||
|
||||
case CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT + ".lock":
|
||||
|
||||
// load the promptDefinition from the event data object
|
||||
|
||||
String promptTemplate = promptItemCol.getItemValueString(ITEM_PROMPT_DEFINITION);
|
||||
|
||||
imixsAIContextHandler.setWorkItem(workitem);
|
||||
imixsAIContextHandler.addPromptDefinition(promptTemplate);
|
||||
|
||||
String llmPrompt = imixsAIContextHandler.toString();
|
||||
// if we have a prompt we call the llm api endpoint
|
||||
if (llmPrompt != null && !llmPrompt.isBlank()) {
|
||||
String llmAPIEndpoint = serviceEndpoint.get();
|
||||
// postPromptCompletion
|
||||
// JsonObject jsonPrompt =
|
||||
// llmService.buildJsonPromptObjectV1(imixsAIContextHandler);
|
||||
String completionResult = llmService.postPromptCompletion(imixsAIContextHandler,
|
||||
llmAPIEndpoint);
|
||||
// process the ai.result....
|
||||
if (llmAPIDebug) {
|
||||
logger.info("===> Completion Result: ");
|
||||
logger.info(completionResult);
|
||||
}
|
||||
|
||||
String resultMessage = llmService.processPromptResult(completionResult, "", workitem);
|
||||
|
||||
// if the workitem is not locked we can safety update the $workflowabstarct
|
||||
if (!cognitoLockHandler.isLocked(workitem.getUniqueID())) {
|
||||
logger.log(Level.INFO,
|
||||
"│ ├── ✓ workitem not locked - updating $workflowabstract...");
|
||||
workitem.setItemValue("$workflowabstract", resultMessage);
|
||||
workflowService.getDocumentService().save(workitem);
|
||||
} else {
|
||||
// workitem is still in edit mode - so we create a cache event that just stores
|
||||
// the result. This is an async caching mechanism for the front end.
|
||||
logger.log(Level.INFO,
|
||||
"│ ├── ⚐ workitem locked - create COGNITO_CACHE event...");
|
||||
promptItemCol.setItemValue("$workflowabstract", resultMessage);
|
||||
// create a new event
|
||||
eventLogService.createEvent(CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE,
|
||||
workitem.getUniqueID(),
|
||||
promptItemCol);
|
||||
}
|
||||
} else {
|
||||
logger.finest(
|
||||
"......no prompt definition found for " + workitem.getUniqueID());
|
||||
}
|
||||
// finally remove the event log entry...
|
||||
eventLogService.removeEvent(eventLogEntry.getId());
|
||||
break;
|
||||
|
||||
case CognitoEventService.EVENTLOG_TOPIC_COGNITO_CACHE + ".lock":
|
||||
logger.log(Level.INFO,
|
||||
"│ ├── process COGNITO_CACHE event...");
|
||||
if (!cognitoLockHandler.isLocked(workitem.getUniqueID())) {
|
||||
logger.log(Level.INFO,
|
||||
"│ ├── ✓ workitem not locked - updating $workflowabstract...");
|
||||
// ItemCollection promptItemCol = new ItemCollection(eventLogEntry.getData());
|
||||
String resultMessage = promptItemCol.getItemValueString("$workflowabstract");
|
||||
workitem.setItemValue("$workflowabstract", resultMessage);
|
||||
workflowService.getDocumentService().save(workitem);
|
||||
// finally remove the event log entry...
|
||||
eventLogService.removeEvent(eventLogEntry.getId());
|
||||
} else {
|
||||
// repeat event until workitem is unlocked
|
||||
eventLogService.unlock((eventLogEntry));
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// no op
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (OptimisticLockException e) {
|
||||
// lock was not possible - continue....
|
||||
logger.log(Level.INFO, "│ ├── ⚠️ unable to lock AsyncEvent: {0}", e.getMessage());
|
||||
} catch (PluginException | AdapterException e) {
|
||||
logger.log(Level.WARNING, e.getErrorCode() + " - " + e.getMessage());
|
||||
// remove the event log entry...
|
||||
eventLogService.removeEvent(eventLogEntry.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, "├── ✅ {0} CognitoEvents processed in {1}ms",
|
||||
new Object[] { events.size(), System.currentTimeMillis() - l });
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,274 +0,0 @@
|
|||
/****************************************************************************
|
||||
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
|
||||
* https://www.imixs.com
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* This Source Code may also be made available under the terms of the
|
||||
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
|
||||
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
****************************************************************************/
|
||||
package ai.dynamixs.cognition;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.imixs.workflow.faces.data.WorkflowEvent;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.interceptor.Interceptor;
|
||||
|
||||
/**
|
||||
* The CognitoLockHandler is an application scoped CDI bean that holds a list of
|
||||
* workitem uniqueIds currently in edit mode. This caching mechanism is used by
|
||||
* the {@code CognitoEventService} to avoid optimistic lock exceptions.
|
||||
* <p>
|
||||
* The IDs are stored in the lock cache. The CognitoEventService looks up an ID
|
||||
* in this cache before updating a workitem in a safe way.
|
||||
* <p>
|
||||
* It may happen that a user switches into edit mode
|
||||
* ({@link WorkflowEvent#DOCUMENT_CHANGED}) without updating the workitem. For
|
||||
* this reason a locked ID will be released after {@value #LOCK_TIMEOUT_SECONDS}
|
||||
* seconds automatically.
|
||||
* <p>
|
||||
* <strong>Thread Safety:</strong> This implementation uses a
|
||||
* {@link ConcurrentHashMap} to ensure thread-safe operations in a
|
||||
* multi-user-environment where the same workitem can be opened by different
|
||||
* users in parallel.
|
||||
*
|
||||
* @author rsoika
|
||||
* @version 1.0
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class CognitoLockHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CognitoLockHandler.class.getName());
|
||||
|
||||
/**
|
||||
* Lock timeout in seconds. After this duration, a lock is considered stale and
|
||||
* will be automatically released.
|
||||
*/
|
||||
public static final long LOCK_TIMEOUT_SECONDS = 120;
|
||||
|
||||
/**
|
||||
* Thread-safe cache storing workitem uniqueIds mapped to their lock timestamp.
|
||||
* The timestamp is used to determine if a lock has expired.
|
||||
*/
|
||||
private final Map<String, Instant> lockCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* WorkflowEvent listener that manages the lock cache based on document
|
||||
* lifecycle events.
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>{@link WorkflowEvent#DOCUMENT_CHANGED}: Adds the workitem's uniqueID to
|
||||
* the lock cache (lock operation)</li>
|
||||
* <li>{@link WorkflowEvent#DOCUMENT_AFTER_SAVE}: Removes the workitem's
|
||||
* uniqueID from the lock cache (unlock operation)</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This observer is executed with {@link Interceptor.Priority#LIBRARY_BEFORE}
|
||||
* priority to ensure it runs before other observers.
|
||||
*
|
||||
* @param workflowEvent the workflow event containing the workitem and event
|
||||
* type
|
||||
* @throws PluginException if an error occurs during event processing
|
||||
*/
|
||||
public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent)
|
||||
throws PluginException {
|
||||
|
||||
int eventType = workflowEvent.getEventType();
|
||||
String uniqueId = extractUniqueId(workflowEvent);
|
||||
|
||||
if (uniqueId == null || uniqueId.isEmpty()) {
|
||||
logger.log(Level.FINE, "Skipping lock operation - workitem has no uniqueId");
|
||||
return;
|
||||
}
|
||||
|
||||
// Lock the workitem when user enters edit mode
|
||||
if (WorkflowEvent.WORKITEM_CHANGED == eventType) {
|
||||
lock(uniqueId);
|
||||
logger.log(Level.INFO, "Workitem locked: uniqueId={0}, active locks={1}",
|
||||
new Object[] { uniqueId, lockCache.size() });
|
||||
}
|
||||
|
||||
// Unlock the workitem after successful save
|
||||
if (WorkflowEvent.WORKITEM_AFTER_PROCESS == eventType) {
|
||||
boolean wasLocked = unlock(uniqueId);
|
||||
if (wasLocked) {
|
||||
logger.log(Level.INFO, "Workitem unlocked after process: uniqueId={0}, remaining locks={1}",
|
||||
new Object[] { uniqueId, lockCache.size() });
|
||||
} else {
|
||||
logger.log(Level.INFO, "Workitem was not locked (possibly expired): uniqueId={0}",
|
||||
uniqueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given workitem uniqueID is currently locked (in edit mode).
|
||||
* <p>
|
||||
* This method also performs cleanup of stale locks. If the lock for the given
|
||||
* ID has exceeded the timeout ({@value #LOCK_TIMEOUT_SECONDS} seconds), it will
|
||||
* be automatically removed and this method returns {@code false}.
|
||||
*
|
||||
* @param id the unique identifier of the workitem to check
|
||||
* @return {@code true} if the workitem is currently locked and the lock has not
|
||||
* expired, {@code false} otherwise
|
||||
*/
|
||||
public boolean isLocked(String id) {
|
||||
if (id == null || id.isEmpty()) {
|
||||
logger.log(Level.FINE, "isLocked called with null or empty id - returning false");
|
||||
return false;
|
||||
}
|
||||
|
||||
Instant lockTimestamp = lockCache.get(id);
|
||||
|
||||
if (lockTimestamp == null) {
|
||||
logger.log(Level.FINE, "Workitem not locked: uniqueId={0}", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if lock has expired
|
||||
if (isLockExpired(lockTimestamp)) {
|
||||
logger.log(Level.INFO, "Lock expired and removed: uniqueId={0}, locked since={1}",
|
||||
new Object[] { id, lockTimestamp });
|
||||
lockCache.remove(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
long lockedSeconds = java.time.Duration.between(lockTimestamp, Instant.now()).getSeconds();
|
||||
logger.log(Level.FINE, "Workitem is locked: uniqueId={0}, locked for {1}s",
|
||||
new Object[] { id, lockedSeconds });
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a workitem uniqueID to the lock cache with the current timestamp.
|
||||
* <p>
|
||||
* If the ID is already in the cache, the timestamp will be updated (lock
|
||||
* refresh).
|
||||
*
|
||||
* @param id the unique identifier of the workitem to lock
|
||||
*/
|
||||
public void lock(String id) {
|
||||
if (id == null || id.isEmpty()) {
|
||||
logger.log(Level.WARNING, "Attempted to lock with null or empty id - operation ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
Instant previousLock = lockCache.put(id, Instant.now());
|
||||
|
||||
if (previousLock != null) {
|
||||
logger.log(Level.FINE, "Lock refreshed: uniqueId={0}, previous lock from={1}",
|
||||
new Object[] { id, previousLock });
|
||||
} else {
|
||||
logger.log(Level.FINE, "New lock created: uniqueId={0}", id);
|
||||
}
|
||||
|
||||
// Opportunistic cleanup of expired locks
|
||||
cleanupExpiredLocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a workitem uniqueID from the lock cache.
|
||||
*
|
||||
* @param id the unique identifier of the workitem to unlock
|
||||
* @return {@code true} if the workitem was locked and is now unlocked,
|
||||
* {@code false} if the workitem was not locked
|
||||
*/
|
||||
public boolean unlock(String id) {
|
||||
if (id == null || id.isEmpty()) {
|
||||
logger.log(Level.WARNING, "Attempted to unlock with null or empty id - operation ignored");
|
||||
return false;
|
||||
}
|
||||
|
||||
Instant removed = lockCache.remove(id);
|
||||
|
||||
if (removed != null) {
|
||||
long lockedDuration = java.time.Duration.between(removed, Instant.now()).getSeconds();
|
||||
logger.log(Level.FINE, "Lock removed: uniqueId={0}, was locked for {1}s",
|
||||
new Object[] { id, lockedDuration });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of active locks in the cache.
|
||||
* <p>
|
||||
* <strong>Note:</strong> This count may include expired locks that have not yet
|
||||
* been cleaned up.
|
||||
*
|
||||
* @return the number of entries in the lock cache
|
||||
*/
|
||||
public int getLockCount() {
|
||||
return lockCache.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all expired locks from the cache.
|
||||
* <p>
|
||||
* This method is called opportunistically during lock operations to prevent
|
||||
* unbounded cache growth.
|
||||
*/
|
||||
public void cleanupExpiredLocks() {
|
||||
int initialSize = lockCache.size();
|
||||
|
||||
lockCache.entrySet().removeIf(entry -> {
|
||||
boolean expired = isLockExpired(entry.getValue());
|
||||
if (expired) {
|
||||
logger.log(Level.FINE, "Cleaning up expired lock: uniqueId={0}, locked since={1}",
|
||||
new Object[] { entry.getKey(), entry.getValue() });
|
||||
}
|
||||
return expired;
|
||||
});
|
||||
|
||||
int removed = initialSize - lockCache.size();
|
||||
if (removed > 0) {
|
||||
logger.log(Level.INFO, "Expired locks cleanup completed: removed={0}, remaining={1}",
|
||||
new Object[] { removed, lockCache.size() });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a lock timestamp has exceeded the timeout threshold.
|
||||
*
|
||||
* @param lockTimestamp the timestamp when the lock was created
|
||||
* @return {@code true} if the lock is expired, {@code false} otherwise
|
||||
*/
|
||||
private boolean isLockExpired(Instant lockTimestamp) {
|
||||
return lockTimestamp.plusSeconds(LOCK_TIMEOUT_SECONDS).isBefore(Instant.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the uniqueId from the workitem contained in the workflow event.
|
||||
*
|
||||
* @param workflowEvent the workflow event
|
||||
* @return the uniqueId of the workitem, or {@code null} if not available
|
||||
*/
|
||||
private String extractUniqueId(WorkflowEvent workflowEvent) {
|
||||
if (workflowEvent == null || workflowEvent.getWorkitem() == null) {
|
||||
logger.log(Level.WARNING, "WorkflowEvent or workitem is null - cannot extract uniqueId");
|
||||
return null;
|
||||
}
|
||||
|
||||
String uniqueId = workflowEvent.getWorkitem().getUniqueID();
|
||||
|
||||
if (uniqueId == null || uniqueId.isEmpty()) {
|
||||
logger.log(Level.FINE, "Workitem has no uniqueId (possibly a new document)");
|
||||
}
|
||||
|
||||
return uniqueId;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
/****************************************************************************
|
||||
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* This Source Code may also be made available under the terms of the
|
||||
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
|
||||
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
****************************************************************************/
|
||||
|
||||
package ai.dynamixs.cognition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.ai.workflow.ImixsAIPromptService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.EventLogService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
import ai.dynamixs.ChronicleTextBuilder;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The CognitoPlugin is a generic plugin to generate an cognito.create.event.
|
||||
* This event is processed by the `CognitoEventService` to generate an AI based
|
||||
* workflow abstract
|
||||
* <p>
|
||||
* The plugin can be activated by the following workflow result tag
|
||||
*
|
||||
* <pre>
|
||||
{@code
|
||||
<dynamixs-ai name="COGNITO" />
|
||||
}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The embedded tag 'debug' is optional
|
||||
*
|
||||
* <p>
|
||||
* The prompt definition is either loaded from the corresponding BPMN event
|
||||
* (DataObject) or generated as generic default template in case that no
|
||||
* PromptDefinition is assigned to the current event.
|
||||
*
|
||||
*
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
public class CognitoPlugin extends org.imixs.ai.rag.workflow.RAGIndexPlugin {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CognitoPlugin.class.getName());
|
||||
|
||||
@Inject
|
||||
private WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
private EventLogService eventLogService;
|
||||
|
||||
@Inject
|
||||
private ImixsAIPromptService imixsAIPromptService;
|
||||
|
||||
@Override
|
||||
public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException {
|
||||
|
||||
// do only run on type = workitem!
|
||||
if (!workitem.getType().equals("workitem")) {
|
||||
// no op!
|
||||
return workitem;
|
||||
}
|
||||
|
||||
// read optional configuration form the model or imixs.properties....
|
||||
List<ItemCollection> cognitoAIDefinitions = workflowService.evalWorkflowResultXML(event, "dynamixs-ai",
|
||||
"COGNITO", workitem, false);
|
||||
|
||||
// COGNITO Mode?
|
||||
if (cognitoAIDefinitions != null && cognitoAIDefinitions.size() > 0) {
|
||||
logger.info("├── running Dynamixs.AI Cognito Plugin");
|
||||
// test if the event provides a Prompt template!
|
||||
String promptTemplate = imixsAIPromptService.loadPromptTemplateByModelElement(event);
|
||||
|
||||
if (promptTemplate != null && !promptTemplate.isBlank()) {
|
||||
logger.info("│ ├── loaded custom cognito prompt template from event");
|
||||
} else {
|
||||
promptTemplate = buildDefaultPromptTemplate(workitem);
|
||||
logger.info("│ ├── created default cognito prompt template");
|
||||
}
|
||||
|
||||
// we create a data object that holds the template
|
||||
ItemCollection promptItemCol = new ItemCollection();
|
||||
promptItemCol.setItemValue("category", "cognition");
|
||||
promptItemCol.setItemValue(CognitoEventService.ITEM_PROMPT_DEFINITION, promptTemplate);
|
||||
eventLogService.createEvent(CognitoEventService.EVENTLOG_TOPIC_COGNITO_PROMPT, workitem.getUniqueID(),
|
||||
promptItemCol);
|
||||
}
|
||||
|
||||
return workitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method generates a generic prompt definition including a prompt template
|
||||
* including the workflow chronicle data.
|
||||
*
|
||||
* @param workitem
|
||||
* @return
|
||||
*/
|
||||
private String buildDefaultPromptTemplate(ItemCollection workitem) {
|
||||
|
||||
// generate default template
|
||||
ChronicleTextBuilder chronicleTextBuilder = new ChronicleTextBuilder(workitem);
|
||||
String promptTemplate = chronicleTextBuilder.build();
|
||||
|
||||
String result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
|
||||
"<PromptDefinition>\n" + //
|
||||
"\t<prompt_options>{\"n_predict\": 2048, \"temperature\": 0.2, \"top_p\": 0.9}</prompt_options>\n" + //
|
||||
"\n" + //
|
||||
" <prompt role=\"system\"><![CDATA[\n" + //
|
||||
"You are a process analyst. A workflow has just been completed.\n" + //
|
||||
"\n" + //
|
||||
"Create a brief project insight:\n" + //
|
||||
"- What specifically happened? (Include relevant names from people, companies, products when mentioned.)\n"
|
||||
+ //
|
||||
"- Is there anything unusual or important to remember for the future? (Pay attention to user comments - they often contain important warnings or decisions.)\n"
|
||||
+ //
|
||||
"\n" + //
|
||||
"No general advice. Only project-specific facts and insights.]]>\n" + //
|
||||
" </prompt>\n" + //
|
||||
" <prompt role=\"user\"><![CDATA[\n" + promptTemplate + "]]>\n" + //
|
||||
" </prompt>\n" + //
|
||||
"\n" + //
|
||||
"</PromptDefinition> ";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
package ai.dynamixs;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.ai.ImixsAIContextHandler;
|
||||
import org.imixs.ai.workflow.ImixsAIPromptService;
|
||||
import org.imixs.ai.workflow.OpenAIAPIService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.ConditionalExpressionEvent;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.AdapterException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.transaction.TransactionScoped;
|
||||
|
||||
/**
|
||||
* The ConditionalAIAdapter reacts on CDI Events of type BPMNConditionEvent and
|
||||
* evaluates a condition against an LLM
|
||||
* <p>
|
||||
* The Adapter defines a Default Expression template for LLMs. The BPMN
|
||||
* Configuration must only include the user prompt. See the following example:
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
<imixs-ai name="CONDITION">
|
||||
<debug>true</debug>
|
||||
<endpoint><propertyvalue>llm.service.endpoint</propertyvalue></endpoint>
|
||||
<result-item>my.condition</result-item>
|
||||
<prompt><![CDATA[
|
||||
Is Germany an EU member country? ]]>
|
||||
</prompt>
|
||||
</imixs-ai>
|
||||
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Caching: The ConditionalAIAdapter implements a caching mechnaism. The adapter
|
||||
* class stores the hash value in to the item <result-item>.hash to avoid
|
||||
* duplicate calls against the llm with the same prompt in one processing cycle!
|
||||
*/
|
||||
@TransactionScoped
|
||||
public class ConditionalAIAdapter implements Serializable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ConditionalAIAdapter.class.getName());
|
||||
|
||||
// Transaction-scoped cache - survives across multiple eval() calls
|
||||
private Map<Long, String> promptResultCache = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
protected WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
protected ImixsAIPromptService imixsAIPromptService;
|
||||
|
||||
@Inject
|
||||
protected OpenAIAPIService llmService;
|
||||
|
||||
@Inject
|
||||
ImixsAIContextHandler imixsAIContextHandler;
|
||||
|
||||
public static String DEFAULT_EXPRESSION_TEMPLATE = "<imixs-ai name=\"CONDITION\">\n" + //
|
||||
" <debug>true</debug>\n" + //
|
||||
" <endpoint><propertyvalue>llm.service.endpoint</propertyvalue></endpoint>\n" + //
|
||||
" <result-event>BOOLEAN</result-event>\n" + //
|
||||
" <PromptDefinition>\n" + //
|
||||
" <prompt_options>{\"n_predict\": 16, \"temperature\": 0 }</prompt_options>\n" + //
|
||||
" <prompt role=\"system\"><![CDATA[\n" + //
|
||||
" Evaluate the following condition to 'true' or 'false'. Do only answer with 'true' or 'false'. Do not add any additional context into your answer.]]>\n"
|
||||
+ //
|
||||
" </prompt>\n" + //
|
||||
" </PromptDefinition>\n" + //
|
||||
"</imixs-ai>";
|
||||
|
||||
/**
|
||||
* Test method
|
||||
*
|
||||
* @param conditionEvent
|
||||
* @throws PluginException
|
||||
* @throws AdapterException
|
||||
*/
|
||||
public void onConditionEvent(@Observes ConditionalExpressionEvent conditionalEvent)
|
||||
throws PluginException, AdapterException {
|
||||
|
||||
// run only if we have a prompt definition
|
||||
String condition = conditionalEvent.getCondition();
|
||||
if (condition != null && condition.contains("<imixs-ai")) {
|
||||
long l = System.currentTimeMillis();
|
||||
List<ItemCollection> llmConditionDefinitions;
|
||||
boolean llmAPIDebug = false;
|
||||
|
||||
condition = condition.trim();
|
||||
llmConditionDefinitions = workflowService.evalXMLExpressionList(
|
||||
conditionalEvent.getCondition(), "imixs-ai", "CONDITION", conditionalEvent.getWorkitem(), true);
|
||||
|
||||
for (ItemCollection promptDefinition : llmConditionDefinitions) {
|
||||
String llmAPIEndpoint = imixsAIPromptService.parseLLMEndpointByBPMN(promptDefinition);
|
||||
String userPrompt = promptDefinition.getItemValueString("prompt");
|
||||
|
||||
if ("true".equalsIgnoreCase(promptDefinition.getItemValueString("debug"))) {
|
||||
llmAPIDebug = true;
|
||||
}
|
||||
if (llmAPIDebug) {
|
||||
logger.info("├── evaluate conditional expression");
|
||||
}
|
||||
// set DEFAULT_EXPRESSION_TEMPLATE.
|
||||
imixsAIContextHandler.setWorkItem(conditionalEvent.getWorkitem());
|
||||
imixsAIContextHandler.addPromptDefinition(DEFAULT_EXPRESSION_TEMPLATE);
|
||||
|
||||
// add the user prompt!
|
||||
imixsAIContextHandler.addMessage(ImixsAIContextHandler.ROLE_USER, userPrompt,
|
||||
workflowService.getSessionContext().getCallerPrincipal().getName(), null);
|
||||
|
||||
// POST PromptCompletion
|
||||
JsonObject jsonPrompt = imixsAIContextHandler.getOpenAIMessageObject();
|
||||
if (llmAPIDebug) {
|
||||
logger.info("│ ├── conditional prompt:");
|
||||
logger.info(jsonPrompt.toString());
|
||||
}
|
||||
|
||||
// Caching:
|
||||
// if jsonPrompt (hash) was already stored, we do not call the LLM
|
||||
long hashPrompt = jsonPrompt.hashCode();
|
||||
// Check transaction-scoped cache
|
||||
if (promptResultCache.containsKey(hashPrompt)) {
|
||||
if (llmAPIDebug) {
|
||||
logger.info("│ ├── reuse cached result from transaction cache - hash=" + hashPrompt);
|
||||
logger.info("└── ✓ evaluation time: " + (System.currentTimeMillis() - l) + "ms");
|
||||
}
|
||||
conditionalEvent.setCondition(promptResultCache.get(hashPrompt));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
String completionResult = llmService.postPromptCompletion(imixsAIContextHandler, llmAPIEndpoint);
|
||||
if (llmAPIDebug) {
|
||||
logger.info("│ ├── ⚙ Completion Request conditional expression...");
|
||||
}
|
||||
String conditionalExpressionResult = llmService.processPromptResult(completionResult, "BOOLEAN",
|
||||
conditionalEvent.getWorkitem());
|
||||
|
||||
// store the result message
|
||||
if (conditionalExpressionResult != null && !conditionalExpressionResult.isBlank()) {
|
||||
// trim result
|
||||
conditionalExpressionResult = conditionalExpressionResult.trim().toLowerCase();
|
||||
|
||||
if (!"true".equals(conditionalExpressionResult) && !"false".equals(conditionalExpressionResult)) {
|
||||
logger.warning(
|
||||
"│ ├── ⚠ Unexpected conditional expression result: " + conditionalExpressionResult);
|
||||
throw new PluginException(OpenAIAPIService.class.getSimpleName(),
|
||||
OpenAIAPIService.ERROR_PROMPT_INFERENCE,
|
||||
"Conditional expression should result into 'true' or 'false' only");
|
||||
}
|
||||
if (llmAPIDebug) {
|
||||
logger.info("│ ├── ⚐ Conditional expression result: " + conditionalExpressionResult);
|
||||
}
|
||||
boolean booleanExpressionResult = Boolean.parseBoolean(conditionalExpressionResult.trim());
|
||||
// Store in transaction-scoped cache
|
||||
promptResultCache.put(hashPrompt, "" + booleanExpressionResult);
|
||||
conditionalEvent.setCondition("" + booleanExpressionResult);
|
||||
logger.info("└── ✓ evaluation time: " + (System.currentTimeMillis() - l) + "ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
24
build.sh
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
|
||||
############################################################
|
||||
# The Dynamixs.AI Developer Script
|
||||
# start, build, hot, setup, deploy
|
||||
#
|
||||
############################################################
|
||||
|
||||
strip_dash() {
|
||||
echo "$1" | sed 's/^-//'
|
||||
}
|
||||
|
||||
echo " _ _ _ _ "
|
||||
echo " __| | _____ _(_) | |__ ___| |_ __"
|
||||
echo " / _\` |/ _ \\ \\ / / | | '_ \\ / _ \\ | \'_ \\"
|
||||
echo "| (_| | __/\ V /| | | | | | __/ | |_) |"
|
||||
echo " \__,_|\___| \_/ |_| |_| |_|\___|_| .__/ "
|
||||
echo " |_| "
|
||||
echo " Dynamixs.AI Build Script..."
|
||||
echo "_________________________________________"
|
||||
|
||||
# Update git
|
||||
git pull
|
||||
mvn clean install -DskipTests -Pimixs-cloud
|
||||
29
devi
|
|
@ -1,12 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
############################################################
|
||||
# The Imixs Developer Script
|
||||
# The Dynamixs.AI Developer Script
|
||||
# start, build, hot, setup, deploy
|
||||
#
|
||||
############################################################
|
||||
|
||||
# Funktion zum Entfernen des '-' Zeichens von einem Parameter
|
||||
strip_dash() {
|
||||
echo "$1" | sed 's/^-//'
|
||||
}
|
||||
|
|
@ -24,23 +23,31 @@ strip_dash() {
|
|||
if [[ "$(strip_dash $1)" == "setup" ]]; then
|
||||
echo " Dev Setup..."
|
||||
sudo chmod -R 777 docker/deployments/
|
||||
echo " starting dev enrvionment..."
|
||||
echo " starting dev environment..."
|
||||
mvn clean install -Pdebug
|
||||
cp ./*-app/target/*.war ./docker/deployments/
|
||||
docker compose -f ./docker/docker-compose-dev.yaml up
|
||||
docker compose -f ./docker-compose-dev.yaml up
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$(strip_dash $1)" == "start" ]]; then
|
||||
echo " Start Dev Environment..."
|
||||
docker compose -f ./docker/docker-compose-dev.yaml up
|
||||
docker compose -f ./docker-compose.yaml up
|
||||
fi
|
||||
|
||||
if [[ "$(strip_dash $1)" == "dev" ]]; then
|
||||
echo " Start Dev Environment..."
|
||||
mvn clean install -DskipTests -Pdebug
|
||||
docker compose -f ./docker-compose-dev.yaml up
|
||||
fi
|
||||
|
||||
if [[ "$(strip_dash $1)" == "docker" ]]; then
|
||||
echo " Buld Docker Image..."
|
||||
mvn clean install -Pdocker
|
||||
echo " Build Docker image..."
|
||||
mvn clean install -DskipTests -Pdocker
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if [[ "$(strip_dash $1)" == "build" ]]; then
|
||||
echo " Build and Autodeploy..."
|
||||
mvn clean install -DskipTests
|
||||
|
|
@ -58,11 +65,6 @@ if [[ "$(strip_dash $1)" == "hot" ]]; then
|
|||
cd ..
|
||||
fi
|
||||
|
||||
if [[ "$(strip_dash $1)" == "deploy" ]]; then
|
||||
echo " Deploy to Imixs-Cloud..."
|
||||
mvn clean install -Pimixs-cloud -DskipTests
|
||||
fi
|
||||
|
||||
|
||||
# Überprüfen, ob keine Parameter übergeben wurden - standard build
|
||||
if [[ $# -eq 0 ]]; then
|
||||
|
|
@ -70,11 +72,10 @@ if [[ $# -eq 0 ]]; then
|
|||
echo " Run with ./dev.sh -XXX"
|
||||
echo " "
|
||||
echo " -start : start Docker Containers"
|
||||
echo " -dev : start the Docker dev environment"
|
||||
echo " -build : build application and redeploy"
|
||||
echo " -hot : Manik Hotdeploy"
|
||||
echo " -docker : build the Docker image"
|
||||
echo " -test : run tests"
|
||||
echo " -deploy: Imixs-Cloud Deployment starten "
|
||||
echo " -setup : setup dev environment - rebuild docker containers "
|
||||
echo "_________________________________________"
|
||||
echo " "
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@ services:
|
|||
# PostgreSQL
|
||||
#######################
|
||||
db:
|
||||
image: postgres:9.6.1
|
||||
image: postgres:17.4
|
||||
environment:
|
||||
POSTGRES_PASSWORD: adminadmin
|
||||
POSTGRES_DB: office
|
||||
volumes:
|
||||
- dbdata-hai:/var/lib/postgresql/data
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
|
||||
#######################
|
||||
# Dynamixs AI
|
||||
#######################
|
||||
app:
|
||||
image: imixs/dynamixs-ai
|
||||
image: imixs/dynamixs-super-office
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
|
|
@ -44,10 +44,8 @@ services:
|
|||
WOPI_HOST_ENDPOINT: "http://app:8080/api/wopi/"
|
||||
COLLABORA_CONVERTER_URL: "http://collabora:9980/lool/convert-to/"
|
||||
|
||||
# Imixs-AI
|
||||
# Optional configured via imixs.properties
|
||||
LLM_SERVICE_ENDPOINT: ${LLM_API_ENDPOINT}
|
||||
LLM_SERVICE_ENDPOINT_APIKEY: ${LLM_API_KEY}
|
||||
# LLM Integration
|
||||
LLM_CONFIG_FILE: /opt/jboss/imixs-llm.xml
|
||||
|
||||
# Cassandra Embeddings
|
||||
EMBEDDINGS_CLUSTER_CONTACTPOINTS: "cassandra"
|
||||
|
|
@ -58,21 +56,20 @@ services:
|
|||
- "9990:9990"
|
||||
- "8787:8787"
|
||||
volumes:
|
||||
- ./deployments:/opt/jboss/wildfly/standalone/deployments/
|
||||
- ./import_examples:/opt/jboss/import_examples/
|
||||
- ./docker/deployments:/opt/jboss/wildfly/standalone/deployments/
|
||||
- ./docker/keys/imixs-llm.xml:/opt/jboss/imixs-llm.xml
|
||||
#- ./import_examples:/opt/jboss/import_examples/
|
||||
|
||||
# Mapping the host ip to the container
|
||||
# This setting is used for local testing only
|
||||
# Wildfly can access the keycloak server via the external host address
|
||||
extra_hosts:
|
||||
- "keycloak.imixs.local:host-gateway"
|
||||
# extra_hosts:
|
||||
# - "keycloak.imixs.local:host-gateway"
|
||||
|
||||
#######################
|
||||
# Tika OCR Service
|
||||
#######################
|
||||
tika:
|
||||
#image: imixs/tika
|
||||
#image: apache/tika:1.24.1-full
|
||||
image: apache/tika:3.2.0.0-full
|
||||
environment:
|
||||
TZ: "Europe/Berlin"
|
||||
|
|
@ -114,40 +111,17 @@ services:
|
|||
- password=adminadmin
|
||||
- extra_params=--o:ssl.enable=false
|
||||
- aliasgroup1=http://app:8080
|
||||
# volumes:
|
||||
# - ./configuration/collabora/fonts:/usr/share/fonts/truetype/more/
|
||||
# - ./configuration/collabora/fonts:/opt/cool/systemplate/usr/share/fonts/truetype/more/
|
||||
|
||||
#######################
|
||||
# Imixs Admin Client
|
||||
#######################
|
||||
imixsadmin:
|
||||
image: imixs/imixs-admin
|
||||
ports:
|
||||
- "8888:8080"
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./configuration/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheusdata:/prometheus/
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:10.4.0 # Aktuelle stabile Version
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin # Standardpasswort setzen
|
||||
volumes:
|
||||
- grafana-storage:/var/lib/grafana # Persistente Daten
|
||||
#networks:
|
||||
# - monitoring
|
||||
# imixsadmin:
|
||||
# image: imixs/imixs-admin
|
||||
# ports:
|
||||
# - "8888:8080"
|
||||
|
||||
volumes:
|
||||
dbdata-hai:
|
||||
dbkeycloak:
|
||||
dbdata:
|
||||
name: ${PROJECT_PREFIX}-dbdata
|
||||
cassandra_data:
|
||||
prometheusdata:
|
||||
grafana-storage:
|
||||
name: ${PROJECT_PREFIX}-cassandra_data
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
services:
|
||||
#######################
|
||||
# PostgreSQL
|
||||
#######################
|
||||
db:
|
||||
image: postgres:9.6.1
|
||||
environment:
|
||||
POSTGRES_PASSWORD: adminadmin
|
||||
POSTGRES_DB: office
|
||||
volumes:
|
||||
- dbdata-hai:/var/lib/postgresql/data
|
||||
|
||||
#######################
|
||||
# Dynamixs AI
|
||||
#######################
|
||||
app:
|
||||
image: imixs/dynamixs-ai
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
JAVA_OPTS: "-Dnashorn.args=--no-deprecation-warning"
|
||||
POSTGRES_USER: "postgres"
|
||||
POSTGRES_PASSWORD: "adminadmin"
|
||||
POSTGRES_CONNECTION: "jdbc:postgresql://db/office"
|
||||
TZ: "Europe/Berlin"
|
||||
LANG: "en_US.UTF-8"
|
||||
MAILGATEWAY: "localhost"
|
||||
ASYNCEVENT_PROCESSOR_ENABLED: "true"
|
||||
ASYNCEVENT_PROCESSOR_INITIALDELAY: "30000"
|
||||
OCR_SERVICE_ENDPOINT: "http://tika:9998/tika"
|
||||
OCR_SERVICE_MODE: "MODEL"
|
||||
#OCR_STRATEGY: "NO_OCR, OCR_ONLY, OCR_AND_TEXT_EXTRACTION, AUTO (default)"
|
||||
OCR_STRATEGY: "AUTO"
|
||||
# Collabora integration
|
||||
WOPI_PUBLIC_ENDPOINT: "http://localhost:9980"
|
||||
WOPI_DISCOVERY_ENDPOINT: "http://collabora:9980/hosting/discovery"
|
||||
WOPI_HOST_ENDPOINT: "http://imixs-documents:8080/api/wopi/"
|
||||
COLLABORA_CONVERTER_URL: "http://collabora:9980/lool/convert-to/"
|
||||
|
||||
# Imixs-Archive
|
||||
# ARCHIVE_SERVICE_ENDPOINT: "http://imixs-archive:8080/api"
|
||||
|
||||
# Imixs-AI
|
||||
# Optional configured via imixs.properties
|
||||
LLM_SERVICE_ENDPOINT: "https://llama.cpp.imixs.com/"
|
||||
LLM_SERVICE_ENDPOINT_USER: "admin"
|
||||
LLM_SERVICE_ENDPOINT_PASSWORD: "imixs4.null"
|
||||
|
||||
# Cassandra Embeddings
|
||||
EMBEDDINGS_CLUSTER_CONTACTPOINTS: "cassandra"
|
||||
EMBEDDINGS_CLUSTER_KEYSPACE: "embeddings"
|
||||
|
||||
# OIDC
|
||||
OIDCCONFIG_PROVIDERURI: "http://keycloak.imixs.local:8084/realms/dynamixsai/.well-known/openid-configuration"
|
||||
OIDCCONFIG_CLIENTID: "imixs"
|
||||
OIDCCONFIG_CLIENTSECRET: "aSuEXUeD7bARAlX8o3fLagSYbIagBrrM"
|
||||
OIDCCONFIG_REDIRECTURI: "http://localhost:8080/callback"
|
||||
#OIDCCONFIG_SCOPE: "openid profile email"
|
||||
#OIDCCONFIG_CLAIM_CALLERNAME: "preferred_username"
|
||||
#OIDCCONFIG_CLAIM_ROLES: "groups"
|
||||
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "9990:9990"
|
||||
- "8787:8787"
|
||||
volumes:
|
||||
- ./deployments:/opt/jboss/wildfly/standalone/deployments/
|
||||
- ./import_examples:/opt/jboss/import_examples/
|
||||
|
||||
# Mapping the host ip to the container
|
||||
# This setting is used for local testing only
|
||||
# Wildfly can access the keycloak server via the external host address
|
||||
extra_hosts:
|
||||
- "keycloak.imixs.local:host-gateway"
|
||||
|
||||
#######################
|
||||
# Tika OCR Service
|
||||
#######################
|
||||
tika:
|
||||
#image: imixs/tika
|
||||
image: apache/tika:1.24.1-full
|
||||
environment:
|
||||
TZ: "Europe/Berlin"
|
||||
ports:
|
||||
- "9998:9998"
|
||||
|
||||
#######################
|
||||
# Cassandra
|
||||
#######################
|
||||
cassandra:
|
||||
image: cassandra:5.0.4
|
||||
container_name: cassandra
|
||||
mem_limit: 2G # Mindestens 2 GB RAM für Cassandra 5.x
|
||||
mem_reservation: 1G # Reserviert 1 GB
|
||||
environment:
|
||||
- TZ="Europe/Berlin"
|
||||
- JVM_OPTS=-Xms1G -Xmx1G # Heap auf 1 GB begrenzen
|
||||
- CASSANDRA_CLUSTER_NAME=dynamixsAiCluster
|
||||
- CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch
|
||||
- CASSANDRA_DC=datacenter1
|
||||
- CASSANDRA_RACK=rack1
|
||||
ports:
|
||||
- "9042:9042" # CQL-Port
|
||||
- "7000:7000" # Inter-Node-Kommunikation
|
||||
- "7001:7001" # TLS-fähige Inter-Node-Kommunikation
|
||||
- "7199:7199" # JMX-Port
|
||||
volumes:
|
||||
- cassandra_data:/var/lib/cassandra
|
||||
|
||||
#######################
|
||||
# collabora Office Online
|
||||
#######################
|
||||
collabora:
|
||||
image: collabora/code:23.05.0.5.1
|
||||
#expose:
|
||||
# - 9980
|
||||
ports:
|
||||
- "9980:9980"
|
||||
environment:
|
||||
- username=admin
|
||||
- password=adminadmin
|
||||
- extra_params=--o:ssl.enable=false
|
||||
- aliasgroup1=http://app:8080
|
||||
volumes:
|
||||
- ./configuration/collabora/fonts:/usr/share/fonts/truetype/more/
|
||||
- ./configuration/collabora/fonts:/opt/cool/systemplate/usr/share/fonts/truetype/more/
|
||||
|
||||
#######################
|
||||
# Imixs Admin Client
|
||||
#######################
|
||||
# imixsadmin:
|
||||
# image: imixs/imixs-admin
|
||||
# ports:
|
||||
# - "8888:8080"
|
||||
|
||||
##################################
|
||||
# Keycloak SQL Server
|
||||
##################################
|
||||
dbkeycloak:
|
||||
image: postgres:15
|
||||
environment:
|
||||
POSTGRES_PASSWORD: adminadmin
|
||||
POSTGRES_USER: keycloak
|
||||
POSTGRES_DB: keycloak
|
||||
volumes:
|
||||
- dbkeycloak:/var/lib/postgresql/data
|
||||
|
||||
##################################
|
||||
# Keycloak Server
|
||||
##################################
|
||||
keycloak:
|
||||
#image: quay.io/keycloak/keycloak:23.0.5
|
||||
image: quay.io/keycloak/keycloak:26.2.4
|
||||
command:
|
||||
- start-dev
|
||||
environment:
|
||||
- KEYCLOAK_ADMIN=admin
|
||||
- KEYCLOAK_ADMIN_PASSWORD=adminadmin
|
||||
- KC_DB=postgres
|
||||
- KC_DB_URL=jdbc:postgresql://dbkeycloak:5432/keycloak
|
||||
- KC_DB_USER=keycloak
|
||||
- KC_DB_PASSWORD=adminadmin
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./configuration/keycloak/themes/:/opt/keycloak/themes/
|
||||
ports:
|
||||
- "8084:8080"
|
||||
|
||||
volumes:
|
||||
dbdata-hai:
|
||||
dbkeycloak:
|
||||
cassandra_data:
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
version: "3.1"
|
||||
services:
|
||||
|
||||
db:
|
||||
image: postgres:9.6.1
|
||||
environment:
|
||||
POSTGRES_PASSWORD: adminadmin
|
||||
POSTGRES_DB: office
|
||||
volumes:
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
app:
|
||||
image: imixs/imixs-office-workflow
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
TZ: "Europe/Berlin"
|
||||
JAVA_OPTS: "-Dnashorn.args=--no-deprecation-warning"
|
||||
MAILGATEWAY: "localhost"
|
||||
POSTGRES_USER: "postgres"
|
||||
POSTGRES_PASSWORD: "adminadmin"
|
||||
POSTGRES_CONNECTION: "jdbc:postgresql://db/office"
|
||||
METRICS_ENABLED: "true"
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "9990:9990"
|
||||
- "8787:8787"
|
||||
volumes:
|
||||
- ./deployments:/opt/jboss/wildfly/standalone/deployments/
|
||||
|
||||
# imixsadmin:
|
||||
# image: imixs/imixs-admin
|
||||
# ports:
|
||||
# - "8888:8080"
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheusdata:/prometheus/
|
||||
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:7.1.0
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
|
||||
volumes:
|
||||
prometheusdata:
|
||||
dbdata:
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Überprüfen, ob eine Eingabedatei angegeben wurde
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Verwendung: $0 input.csv"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
input_file="$1"
|
||||
output_file="${input_file%.*}_clean.csv"
|
||||
|
||||
# Temporäre Datei für die Verarbeitung
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Verarbeitung:
|
||||
# 1. Zuerst alle echten Zeilenumbrüche (die nicht in Anführungszeichen sind) markieren
|
||||
# 2. Dann Newlines innerhalb von Anführungszeichen durch Leerzeichen ersetzen
|
||||
# 3. HTML-Tags entfernen
|
||||
# 4. Markierte Zeilenumbrüche wiederherstellen
|
||||
|
||||
awk '
|
||||
BEGIN { FPAT = "([^;]*)|(\"[^\"]+\")"; OFS=";"; in_quotes=0 }
|
||||
{
|
||||
# Zeilen zusammenfügen, wenn sie unvollständig sind (nur für Sicherheit)
|
||||
if (NR == 1) {
|
||||
full_line = $0
|
||||
} else {
|
||||
full_line = full_line " " $0
|
||||
}
|
||||
|
||||
# Überprüfen, ob die Zeile vollständig ist (gleich viele öffnende und schließende Anführungszeichen)
|
||||
quotes = gsub(/"/, "&", full_line)
|
||||
if (quotes % 2 == 0) {
|
||||
# Zeile ist vollständig, jetzt verarbeiten
|
||||
$0 = full_line
|
||||
|
||||
# Newlines in jedem Feld durch Leerzeichen ersetzen
|
||||
for (i=1; i<=NF; i++) {
|
||||
# HTML-Tags entfernen
|
||||
gsub(/<[^>]*>/, "", $i)
|
||||
|
||||
# Newlines und mehrfache Leerzeichen bereinigen
|
||||
gsub(/\n/, " ", $i)
|
||||
gsub(/ +/, " ", $i)
|
||||
|
||||
# Feld trimmen
|
||||
sub(/^[ \t]+/, "", $i)
|
||||
sub(/[ \t]+$/, "", $i)
|
||||
|
||||
# Feld wieder in Anführungszeichen setzen, wenn es Semikolons oder Anführungszeichen enthält
|
||||
if (($i ~ /;/ || $i ~ /"/) && $i !~ /^".*"$/) {
|
||||
gsub(/"/, "\"\"", $i) # Escape existing quotes
|
||||
$i = "\"" $i "\""
|
||||
}
|
||||
}
|
||||
|
||||
print
|
||||
full_line = ""
|
||||
}
|
||||
}' "$input_file" > "$temp_file"
|
||||
|
||||
# Endgültige Bereinigung
|
||||
mv "$temp_file" "$output_file"
|
||||
|
||||
echo "Bereinigte Datei wurde erstellt: $output_file"
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
id;customer.name;customer.address;customer.zip;customer.city;customer.phone;customer.email;customer.web;customer.country
|
||||
1;TechSolutions GmbH;Musterstraße 123;10115;Berlin;+49 30 12345678;info@techsolutions.de;www.techsolutions.de;DE
|
||||
2;Innovate AG;Hauptstraße 45;80335;München;+49 89 87654321;contact@innovate-ag.com;www.innovate-ag.com;AU
|
||||
3;DataSystems Ltd.;Industriestraße 78;20095;Hamburg;+49 40 5559876;office@datasystems.de;www.datasystems.de;JP
|
||||
4;WebCraft GmbH;Am Bahnhof 5;50667;Köln;+49 221 9876543;info@webcraft.de;www.webcraft.de;DE
|
||||
5;CloudExperts AG;TechPark 12;70173;Stuttgart;+49 711 123457;support@cloudexperts.de;www.cloudexperts.de;DE
|
||||
6;SoftwareHub GmbH;Friedrichstraße 33;60323;Frankfurt;+49 69 5551234;info@softwarehub.de;www.softwarehub.de;DE
|
||||
7;DigitalWorks Ltd.;Königsallee 1;40212;Düsseldorf;+49 211 8765432;contact@digitalworks.de;www.digitalworks.de;DE
|
||||
8;NetSolutions GmbH;Hansastraße 62;04109;Leipzig;+49 341 2345678;office@netsolutions.de;www.netsolutions.com;DE
|
||||
9;CodeMasters AG;Rathausplatz 8;86150;Augsburg;+49 821 9876543;info@codemasters.de;www.codemasters.de;DE
|
||||
10;FutureTech GmbH;Am Markt 3;38100;Braunschweig;+49 531 5559876;contact@futuretech.de;www.futuretech.de;DE
|
||||
11;SmartSystems Ltd.;Ludwigstraße 15;97070;Würzburg;+49 931 1234567;support@smartsystems.de;www.smartsystems.de;CN
|
||||
12;AppFactory GmbH;Poststraße 23;14467;Potsdam;+49 331 8765432;info@appfactory.de;www.appfactory.de;CN
|
||||
13;DataLabs AG;Goethestraße 98;99084;Erfurt;+49 361 9876543;office@datalabs.de;www.datalabs.de;CN
|
||||
14;WebInnovate GmbH;Schillerstraße 44;30159;Hannover;+49 511 5551234;contact@webinnovate.de;www.webinnovate.de;CN
|
||||
15;CloudSystems Ltd.;Bahnhofstraße 77;66111;Saarbrücken;+49 681 2345678;info@cloudsystems.de;www.cloudsystems.de;CN
|
||||
21;GlobalTech Solutions;124 Oxford Street;W1D 2HQ;London;+44 20 7123 4567;info@globaltech.co.uk;www.globaltech.co.uk;CN
|
||||
22;InnovateX Ltd;78 Canary Wharf;E14 5AB;London;+44 20 7987 6543;contact@innovatex.com;www.innovatex.com;CN
|
||||
23;DataDynamics Inc;446 Silicon Roundabout;EC2A 4NE;London;+44 20 7555 12345;office@datadynamics.com;www.datadynamics.com;FR
|
||||
24;CloudSphere GmbH;TechPark Berlin 15;10115;Berlin;+49 30 9876 15432;info@cloudsphere.de;www.cloudsphere.de;FR
|
||||
25;WebCraft International;200 Madison Ave;10016;New York;+1 212 555 7890;support@webcraft.com;www.webcraft.com;FR
|
||||
26;DigitalFrontiers Pte Ltd;1 Raffles Place;048616;Singapore;+65 6123 4567;info@digitalfrontiers.sg;www.digitalfrontiers.sg;FR
|
||||
27;TechNova SAS;55 Praspiekt Pieramozcau;75008;Misnk; 1 42 86 53 09;contact@technova.by;www.technova.by;BY
|
||||
28;AppFactory Ltd;88 Kingsway;WC2B 6AA;London;+44 20 7123 9876;office@appfactory.io;www.appfactory.io;FR
|
||||
29;GlobalData Systems;Level 25 One Canada Square;E14 5AB;London;+44 20 7987 1234;info@globaldata.com;www.globaldata.com;FR
|
||||
210;SmartSolutions AG;Bahnhofstrasse 45;8001;Zurich;+41 44 234 56 78;contact@smartsolutions.ch;www.smartsolutions.ch;FR
|
||||
211;InnovationHub Ltd;22 Shoreditch High Street;E1 6PE;London;+44 20 7555 8765;support@innovationhub.co.uk;www.innovationhub.co.uk;UK
|
||||
212;CyberSecure Inc;500 5th Avenue;10110;New York;+1 212 867 5309;security@cybersecure.com;www.cybersecure.com;FR
|
||||
213;TechBridge Tokyo;Shinjuku Center Building 1-25-1;163-0650;Tokyo;+81 3 5321 7890;info@techbridge.jp;www.techbridge.jp;JP
|
||||
214;LondonDigital Agency;15 Covent Garden;WC2E 8BE;London;+44 20 7123 5555;hello@londondigital.com;www.londondigital.com;FR
|
||||
215;GlobalInnovate Group;Tower 42; 25 Old Broad Street;EC2N 1HQ;London;+44 20 7987 9999;info@globalinnovate.com;www.globalinnovate.com;FR
|
||||
216;DataCraft Sydney;1 Macquarie Place;2000;Sydney;+61 2 9123 4567;au@datacraft.com;www.datacraft.com;FR
|
||||
217;EuroTech Solutions;Amsterdam Towers;1011 PN;Amsterdam;+31 20 765 4321;info@eurotech.nl;www.eurotech.nl;NL
|
||||
218;LondonFinTech Labs;Level 39; One Canada Square;E14 5AB;London;+44 20 7555 4321;finance@londonfintech.com;www.londonfintech.com;UK
|
||||
219;CloudMasters Inc;221 Main Street;94105;San Francisco;+1 415 555 1234;support@cloudmasters.com;www.cloudmasters.com;FR
|
||||
220;TechVenture Capital;8 St. James's Square;SW1Y 4JU;London;+44 20 7123 7777;invest@techventure.com;www.techventure.com;FR
|
||||
|
Can't render this file because it has a wrong number of fields in line 31.
|
|
|
@ -1,90 +0,0 @@
|
|||
ID;Name;Description;stock;price;category;subcategory;Lieferzeit;EAN
|
||||
DEV001;Arduino Uno R3a;The Arduino Uno R3 is a foundational microcontroller board based on the ATmega328P. It features 14 digital I/O pins, 6 analog inputs, a 16 MHz quartz crystal, USB connectivity, and a power jack. Operating voltage is 5V. It is the ideal platform for beginners in electronics and coding, widely used for prototyping, DIY projects, automation, robotics, and educational purposes. It can be programmed using the Arduino IDE.;45;22.99;Microcontroller & Development Boards;Arduino Boards;2-3 Tage;7630049200016
|
||||
DEV002;Raspberry Pi 4 Model B 4GB;The new high-performance single-board computer featuring a Broadcom BCM2711, quad-core Cortex-A72 (ARM v8) 64-bit SoC running at 1.5GHz and 4GB of LPDDR4-3200 SDRAM. Connectivity includes dual-band 2.4/5.0 GHz Wi-Fi, Bluetooth 5.0, Gigabit Ethernet, two USB 3.0 ports, and two micro-HDMI ports supporting dual 4K displays. Its primary use is as a low-cost desktop computer, network-attached storage (NAS) device, media center, or embedded system for industrial applications.;28;75.50;Microcontroller & Development Boards;Raspberry Pi Boards;5-7 Tage;1931000001047
|
||||
DEV003;ESP32-WROOM-312 Development Board;A powerful Wi-Fi and Bluetooth-enabled microcontroller board with dual-core Xtensa LX6 processor. Features 4MB flash memory, 520KB SRAM, 34 GPIO pins, and supports various communication protocols like I2C, I2S, SPI, and UART. Ideal for IoT projects, smart home devices, and wireless applications requiring robust connectivity and processing power.;67;12.95;Microcontroller & Development Boards;ESP32/8266 Boards;3-5 Tage;8717478034021
|
||||
DEV004;STM32F407VET6 Development Board;High-performance ARM Cortex-M4 based board with DSP and FPU instructions. Features 512KB flash, 192KB RAM, USB OTG, Ethernet, and multiple timers. Operating frequency up to 168MHz. Suitable for industrial control, motor control, audio processing, and advanced embedded applications requiring high computational power.;23;35.80;Microcontroller & Development Boards;Other Microcontrollers;7-10 Tage;6940541880018
|
||||
DEV005;Arduino Motor Shield Rev3;Add-on shield designed to drive inductive loads such as relays, solenoids, DC and stepper motors. Features two channels that support 2A continuous current, screw terminals for easy connection, and built-in protection diodes. Perfect for robotics projects and automation systems when used with Arduino boards.;89;24.50;Microcontroller & Development Boards;Accessories;1-2 Tage;7630049200023
|
||||
DEV006;Raspberry Pi 4 Official Case;Official protective case for Raspberry Pi 4 Model B with integrated GPIO access and dedicated slots for camera and display cables. Features a modular design with three plates for easy access to ports and components. Made from high-quality white plastic with colored accents.;156;8.99;Microcontroller & Development Boards;Accessories;1-2 Tage;1931000001054
|
||||
DEV007;DHT22 AM2302 Digital Sensor;A pre-calibrated digital temperature and humidity sensor module. It provides a digital signal output and features a dedicated NTC for temperature measurement and a resistive humidity sensing element. Operating voltage: 3.3V - 6V. Measurement range: Humidity 0-100% RH, Temperature -40 to 80°C. Accuracy: ±2% RH and ±0.5°C. Typical applications include HVAC systems, weather stations, environmental monitoring, home automation, and data logging projects. It is easy to interface with Arduino, Raspberry Pi, and other microcontrollers.;120;9.95;Sensors & Modules;Temperature & Humidity Sensors;1-2 Tage;8591854063228
|
||||
DEV008;HC-SR05 Ultrasonic Sensor;Ultrasonic distance measurement module with 2cm to 400cm non-contact range. Operating voltage: 5V DC. Provides excellent ranging accuracy with stable readings. Uses sonar principles to determine distance to objects. Ideal for obstacle avoidance robots, parking assistance systems, and liquid level measurement.;204;3.50;Sensors & Modules;Motion & Proximity Sensors;1-2 Tage;6943185501012
|
||||
DEV009;PIR Motion Sensor HC-SR501;Passive infrared motion detection sensor with adjustable sensitivity and delay time. Detection range up to 7 meters with 120-degree detection angle. Operating voltage: 4.5-20V DC. Features low power consumption and reliable performance. Perfect for security systems, automatic lighting control, and energy-saving applications.;178;4.25;Sensors & Modules;Motion & Proximity Sensors;1-2 Tage;6943185501029
|
||||
DEV010;BH1750 Digital Light Sensor;Digital ambient light sensor with I2C interface and 16-bit resolution. Measurement range: 1-65535 lux. Features low power consumption and high precision. No need for external components. Ideal for display backlight control in mobile devices, automatic brightness adjustment systems, and environmental light monitoring.;95;6.80;Sensors & Modules;Light, Color & Gesture Sensors;2-3 Tage;8591854063235
|
||||
DEV011;APDS-9960 Gesture Sensor;Advanced gesture detection, proximity sensing, and ambient light sensor in one module. Features I2C interface with interrupt output. Can detect simple gestures (up, down, left, right) and measure proximity up to 20cm. Perfect for touchless interfaces, interactive displays, and smart home control.;63;15.75;Sensors & Modules;Light, Color & Gesture Sensors;3-5 Tage;8717478034038
|
||||
DEV012;MQ-2 Gas Sensor Module;Semiconductor gas sensor for detecting LPG, propane, hydrogen, methane, alcohol, and smoke. Analog and digital output with adjustable sensitivity. Heating voltage: 5V±0.2V. Fast response and recovery time. Suitable for gas leak detection in home and industry, air quality monitoring, and safety systems.;112;8.45;Sensors & Modules;Gas, Air Quality & Pressure Sensors;2-3 Tage;6943185501036
|
||||
DEV013;BMP2810 Barometric Pressure Sensor;High-precision digital barometric pressure and temperature sensor with I2C and SPI interfaces. Pressure range: 300-1100 hPa with ±1 hPa absolute accuracy. Temperature measurement with ±1.0°C accuracy. Low power consumption. Ideal for weather stations, altitude tracking, and indoor navigation.;87;9.20;Sensors & Modules;Gas, Air Quality & Pressure Sensors;2-3 Tage;8591854063242
|
||||
DEV014;NEO-6M GPS Module;GPS receiver module with built-in EEPROM and ceramic antenna. Provides accurate positioning with 2.5m accuracy. Supports up to 5Hz update rate with NMEA protocol. Operating voltage: 3.3-5V. Features low power consumption and hot start capability. Perfect for navigation systems, tracking devices, and drones.;134;18.90;Sensors & Modules;GPS & Location Modules;3-5 Tage;8717478034045
|
||||
DEV015;RC522 RFID Reader Module;RFID reader/writer operating at 13.56MHz with SPI interface. Reading distance up to 5cm. Supports ISO 14443A standard tags. Operating voltage: 2.5-3.3V. Ideal for access control systems, attendance tracking, payment systems, and interactive applications.;198;7.85;Sensors & Modules;RFID & NFC Modules;1-2 Tage;6943185501043
|
||||
DEV016;37-in-1 Sensor Module Kit;Comprehensive sensor kit containing 37 most popular modules including temperature, humidity, motion, light, sound, and gas sensors. Comes with tutorial CD and connection diagrams. Perfect for beginners learning electronics and IoT programming. All modules are compatible with Arduino and Raspberry Pi.;45;89.99;Sensors & Modules;Sensor Kits;5-7 Tage;7630049200030
|
||||
DEV017;SG90 Micro Servo Motor;TowerPro SG90 mini servo motor with 180-degree rotation range. Operating voltage: 4.8V. Stall torque: 1.8kg/cm. Comes with plastic gears and three-wire interface (power, ground, signal). Ideal for robotics, RC models, camera positioning, and small automation projects.;312;4.75;Actuators & Output;Motors;1-2 Tage;6940541880025
|
||||
DEV018;28BYJ-48 Stepper Motor with Driver;Unipolar stepper motor with ULN2003 driver board. Step angle: 5.625° x 1/64 reduction ratio. Operating voltage: 5-12V DC. Provides precise position control without feedback. Perfect for 3D printers, CNC machines, automated curtains, and precision positioning systems.;167;12.50;Actuators & Output;Motors;2-3 Tage;8591854063259
|
||||
DEV019;L298N Motor Driver Module;Dual H-bridge motor driver capable of driving two DC motors or one stepper motor. Operating voltage: 5-35V. Maximum current: 2A per channel. Features logic level conversion and heat sink. Ideal for robotics projects, motor control applications, and high-power driving needs.;98;8.95;Actuators & Output;Motor Drivers & Controllers;2-3 Tage;8717478034052
|
||||
DEV020;5V Relay Module;Single channel relay module with optocoupler isolation. Operating voltage: 5V. Switching capacity: 10A 250V AC or 30V DC. Features status LED and standard interface for easy connection to microcontrollers. Perfect for controlling high-voltage appliances with low-voltage circuits.;245;3.25;Actuators & Output;Relays & Switches;1-2 Tage;6943185501050
|
||||
DEV021;16x2 LCD Display with I2C;Blue backlight LCD display with 16 characters x 2 lines and I2C interface module. Operating voltage: 5V. Contrast adjustable. The I2C interface reduces required GPIO pins from 6 to 2. Ideal for displaying system status, sensor readings, and user interface information.;143;14.99;Actuators & Output;Displays;2-3 Tage;7630049200047
|
||||
DEV022;0.96 inch OLED Display;128x64 pixel OLED display with SSD1306 driver and I2C/SPI interface. Features high contrast, wide viewing angle, and low power consumption. Operating voltage: 3.3-5V. Perfect for projects requiring compact, high-quality graphics display.;189;10.45;Actuators & Output;Displays;2-3 Tage;1931000001061
|
||||
DEV023;5mm RGB LED Common Cathode;Diffused RGB LED with common cathode configuration. Operating voltage: 2.0-2.5V (Red), 3.0-3.4V (Green/Blue). Maximum current: 20mA per color. Provides full color spectrum mixing. Ideal for status indicators, mood lighting, and visual feedback in projects.;500;0.75;Actuators & Output;LEDs & Lighting;1-2 Tage;8591854063266
|
||||
DEV024;Active Buzzer Module;5V active buzzer with built-in oscillator that produces continuous sound when powered. Operating voltage: 3.3-5V. Sound output: approximately 85dB. Easy to drive with microcontroller digital pin. Perfect for alarm systems, timers, and user notification applications.;287;2.10;Actuators & Output;Buzzers & Speakers;1-2 Tage;6943185501067
|
||||
DEV025;1K Ohm Resistor Pack;Assortment of 100 pieces 1K ohm 1/4W metal film resistors with 1% tolerance. Temperature coefficient: 50ppm/°C. Perfect for pull-up/pull-down resistors, voltage dividers, and current limiting in various electronic circuits.;15;4.99;Components & Parts;Resistors, Capacitors, Potentiometers;1-2 Tage;8717478034069
|
||||
DEV026;100uF Electrolytic Capacitor;Radial lead electrolytic capacitor with 25V voltage rating. Operating temperature: -40°C to +85°C. Low ESR and high ripple current capability. Ideal for power supply filtering, audio circuits, and general decoupling applications.;420;0.25;Components & Parts;Resistors, Capacitors, Potentiometers;1-2 Tage;6940541880032
|
||||
DEV027;10K Ohm Linear Potentiometer;Rotary potentiometer with 10K ohm resistance and linear taper. Shaft length: 15mm. Power rating: 0.5W. Features smooth rotation and reliable performance. Perfect for volume control, brightness adjustment, and parameter tuning.;195;1.20;Components & Parts;Resistors, Capacitors, Potentiometers;1-2 Tage;8591854063273
|
||||
DEV028;2N2222A NPN Transistor;General purpose NPN bipolar junction transistor in TO-92 package. Collector current: 800mA max. Collector-emitter voltage: 40V max. Gain bandwidth: 250MHz. Ideal for switching and amplification applications in various electronic circuits.;876;0.35;Components & Parts;Transistors & MOSFETs;1-2 Tage;7630049200054
|
||||
DEV029;IRFZ44N N-Channel MOSFET;Power MOSFET with low on-resistance and fast switching speed. Drain-source voltage: 55V. Continuous drain current: 49A. TO-220 package. Perfect for motor control, power switching, and high-current applications.;321;2.15;Components & Parts;Transistors & MOSFETs;1-2 Tage;1931000001078
|
||||
DEV030;1N4007 Rectifier Diode;General purpose rectifier diode with 1000V maximum repetitive reverse voltage and 1A average forward current. DO-41 package. Ideal for power supply rectification, reverse polarity protection, and general purpose switching.;650;0.15;Components & Parts;Diodes & LEDs;1-2 Tage;8717478034076
|
||||
DEV031;5mm Green LED;Diffused green LED with 20mA forward current and 2.1V forward voltage. Viewing angle: 30 degrees. Luminous intensity: 5000-8000 mcd. Perfect for status indicators, panel lights, and visual feedback in electronic projects.;1200;0.20;Components & Parts;Diodes & LEDs;1-2 Tage;6943185501074
|
||||
DEV032;6x6mm Tactile Switch;Momentary push button switch with through-hole mounting. Operating force: 160±50gf. Contact resistance: <50mΩ. Life expectancy: 100,000 cycles. Ideal for user input, reset buttons, and control interfaces.;890;0.10;Components & Parts;Buttons & Switches;1-2 Tage;8591854063280
|
||||
DEV033;Toggle Switch SPDT;Single pole double throw toggle switch with on-on configuration. Rating: 6A 125V AC / 3A 250V AC. Panel mount design with nut and washer. Perfect for power switching, mode selection, and circuit configuration.;134;2.95;Components & Parts;Buttons & Switches;2-3 Tage;6940541880049
|
||||
DEV034;Jumper Wires Male-to-Male;Bundle of 120 pieces 20cm male-to-male jumper wires in multiple colors. 0.1 pitch. Made with high-quality Dupont connectors. Perfect for breadboard connections, prototyping, and wiring Arduino projects.;45;6.99;Components & Parts;Wires, Cables & Connectors;1-2 Tage;7630049200061
|
||||
DEV035;USB Type B Cable;1.5 meter USB 2.0 Type A to Type B cable with gold-plated connectors. Data transfer speed up to 480Mbps. 28AWG power conductors. Perfect for connecting Arduino boards, printers, and other devices with Type B接口.;178;7.50;Components & Parts;Wires, Cables & Connectors;1-2 Tage;1931000001085
|
||||
DEV036;400-Point Solderless Breadboard;High-quality solderless breadboard with 400 tie points. Features two power rails and 63 rows of interconnected terminals. Adhesive backing for secure mounting. Maximum voltage: 300V. Ideal for circuit prototyping and testing.;67;8.25;Components & Parts;Breadboards & Prototyping;1-2 Tage;8717478034083
|
||||
DEV037;Breadboard Jumper Wire Kit;Kit containing 140 pieces of pre-cut and stripped jumper wires in various lengths and colors. Includes male-to-male, male-to-female, and female-to-female types. Organized in convenient storage box. Perfect for breadboard prototyping.;92;12.99;Components & Parts;Breadboards & Prototyping;1-2 Tage;6943185501081
|
||||
DEV038;12V 2A Power Supply;Switching power adapter with 12V DC output and 2A maximum current. Input: 100-240V AC. Comes with 5.5mm x 2.1mm barrel jack connector. Short circuit and overvoltage protection. Ideal for powering Arduino projects, LED strips, and various electronics.;58;14.95;Power & Battery;Power Supplies;3-5 Tage;8591854063297
|
||||
DEV039;5V 3A USB Power Supply;High-current USB power supply with 5V 3A output. Features built-in USB Type-A port and overcurrent protection. Input: 100-240V AC. Perfect for powering Raspberry Pi, high-power USB devices, and charging applications.;47;11.50;Power & Battery;Power Supplies;2-3 Tage;6940541880056
|
||||
DEV040;4xAA Battery Holder;Plastic battery holder for 4 AA batteries with series connection providing 6V output. Features wire leads with stripped ends and on/off switch. Secure battery closure. Perfect for portable projects and backup power.;124;3.75;Power & Battery;Battery Holders;1-2 Tage;7630049200078
|
||||
DEV041;TP4056 Lithium Charger Module;Single cell lithium battery charging module with 1A maximum charge current. Features charging status indicators and protection circuits. Input: 5V USB. Supports 3.7V Li-ion and LiPo batteries. Perfect for portable projects.;216;4.25;Power & Battery;Charging Circuits;2-3 Tage;1931000001092
|
||||
DEV042;LM2596 DC-DC Buck Converter;Adjustable step-down voltage regulator module with 3A maximum output current. Input voltage: 4.5-40V. Output voltage: 1.5-35V adjustable. Efficiency up to 92%. Features overheat and short circuit protection.;189;5.95;Power & Battery;Voltage Regulators & Converters;2-3 Tage;8717478034090
|
||||
DEV043;60W Soldering Station;Temperature controlled soldering station with 60W power and adjustable temperature range 200-480°C. Features ceramic heating element, sleep mode, and digital display. Comes with soldering iron stand and sponge. Perfect for electronics repair and prototyping.;34;49.99;Tools & Equipment;Soldering Equipment;5-7 Tage;6943185501098
|
||||
DEV044;Digital Multimeter DT9205A;3-1/2 digit digital multimeter with LCD display. Measures AC/DC voltage, current, resistance, capacitance, frequency, and temperature. Features diode test, continuity buzzer, and data hold. Comes with test leads and carrying case.;29;38.50;Tools & Equipment;Multimeters & Test Equipment;3-5 Tage;8591854063303
|
||||
DEV045;65-Piece Screwdriver Set;Precision screwdriver set with 65 pieces including various Phillips, flat, Torx, and hex bits. Magnetic tips and comfortable handle. Organized in durable carrying case. Perfect for electronics repair, smartphone disassembly, and精密 work.;56;24.95;Tools & Equipment;Tool Kits;2-3 Tage;6940541880063
|
||||
DEV046;Plastic Project Enclosure 160x100x60mm;Plastic electronic project box with dimensions 160x100x60mm. Features mounting posts for PCBs, ventilation slots, and removable lid. Material: ABS plastic. Perfect for housing electronic projects and prototypes.;78;9.75;Tools & Equipment;Enclosures & Boxes;3-5 Tage;7630049200085
|
||||
DEV047;Arduino Nano Every;Compact board based on the ATMega4809 with 20MHz operating frequency. Features 48KB flash, 6KB SRAM, and 22 GPIO pins. Compatible with Arduino Nano footprint. Perfect for space-constrained projects requiring Arduino compatibility.;91;18.50;Microcontroller & Development Boards;Arduino Boards;3-5 Tage;7630049200092
|
||||
DEV048;Raspberry Pi Pico W;Microcontroller board with RP2040 chip and wireless connectivity. Features 264KB SRAM, 2MB flash, and 30 GPIO pins. Supports MicroPython and C/C++. Built-in Wi-Fi and Bluetooth. Ideal for IoT projects and wireless applications.;167;9.95;Microcontroller & Development Boards;Raspberry Pi Boards;2-3 Tage;1931000001108
|
||||
DEV049;ESP32-CAM Development Board;ESP32 module with OV2640 camera and microSD card slot. Features 4MB flash, 520KB SRAM, and supports Wi-Fi and Bluetooth. Provides video streaming and image capture capabilities. Perfect for security cameras and IoT vision applications.;124;15.75;Microcontroller & Development Boards;ESP32/8266 Boards;3-5 Tage;8717478034106
|
||||
DEV050;ATtiny85 Development Board;Compact development board based on ATtiny85 microcontroller. Features 8KB flash, 512B SRAM, and 6 GPIO pins. Operating voltage: 5V. Perfect for simple projects requiring minimal I/O and small form factor.;205;6.25;Microcontroller & Development Boards;Other Microcontrollers;2-3 Tage;6943185501104
|
||||
DEV051;Arduino Ethernet Shield;Network connectivity shield for Arduino with W5500 Ethernet controller. Supports TCP/IP protocols and provides SD card slot. Operating voltage: 5V. Perfect for network-connected projects and data logging.;76;32.99;Microcontroller & Development Boards;Accessories;4-6 Tage;8591854063310
|
||||
DEV052;Raspberry Pi Official Power Supply;Official 15.3W USB-C power supply for Raspberry Pi 4. Output: 5.1V DC, 3A. Features noise filtering and overcurrent protection. Includes 1.5m USB-C cable. Ensures stable power for Raspberry Pi operation.;142;11.99;Microcontroller & Development Boards;Accessories;2-3 Tage;6940541880070
|
||||
DEV053;DS18B20 Waterproof Temperature Sensor;Digital temperature sensor with 1-wire interface and waterproof stainless steel probe. Measurement range: -55°C to +125°C with ±0.5°C accuracy. 1-meter cable length. Perfect for liquid temperature measurement, environmental monitoring, and industrial applications.;188;8.95;Sensors & Modules;Temperature & Humidity Sensors;2-3 Tage;7630049200108
|
||||
DEV054;HC-SR501 PIR Motion Sensor;Passive infrared motion detector with adjustable time and sensitivity. Detection range: 7 meters with 120° angle. Operating voltage: 4.5-20V DC. Features low power consumption. Ideal for security systems and automatic lighting.;156;4.50;Sensors & Modules;Motion & Proximity Sensors;1-2 Tage;1931000001115
|
||||
DEV055;VL53L0X Laser Distance Sensor;Time-of-flight laser ranging sensor with 2m measurement range and 1mm resolution. I2C interface. Operating voltage: 2.6-3.5V. Features high accuracy and immune to ambient light. Perfect for gesture recognition and proximity sensing.;97;14.25;Sensors & Modules;Motion & Proximity Sensors;3-5 Tage;8717478034113
|
||||
DEV056;TCS34725 Color Sensor;RGB color light sensor with IR filter and white LED. I2C interface with interrupt output. Provides clear, red, green, blue, and lux measurements. Perfect for color sorting, ambient light sensing, and display calibration.;84;13.75;Sensors & Modules;Light, Color & Gesture Sensors;2-3 Tage;6943185501111
|
||||
DEV057;VCNL4040 Proximity Sensor;Integrated proximity and ambient light sensor with I2C interface. Proximity range: 0-200mm. Features interrupt function and low power consumption. Perfect for touchless interfaces and presence detection.;119;9.80;Sensors & Modules;Light, Color & Gesture Sensors;2-3 Tage;8591854063327
|
||||
DEV058;MQ-135 Air Quality Sensor;Semiconductor sensor for detecting harmful gases like NH3, NOx, alcohol, benzene, and CO2. Analog output with adjustable sensitivity. Heating voltage: 5V±0.1V. Suitable for air quality monitoring and environmental detection.;145;7.25;Sensors & Modules;Gas, Air Quality & Pressure Sensors;2-3 Tage;6940541880087
|
||||
DEV059;BME280 Environmental Sensor;Integrated environmental sensor measuring temperature, humidity, and barometric pressure. I2C/SPI interfaces. Operating voltage: 1.8-3.6V. Low power consumption. Ideal for weather stations and environmental monitoring.;132;14.50;Sensors & Modules;Gas, Air Quality & Pressure Sensors;3-5 Tage;7630049200115
|
||||
DEV060;U-blox NEO-M8N GPS Module;High-performance GPS module with 72 channels and 2.5m accuracy. Supports GPS, GLONASS, and BeiDou systems. Update rate: up to 10Hz. Perfect for drones, navigation systems, and precision tracking.;89;26.95;Sensors & Modules;GPS & Location Modules;4-6 Tage;1931000001122
|
||||
DEV061;PN532 NFC RFID Module;NFC/RFID reader/writer supporting ISO 14443A/B, ISO 18092, and FeliCa protocols. Operating frequency: 13.56MHz. Interfaces: I2C, SPI, HSU. Reading distance: up to 5cm. Ideal for contactless payment and access control.;107;18.75;Sensors & Modules;RFID & NFC Modules;3-5 Tage;8717478034120
|
||||
DEV062;Arduino Sensor Kit;Complete sensor kit containing 37 modules compatible with Arduino. Includes tutorials and code examples. Covers basic to advanced sensors. Perfect for educational purposes and learning electronics.;68;79.99;Sensors & Modules;Sensor Kits;5-7 Tage;6943185501128
|
||||
DEV063;NEMA 17 Stepper Motor;Bipolar stepper motor with 1.8° step angle and 42mm frame size. Holding torque: 40Ncm. Current: 1.2A per phase. 4-wire connection. Perfect for 3D printers, CNC machines, and precision positioning systems.;45;28.95;Actuators & Output;Motors;4-6 Tage;8591854063334
|
||||
DEV064;L293D Motor Driver IC;Quadruple half-H driver for bidirectional DC motor control. Operating voltage: 4.5-36V. Output current: 600mA per channel. DIP-16 package. Perfect for controlling small motors and solenoids.;213;3.45;Actuators & Output;Motor Drivers & Controllers;1-2 Tage;6940541880094
|
||||
DEV065;5V 4-Channel Relay Module;4-channel relay module with optocoupler isolation and status LEDs. Operating voltage: 5V. Switching capacity: 10A 250V AC per channel. Features screw terminals and standard control interface.;124;15.50;Actuators & Output;Relays & Switches;2-3 Tage;7630049200122
|
||||
DEV066;20x4 LCD Display with I2C;Large LCD display with 20 characters x 4 lines and I2C interface. Blue backlight with adjustable contrast. Operating voltage: 5V. Perfect for projects requiring extensive text display.;87;19.95;Actuators & Output;Displays;3-5 Tage;1931000001139
|
||||
DEV067;1.3 inch IPS LCD Display;1.3 inch IPS display with 240x240 resolution and ST7789 driver. SPI interface with 65K colors. Operating voltage: 3.3V. Features high brightness and wide viewing angle. Perfect for graphics and GUI applications.;134;16.75;Actuators & Output;Displays;3-5 Tage;8717478034137
|
||||
DEV068;WS2812B RGB LED Strip;Addressable RGB LED strip with 30 LEDs per meter. Each LED individually controllable via single-wire protocol. Operating voltage: 5V. Perfect for decorative lighting, art installations, and visual effects.;78;18.50;Actuators & Output;LEDs & Lighting;2-3 Tage;6943185501135
|
||||
DEV069;Piezo Buzzer Element;Passive piezo buzzer without internal oscillator. Requires external driver circuit. Operating voltage: 3-20V. Resonant frequency: 4kHz. Compact size. Ideal for custom tone generation and audio projects.;345;1.25;Actuators & Output;Buzzers & Speakers;1-2 Tage;8591854063341
|
||||
DEV070;Assorted Resistor Kit;Comprehensive resistor kit with 1000 pieces covering values from 10 ohm to 1M ohm. 1/4W metal film with 1% tolerance. Organized in storage box with value labels. Perfect for electronics projects and repairs.;28;29.99;Components & Parts;Resistors, Capacitors, Potentiometers;2-3 Tage;6940541880100
|
||||
DEV071;100nF Ceramic Capacitor;Multilayer ceramic capacitor with 100nF capacitance and 50V rating. X7R dielectric material. Through-hole design. Ideal for decoupling, filtering, and timing applications.;1200;0.15;Components & Parts;Resistors, Capacitors, Potentiometers;1-2 Tage;7630049200139
|
||||
DEV072;200K Logarithmic Potentiometer;Audio taper potentiometer with 100K ohm resistance. Shaft length: 20mm. Power rating: 0.5W. Smooth rotation with logarithmic response. Perfect for volume controls and audio applications.;167;2.25;Components & Parts;Resistors, Capacitors, Potentiometers;1-2 Tage;1931000001146
|
||||
DEV073;BC547 NPN Transistor;General purpose NPN transistor in TO-92 package. Collector current: 100mA max. Collector-emitter voltage: 45V. DC current gain: 110-800. Ideal for amplification and switching applications.;954;0.25;Components & Parts;Transistors & MOSFETs;1-2 Tage;8717478034144
|
||||
DEV074;IRF540N N-Channel MOSFET;Power MOSFET with 100V drain-source voltage and 33A continuous drain current. Low on-resistance: 44mΩ. TO-220 package. Perfect for high-power switching and motor control applications.;189;3.75;Components & Parts;Transistors & MOSFETs;1-2 Tage;6943185501142
|
||||
DEV075;1N4148 Switching Diode;Fast switching diode with 100V reverse voltage and 200mA forward current. Switching speed: 4ns. DO-35 package. Ideal for high-speed switching, protection circuits, and signal processing.;875;0.12;Components & Parts;Diodes & LEDs;1-2 Tage;8591854063358
|
||||
DEV076;5mm Red LED;Standard red LED with 20mA forward current and 2.0V forward voltage. Viewing angle: 30 degrees. Luminous intensity: 2000-4000 mcd. Perfect for indicators and visual feedback.;1500;0.18;Components & Parts;Diodes & LEDs;1-2 Tage;6940541880117
|
||||
DEV077;12mm Push Button Switch;Momentary push button switch with LED illumination. Operating voltage: 12V DC. Contact rating: 3A 125V AC. Panel mount design. Available in multiple colors. Perfect for control panels and user interfaces.;234;2.95;Components & Parts;Buttons & Switches;2-3 Tage;7630049200146
|
||||
DEV078;DIP Switch 8 Position;8-position dual in-line package switch with through-hole mounting. Rating: 50mA 24V DC. Compact size. Ideal for configuration settings and mode selection in electronic circuits.;187;1.85;Components & Parts;Buttons & Switches;1-2 Tage;1931000001153
|
||||
DEV079;Jumper Wires Female-to-Female;Bundle of 120 pieces 20cm female-to-female jumper wires in multiple colors. 0.1 pitch. High-quality Dupont connectors. Perfect for connecting modules and sensors to development boards.;67;6.99;Components & Parts;Wires, Cables & Connectors;1-2 Tage;8717478034151
|
||||
DEV080;Micro USB Cable;1-meter Micro USB to USB Type-A cable with gold-plated connectors. Data transfer and charging capable. 28AWG power conductors. Perfect for connecting various electronic devices and charging.;245;5.50;Components & Parts;Wires, Cables & Connectors;1-2 Tage;6943185501159
|
||||
DEV081;830-Point Breadboard;Large solderless breadboard with 830 tie points. Features four power rails and 63 rows of terminals. Adhesive backing. Maximum voltage: 300V. Ideal for complex circuit prototyping.;54;12.95;Components & Parts;Breadboards & Prototyping;2-3 Tage;8591854063365
|
||||
DEV082;Breadboard Power Supply Module;3.3V/5V breadboard power supply module with USB input. Maximum output current: 700mA. Features LED indicators and on/off switch. Perfect for providing stable power to breadboard projects.;138;8.45;Components & Parts;Breadboards & Prototyping;2-3 Tage;6940541880124
|
||||
DEV083;9V 1A Power Supply;Wall adapter with 9V DC output and 1A maximum current. Input: 100-240V AC. 5.5mm x 2.1mm barrel jack. Short circuit protection. Ideal for powering effects pedals and various electronics.;89;9.99;Power & Battery;Power Supplies;2-3 Tage;7630049200153
|
||||
DEV084;USB-C Power Delivery Module;USB-C power delivery module with adjustable voltage output (5V, 9V, 12V, 15V, 20V). Maximum power: 100W. Features digital display and multiple protection circuits. Perfect for modern power requirements.;76;22.50;Power & Battery;Power Supplies;3-5 Tage;1931000001160
|
||||
DEV085;18650 Battery Holder;Dual 18650 battery holder with series/parallel switch. Provides 3.7V (parallel) or 7.4V (series) output. Features built-in protection circuit and power switch. Perfect for lithium battery projects.;112;6.95;Power & Battery;Battery Holders;2-3 Tage;8717478034168
|
||||
DEV086;TP5100 2A Lithium Charger;Dual lithium battery charger module with 2A maximum charge current. Supports 3.7V Li-ion and LiPo batteries. Input: 5-12V. Features charging status indicators. Perfect for high-capacity battery charging.;98;7.25;Power & Battery;Charging Circuits;2-3 Tage;6943185501166
|
||||
DEV087;LM317 Adjustable Voltage Regulator;Adjustable linear voltage regulator with 1.5A output current. Output voltage: 1.25-37V. Features overcurrent and thermal protection. TO-220 package. Perfect for custom power supply designs.;167;2.95;Power & Battery;Voltage Regulators & Converters;1-2 Tage;8591854063372
|
||||
DEV088;Temperature Controlled Soldering Iron;60W temperature controlled soldering iron with adjustable temperature 200-450°C. Features ceramic heater and quick heat-up time. Includes stand and spare tips. Perfect for basic soldering tasks.;45;35.99;Tools & Equipment;Soldering Equipment;3-5 Tage;6940541880131
|
||||
DEV089;Auto-Ranging Multimeter;True RMS auto-ranging digital multimeter with 6000 counts. Measures AC/DC voltage, current, resistance, capacitance, frequency, and temperature. Features backlit display and data hold.;38;59.95;Tools & Equipment;Multimeters & Test Equipment;4-6 Tage;7630049200160
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>dynamixs-ai</artifactId>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>dynamixs-ai-a2a</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Dynamixs AI A2A Library</name>
|
||||
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<!-- use JDK settings for compiling -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.source}</source>
|
||||
<target>${java.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Testing JUnit 5 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
|
||||
|
||||
<!-- issue #572
|
||||
hack for:
|
||||
https://stackoverflow.com/questions/75116023/unable-to-make-protected-final-java-lang-class-java-lang-classloader-defineclass
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<argLine>
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||
</argLine>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Jakarta EE -->
|
||||
<dependency>
|
||||
<groupId>jakarta.platform</groupId>
|
||||
<artifactId>jakarta.jakartaee-api</artifactId>
|
||||
<version>${jakarta.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Microprofile -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.microprofile</groupId>
|
||||
<artifactId>microprofile</artifactId>
|
||||
<version>${microprofile.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs Workflow -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-core</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-engine</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-jax-rs</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-faces</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Testing -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.parsson</groupId>
|
||||
<artifactId>jakarta.json</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,448 +0,0 @@
|
|||
package ai.dynamixs.a2a;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonArray;
|
||||
import jakarta.json.JsonArrayBuilder;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonObjectBuilder;
|
||||
import jakarta.json.JsonString;
|
||||
import jakarta.json.JsonValue;
|
||||
|
||||
/**
|
||||
* Represents an A2A Skill Card based on Imixs-Workflow BPMN models.
|
||||
*
|
||||
* The skill ID follows the pattern: {modelVersion}_{taskId}_{eventId} This
|
||||
* allows direct mapping to Imixs workflow execution parameters.
|
||||
*
|
||||
* Example: "office-de-2.0_100_10" represents: - Model Version: "office-de-2.0"
|
||||
* - Task ID: 100 - Event ID: 10
|
||||
*/
|
||||
public class A2ASkillCard implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(A2ASkillCard.class.getSimpleName());
|
||||
|
||||
// A2A Standard Fields
|
||||
private String id; // {modelVersion}_{taskId}_{eventId}
|
||||
private String name; // Human-readable skill name
|
||||
private String description; // Detailed description
|
||||
private List<String> tags; // Categorization tags
|
||||
private List<String> examples; // Example usage scenarios
|
||||
private List<String> inputModes; // Supported input media types
|
||||
private List<String> outputModes; // Supported output media types
|
||||
private Map<String, Object> metadata; // Additional metadata
|
||||
|
||||
// Constructors
|
||||
public A2ASkillCard() {
|
||||
this.tags = new ArrayList<>();
|
||||
this.examples = new ArrayList<>();
|
||||
this.inputModes = new ArrayList<>();
|
||||
this.outputModes = new ArrayList<>();
|
||||
this.metadata = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Id is computed by version, task and event id "invoice-workflow-2.1_100_10"
|
||||
*
|
||||
* @param modelVersion
|
||||
* @param taskID
|
||||
* @param eventID
|
||||
*/
|
||||
public A2ASkillCard(String modelVersion, int taskID, int eventID) {
|
||||
this();
|
||||
this.id = createSkillId(modelVersion, taskID, eventID);
|
||||
|
||||
}
|
||||
|
||||
// Imixs-specific convenience methods for parsing skill ID
|
||||
|
||||
/**
|
||||
* Extracts the model version from the skill ID
|
||||
*
|
||||
* @return model version (e.g., "office-de-2.0")
|
||||
*/
|
||||
public String getModelVersion() {
|
||||
if (id == null || !id.contains("_")) {
|
||||
throw new IllegalStateException("Invalid skill ID format: " + id);
|
||||
}
|
||||
return id.substring(0, id.lastIndexOf('_', id.lastIndexOf('_') - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the task ID from the skill ID
|
||||
*
|
||||
* @return Imixs task ID as integer
|
||||
*/
|
||||
public int getTaskId() {
|
||||
if (id == null || !id.contains("_")) {
|
||||
throw new IllegalStateException("Invalid skill ID format: " + id);
|
||||
}
|
||||
String[] parts = id.split("_");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid skill ID format: " + id);
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(parts[parts.length - 2]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException("Invalid task ID in skill ID: " + id, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the event ID from the skill ID
|
||||
*
|
||||
* @return Imixs event ID as integer
|
||||
*/
|
||||
public int getEventId() {
|
||||
if (id == null || !id.contains("_")) {
|
||||
throw new IllegalStateException("Invalid skill ID format: " + id);
|
||||
}
|
||||
String[] parts = id.split("_");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid skill ID format: " + id);
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(parts[parts.length - 1]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException("Invalid event ID in skill ID: " + id, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a skill ID from Imixs workflow components
|
||||
*
|
||||
* @param modelVersion the workflow model version
|
||||
* @param taskId the task ID
|
||||
* @param eventId the event ID
|
||||
* @return formatted skill ID
|
||||
*/
|
||||
public static String createSkillId(String modelVersion, int taskId, int eventId) {
|
||||
if (modelVersion == null || modelVersion.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("Model version cannot be null or empty");
|
||||
}
|
||||
return String.format("%s_%d_%d", modelVersion, taskId, eventId);
|
||||
}
|
||||
|
||||
// JSON Serialization
|
||||
|
||||
/**
|
||||
* Converts this skill card to a Jakarta JSON object
|
||||
*
|
||||
* @return JsonObject representation of this skill card
|
||||
*/
|
||||
public JsonObject toJsonObject() {
|
||||
JsonObjectBuilder builder = Json.createObjectBuilder()
|
||||
.add("id", id != null ? id : "")
|
||||
.add("name", name != null ? name : "")
|
||||
.add("description", description != null ? description : "");
|
||||
|
||||
// Tags array
|
||||
JsonArrayBuilder tagsBuilder = Json.createArrayBuilder();
|
||||
if (tags != null) {
|
||||
tags.forEach(tagsBuilder::add);
|
||||
}
|
||||
builder.add("tags", tagsBuilder.build());
|
||||
|
||||
// Examples array
|
||||
JsonArrayBuilder examplesBuilder = Json.createArrayBuilder();
|
||||
if (examples != null) {
|
||||
examples.forEach(examplesBuilder::add);
|
||||
}
|
||||
builder.add("examples", examplesBuilder.build());
|
||||
|
||||
// Input modes array
|
||||
JsonArrayBuilder inputModesBuilder = Json.createArrayBuilder();
|
||||
if (inputModes != null) {
|
||||
inputModes.forEach(inputModesBuilder::add);
|
||||
}
|
||||
builder.add("inputModes", inputModesBuilder.build());
|
||||
|
||||
// Output modes array
|
||||
JsonArrayBuilder outputModesBuilder = Json.createArrayBuilder();
|
||||
if (outputModes != null) {
|
||||
outputModes.forEach(outputModesBuilder::add);
|
||||
}
|
||||
builder.add("outputModes", outputModesBuilder.build());
|
||||
|
||||
// Metadata object
|
||||
if (metadata != null && !metadata.isEmpty()) {
|
||||
JsonObjectBuilder metadataBuilder = Json.createObjectBuilder();
|
||||
metadata.forEach((key, value) -> {
|
||||
if (value instanceof String) {
|
||||
metadataBuilder.add(key, (String) value);
|
||||
} else if (value instanceof Number) {
|
||||
metadataBuilder.add(key, ((Number) value).doubleValue());
|
||||
} else if (value instanceof Boolean) {
|
||||
metadataBuilder.add(key, (Boolean) value);
|
||||
} else if (value != null) {
|
||||
metadataBuilder.add(key, value.toString());
|
||||
}
|
||||
});
|
||||
builder.add("metadata", metadataBuilder.build());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an A2ASkillCard from a JSON string
|
||||
*
|
||||
* @param jsonString JSON representation of a skill card
|
||||
* @return A2ASkillCard instance
|
||||
*/
|
||||
// public static A2ASkillCard fromJsonString(String jsonString) {
|
||||
// try (JsonReader reader = Json.createReader(new
|
||||
// java.io.StringReader(jsonString))) {
|
||||
// JsonObject jsonObject = reader.readObject();
|
||||
// return fromJsonObject(jsonObject);
|
||||
// } catch (Exception e) {
|
||||
// logger.severe("Failed to parse A2ASkillCard from JSON: " + e.getMessage());
|
||||
// throw new IllegalArgumentException("Invalid JSON format for A2ASkillCard",
|
||||
// e);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Creates an A2ASkillCard from a JsonObject
|
||||
*
|
||||
* @param jsonObject JsonObject representation
|
||||
* @return A2ASkillCard instance
|
||||
*/
|
||||
public static A2ASkillCard fromJsonObject(JsonObject jsonObject) {
|
||||
A2ASkillCard skill = new A2ASkillCard();
|
||||
|
||||
// Basic fields
|
||||
skill.setId(jsonObject.getString("id", ""));
|
||||
skill.setName(jsonObject.getString("name", ""));
|
||||
skill.setDescription(jsonObject.getString("description", ""));
|
||||
|
||||
// Arrays
|
||||
if (jsonObject.containsKey("tags")) {
|
||||
JsonArray tagsArray = jsonObject.getJsonArray("tags");
|
||||
skill.setTags(jsonArrayToStringList(tagsArray));
|
||||
}
|
||||
|
||||
if (jsonObject.containsKey("examples")) {
|
||||
JsonArray examplesArray = jsonObject.getJsonArray("examples");
|
||||
skill.setExamples(jsonArrayToStringList(examplesArray));
|
||||
}
|
||||
|
||||
if (jsonObject.containsKey("inputModes")) {
|
||||
JsonArray inputModesArray = jsonObject.getJsonArray("inputModes");
|
||||
skill.setInputModes(jsonArrayToStringList(inputModesArray));
|
||||
}
|
||||
|
||||
if (jsonObject.containsKey("outputModes")) {
|
||||
JsonArray outputModesArray = jsonObject.getJsonArray("outputModes");
|
||||
skill.setOutputModes(jsonArrayToStringList(outputModesArray));
|
||||
}
|
||||
|
||||
// Metadata
|
||||
if (jsonObject.containsKey("metadata")) {
|
||||
JsonObject metadataObject = jsonObject.getJsonObject("metadata");
|
||||
Map<String, Object> metadata = new HashMap<>();
|
||||
metadataObject.forEach((key, value) -> {
|
||||
switch (value.getValueType()) {
|
||||
case STRING:
|
||||
metadata.put(key, ((JsonString) value).getString());
|
||||
break;
|
||||
case NUMBER:
|
||||
metadata.put(key, ((jakarta.json.JsonNumber) value).doubleValue());
|
||||
break;
|
||||
case TRUE:
|
||||
metadata.put(key, Boolean.TRUE);
|
||||
break;
|
||||
case FALSE:
|
||||
metadata.put(key, Boolean.FALSE);
|
||||
break;
|
||||
default:
|
||||
metadata.put(key, value.toString());
|
||||
}
|
||||
});
|
||||
skill.setMetadata(metadata);
|
||||
}
|
||||
|
||||
return skill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to convert JsonArray to List<String>
|
||||
*/
|
||||
private static List<String> jsonArrayToStringList(JsonArray jsonArray) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (JsonValue value : jsonArray) {
|
||||
if (value.getValueType() == JsonValue.ValueType.STRING) {
|
||||
list.add(((JsonString) value).getString());
|
||||
} else {
|
||||
list.add(value.toString());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// Validation
|
||||
|
||||
/**
|
||||
* Validates this skill card for A2A compliance
|
||||
*
|
||||
* @return true if valid, false otherwise
|
||||
*/
|
||||
public boolean isValid() {
|
||||
if (id == null || id.trim().isEmpty()) {
|
||||
logger.warning("Skill card validation failed: missing ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
logger.warning("Skill card validation failed: missing name");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (description == null || description.trim().isEmpty()) {
|
||||
logger.warning("Skill card validation failed: missing description");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate skill ID format
|
||||
try {
|
||||
getModelVersion();
|
||||
getTaskId();
|
||||
getEventId();
|
||||
} catch (Exception e) {
|
||||
logger.warning("Skill card validation failed: invalid ID format: " + id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(List<String> tags) {
|
||||
this.tags = tags != null ? tags : new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<String> getExamples() {
|
||||
return examples;
|
||||
}
|
||||
|
||||
public void setExamples(List<String> examples) {
|
||||
this.examples = examples != null ? examples : new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<String> getInputModes() {
|
||||
return inputModes;
|
||||
}
|
||||
|
||||
public void setInputModes(List<String> inputModes) {
|
||||
this.inputModes = inputModes != null ? inputModes : new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<String> getOutputModes() {
|
||||
return outputModes;
|
||||
}
|
||||
|
||||
public void setOutputModes(List<String> outputModes) {
|
||||
this.outputModes = outputModes != null ? outputModes : new ArrayList<>();
|
||||
}
|
||||
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Map<String, Object> metadata) {
|
||||
this.metadata = metadata != null ? metadata : new HashMap<>();
|
||||
}
|
||||
|
||||
// Convenience methods for metadata
|
||||
|
||||
/**
|
||||
* Adds a metadata entry
|
||||
*/
|
||||
public void addMetadata(String key, Object value) {
|
||||
if (metadata == null) {
|
||||
metadata = new HashMap<>();
|
||||
}
|
||||
metadata.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a metadata value as String
|
||||
*/
|
||||
public String getMetadataString(String key) {
|
||||
Object value = metadata != null ? metadata.get(key) : null;
|
||||
return value != null ? value.toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a metadata value as Boolean
|
||||
*/
|
||||
public Boolean getMetadataBoolean(String key) {
|
||||
Object value = metadata != null ? metadata.get(key) : null;
|
||||
if (value instanceof Boolean) {
|
||||
return (Boolean) value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// toString for debugging
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("A2ASkillCard{id='%s', name='%s', modelVersion='%s', taskId=%d, eventId=%d}",
|
||||
id, name,
|
||||
id != null ? getModelVersion() : "unknown",
|
||||
id != null ? getTaskId() : -1,
|
||||
id != null ? getEventId() : -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
A2ASkillCard that = (A2ASkillCard) obj;
|
||||
return id != null ? id.equals(that.id) : that.id == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id != null ? id.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,436 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Imixs Workflow
|
||||
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public
|
||||
* License at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Project:
|
||||
* http://www.imixs.org
|
||||
* http://java.net/projects/imixs-workflow
|
||||
*
|
||||
* Contributors:
|
||||
* Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika - Software Developer
|
||||
*******************************************************************************/
|
||||
|
||||
package ai.dynamixs.a2a;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonArray;
|
||||
import jakarta.json.JsonArrayBuilder;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonObjectBuilder;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
|
||||
/**
|
||||
* The TextblockRestService provides methods to access the content of a textbock
|
||||
* in various ways.
|
||||
*
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
@Named
|
||||
@RequestScoped
|
||||
@Path("/a2a/")
|
||||
@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.TEXT_PLAIN })
|
||||
public class A2ASkillCardRestService implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Logger logger = Logger.getLogger(A2ASkillCardRestService.class.getSimpleName());
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
|
||||
@Inject
|
||||
A2ASkillService a2aSkillService;
|
||||
|
||||
/**
|
||||
* A2A Agent Card Discovery Endpoint According to RFC 8615 - Well-Known URIs
|
||||
* URL: /.well-known/agent.json
|
||||
*/
|
||||
@GET
|
||||
@Path("/.well-known/agent.json")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response getAgentCard() {
|
||||
try {
|
||||
JsonObject agentCard = buildAgentCard();
|
||||
return Response.ok(agentCard).build();
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error creating agent card: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", null))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A2A JSON-RPC 2.0 Endpoint All A2A protocol methods are handled here URL:
|
||||
* /a2a/v1 (as specified in Agent Card)
|
||||
*/
|
||||
@POST
|
||||
@Path("/a2a/v1")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response handleJsonRpcRequest(JsonObject request) {
|
||||
try {
|
||||
// Validate JSON-RPC 2.0 structure
|
||||
if (!isValidJsonRpcRequest(request)) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(buildJsonRpcError(-32600, "Invalid Request", null))
|
||||
.build();
|
||||
}
|
||||
|
||||
String method = request.getString("method");
|
||||
Object id = request.get("id");
|
||||
JsonObject params = request.getJsonObject("params");
|
||||
|
||||
// Route to appropriate A2A method
|
||||
switch (method) {
|
||||
case "message/send":
|
||||
return handleMessageSend(id, params);
|
||||
case "tasks/get":
|
||||
return handleTasksGet(id, params);
|
||||
case "tasks/cancel":
|
||||
return handleTasksCancel(id, params);
|
||||
case "agent/authenticatedExtendedCard":
|
||||
return handleAuthenticatedExtendedCard(id, params);
|
||||
default:
|
||||
return Response.status(Response.Status.NOT_FOUND)
|
||||
.entity(buildJsonRpcError(-32601, "Method not found", id))
|
||||
.build();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error processing JSON-RPC request: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", null))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the A2A compliant Agent Card
|
||||
*/
|
||||
private JsonObject buildAgentCard() {
|
||||
// Security schemes for authentication
|
||||
JsonObject securitySchemes = Json.createObjectBuilder()
|
||||
.add("bearer", Json.createObjectBuilder()
|
||||
.add("type", "http")
|
||||
.add("scheme", "bearer")
|
||||
.add("bearerFormat", "JWT")
|
||||
.build())
|
||||
.add("apiKey", Json.createObjectBuilder()
|
||||
.add("type", "apiKey")
|
||||
.add("in", "header")
|
||||
.add("name", "X-API-Key")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
// Security requirements
|
||||
JsonArray security = Json.createArrayBuilder()
|
||||
.add(Json.createObjectBuilder()
|
||||
.add("bearer", Json.createArrayBuilder().build())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
// Agent capabilities
|
||||
JsonObject capabilities = Json.createObjectBuilder()
|
||||
.add("streaming", false) // SSE not implemented yet
|
||||
.add("pushNotifications", false) // Push notifications not implemented yet
|
||||
.add("stateTransitionHistory", false)
|
||||
.build();
|
||||
|
||||
// Agent provider information
|
||||
JsonObject provider = Json.createObjectBuilder()
|
||||
.add("organization", "Dynamixs.AI")
|
||||
.add("url", "https://www.dynamixs.ai")
|
||||
.build();
|
||||
|
||||
// Skills array
|
||||
JsonArray skills = buildA2ASkills();
|
||||
|
||||
// Build complete A2A Agent Card
|
||||
JsonObjectBuilder cardBuilder = Json.createObjectBuilder()
|
||||
.add("name", "Dynamixs.AI Processing Agent")
|
||||
.add("description",
|
||||
"An agent for processing business documents and tasks.")
|
||||
.add("url", getBaseUrl() + "a2a/v1") // JSON-RPC endpoint
|
||||
.add("provider", provider)
|
||||
.add("version", "1.0.0")
|
||||
.add("documentationUrl", getBaseUrl() + "docs/a2a")
|
||||
.add("capabilities", capabilities)
|
||||
.add("securitySchemes", securitySchemes)
|
||||
.add("security", security)
|
||||
.add("defaultInputModes", Json.createArrayBuilder()
|
||||
.add("text/plain")
|
||||
.add("application/json")
|
||||
.build())
|
||||
.add("defaultOutputModes", Json.createArrayBuilder()
|
||||
.add("text/plain")
|
||||
.add("application/json")
|
||||
.add("text/html")
|
||||
.build())
|
||||
.add("skills", skills)
|
||||
.add("supportsAuthenticatedExtendedCard", false); // Simplified for now
|
||||
|
||||
return cardBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds A2A compliant skills array
|
||||
*/
|
||||
private JsonArray buildA2ASkills() {
|
||||
|
||||
logger.info("Starting to build A2A skills...");
|
||||
|
||||
List<A2ASkillCard> skills = a2aSkillService.parseModels();
|
||||
logger.info("parseModels() returned " + (skills != null ? skills.size() : "null") + " skills");
|
||||
|
||||
if (skills != null) {
|
||||
for (A2ASkillCard skill : skills) {
|
||||
logger.info("Skill found: " + skill.getId() + " - Valid: " + skill.isValid());
|
||||
if (!skill.isValid()) {
|
||||
logger.warning("Invalid skill: " + skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<A2ASkillCard> validSkills = skills.stream()
|
||||
.filter(A2ASkillCard::isValid)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
logger.info("Valid skills after filtering: " + validSkills.size());
|
||||
|
||||
return validSkills.stream()
|
||||
.map(A2ASkillCard::toJsonObject)
|
||||
.collect(Json::createArrayBuilder,
|
||||
JsonArrayBuilder::add,
|
||||
JsonArrayBuilder::addAll)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle A2A message/send method
|
||||
*/
|
||||
private Response handleMessageSend(Object id, JsonObject params) {
|
||||
try {
|
||||
// Extract message from params
|
||||
JsonObject message = params.getJsonObject("message");
|
||||
if (message == null) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(buildJsonRpcError(-32602, "Invalid params: missing message",
|
||||
id))
|
||||
.build();
|
||||
}
|
||||
|
||||
// Process the message and create a task
|
||||
String taskId = generateTaskId();
|
||||
String contextId = generateContextId();
|
||||
|
||||
// For demo: create a simple completed task
|
||||
JsonObject task = Json.createObjectBuilder()
|
||||
.add("id", taskId)
|
||||
.add("contextId", contextId)
|
||||
.add("status", Json.createObjectBuilder()
|
||||
.add("state", "completed")
|
||||
.add("timestamp", getCurrentTimestamp())
|
||||
.build())
|
||||
.add("artifacts", Json.createArrayBuilder()
|
||||
.add(Json.createObjectBuilder()
|
||||
.add("artifactId", generateArtifactId())
|
||||
.add("name", "Processing Result")
|
||||
.add("parts", Json.createArrayBuilder()
|
||||
.add(Json.createObjectBuilder()
|
||||
.add("kind", "text")
|
||||
.add("text", "Task completed successfully. Message processed: "
|
||||
+
|
||||
message.getJsonArray(
|
||||
"parts")
|
||||
.getJsonObject(0)
|
||||
.getString("text",
|
||||
""))
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.add("history", Json.createArrayBuilder()
|
||||
.add(message)
|
||||
.build())
|
||||
.add("kind", "task")
|
||||
.build();
|
||||
|
||||
// Return JSON-RPC success response
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", task)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in message/send: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle A2A tasks/get method
|
||||
*/
|
||||
private Response handleTasksGet(Object id, JsonObject params) {
|
||||
try {
|
||||
String taskId = params.getString("id");
|
||||
|
||||
// For demo: return a mock task
|
||||
JsonObject task = Json.createObjectBuilder()
|
||||
.add("id", taskId)
|
||||
.add("contextId", generateContextId())
|
||||
.add("status", Json.createObjectBuilder()
|
||||
.add("state", "completed")
|
||||
.add("timestamp", getCurrentTimestamp())
|
||||
.build())
|
||||
.add("kind", "task")
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", task)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in tasks/get: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32001, "Task not found", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle A2A tasks/cancel method
|
||||
*/
|
||||
private Response handleTasksCancel(Object id, JsonObject params) {
|
||||
try {
|
||||
String taskId = params.getString("id");
|
||||
|
||||
JsonObject task = Json.createObjectBuilder()
|
||||
.add("id", taskId)
|
||||
.add("contextId", generateContextId())
|
||||
.add("status", Json.createObjectBuilder()
|
||||
.add("state", "canceled")
|
||||
.add("timestamp", getCurrentTimestamp())
|
||||
.build())
|
||||
.add("kind", "task")
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", task)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32002, "Task cannot be canceled", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle authenticated extended card (not implemented)
|
||||
*/
|
||||
private Response handleAuthenticatedExtendedCard(Object id, JsonObject params) {
|
||||
return Response.status(Response.Status.NOT_IMPLEMENTED)
|
||||
.entity(buildJsonRpcError(-32004, "This operation is not supported", id))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates JSON-RPC 2.0 request structure
|
||||
*/
|
||||
private boolean isValidJsonRpcRequest(JsonObject request) {
|
||||
return request.containsKey("jsonrpc") &&
|
||||
"2.0".equals(request.getString("jsonrpc")) &&
|
||||
request.containsKey("method") &&
|
||||
request.containsKey("id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a JSON-RPC 2.0 error response
|
||||
*/
|
||||
private JsonObject buildJsonRpcError(int code, String message, Object id) {
|
||||
JsonObjectBuilder errorBuilder = Json.createObjectBuilder()
|
||||
.add("code", code)
|
||||
.add("message", message);
|
||||
|
||||
JsonObjectBuilder responseBuilder = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("error", errorBuilder.build());
|
||||
|
||||
if (id != null) {
|
||||
responseBuilder.add("id", id.toString());
|
||||
} else {
|
||||
responseBuilder.addNull("id");
|
||||
}
|
||||
|
||||
return responseBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper methods for generating IDs and timestamps
|
||||
*/
|
||||
private String generateTaskId() {
|
||||
return java.util.UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
private String generateContextId() {
|
||||
return java.util.UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
private String generateArtifactId() {
|
||||
return java.util.UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
private String getCurrentTimestamp() {
|
||||
return java.time.Instant.now().toString();
|
||||
}
|
||||
|
||||
private String getBaseUrl() {
|
||||
return uriInfo.getBaseUri().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Imixs Workflow
|
||||
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public
|
||||
* License at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Project:
|
||||
* http://www.imixs.org
|
||||
* http://java.net/projects/imixs-workflow
|
||||
*
|
||||
* Contributors:
|
||||
* Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika - Software Developer
|
||||
*******************************************************************************/
|
||||
|
||||
package ai.dynamixs.a2a;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.ModelManager;
|
||||
import org.imixs.workflow.engine.ModelService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.ModelException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.openbpmn.bpmn.BPMNModel;
|
||||
|
||||
import jakarta.annotation.security.DeclareRoles;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ejb.LocalBean;
|
||||
import jakarta.ejb.Stateless;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The A2ASkillService parses the model information to provide A2ASkillCards
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS",
|
||||
"org.imixs.ACCESSLEVEL.READERACCESS",
|
||||
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.EDITORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS",
|
||||
"org.imixs.ACCESSLEVEL.READERACCESS",
|
||||
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.EDITORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@Stateless
|
||||
@LocalBean
|
||||
public class A2ASkillService {
|
||||
|
||||
@Inject
|
||||
ModelService modelService;
|
||||
|
||||
@Inject
|
||||
WorkflowService workflowService;
|
||||
|
||||
private static Logger logger = Logger.getLogger(A2ASkillService.class
|
||||
.getName());
|
||||
|
||||
/**
|
||||
* This method iterates over all models and returns a list of skill card objects
|
||||
*
|
||||
* The method tests if a event has a <imixs-ai name="SKILL"> tag.
|
||||
*
|
||||
*/
|
||||
public List<A2ASkillCard> parseModels() {
|
||||
logger.log(Level.INFO, "├── 🔃 parsing A2A SkillCards....");
|
||||
List<A2ASkillCard> result = new ArrayList<>();
|
||||
ModelManager modelManager = new ModelManager(workflowService);
|
||||
List<String> versions = modelService.getVersions();
|
||||
|
||||
try {
|
||||
|
||||
for (String version : versions) {
|
||||
logger.log(Level.INFO, "│ ├── {0}", version);
|
||||
BPMNModel model = modelManager.getModel(version);
|
||||
|
||||
Set<String> groups = modelManager.findAllGroupsByModel(model);
|
||||
for (String group : groups) {
|
||||
List<ItemCollection> tasks = modelManager.findTasks(model, group);
|
||||
for (ItemCollection task : tasks) {
|
||||
int taskID = task.getItemValueInteger("taskid");
|
||||
List<ItemCollection> events = modelManager.findEventsByTask(model, taskID);
|
||||
|
||||
for (ItemCollection event : events) {
|
||||
int eventID = event.getItemValueInteger("eventid");
|
||||
// test if we have a <imixs-ai name="SKILL">
|
||||
try {
|
||||
List<ItemCollection> llmPromptDefinitions = workflowService.evalWorkflowResultXML(event,
|
||||
"imixs-ai",
|
||||
"SKILL", null, false);
|
||||
// did we found a skill?
|
||||
for (ItemCollection skillItemCol : llmPromptDefinitions) {
|
||||
A2ASkillCard skillCard = new A2ASkillCard(version, taskID, eventID);
|
||||
|
||||
skillCard.setName(event.getItemValueString("name"));
|
||||
skillCard.setDescription(skillItemCol.getItemValueString("description"));
|
||||
String tags = skillItemCol.getItemValueString("tags");
|
||||
if (tags != null && !tags.isBlank()) {
|
||||
String[] parts = tags.split(",\\s*");
|
||||
skillCard.setTags(Arrays.asList(parts));
|
||||
}
|
||||
|
||||
skillCard.setExamples(skillItemCol.getItemValueList("example", String.class));
|
||||
|
||||
// skillCard.addMetadata("aea", versions);
|
||||
|
||||
if (skillCard.isValid()) {
|
||||
result.add(skillCard);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (PluginException e) {
|
||||
// no match
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} catch (ModelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
Imixs-Office-Workflow
|
||||
Copyright (C) 2001-2018 Imixs Software Solutions GmbH,
|
||||
http://www.imixs.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Project:
|
||||
http://www.imixs.org
|
||||
|
||||
Contributors:
|
||||
Imixs Software Solutions GmbH - initial API and implementation
|
||||
Ralph Soika - Software Developer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,621 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
|
||||
bean-discovery-mode="all" version="3.0">
|
||||
</beans>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
Imixs Workflow Technology
|
||||
Copyright (C) 2010 Imixs Software Solutions GmbH,
|
||||
http://www.imixs.com
|
||||
|
||||
|
||||
|
||||
Contributors:
|
||||
Imixs Software Solutions GmbH - initial implementation
|
||||
Ralph Soika
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
??
|
||||
|
|
@ -1,392 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>dynamixs-ai</artifactId>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>dynamixs-ai-app</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Dynamixs AI Web App</name>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>debug</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<exec executable="docker">
|
||||
<arg value="build" />
|
||||
<arg value="-f" />
|
||||
<arg value="../Dockerfile-debug" />
|
||||
<arg value="-t" />
|
||||
<arg value="imixs/${imixs-office.applicationname}" />
|
||||
<arg value="./." />
|
||||
</exec>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
|
||||
<profile>
|
||||
<id>imixs-cloud</id>
|
||||
|
||||
<!-- Imixs Security OIDC -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.imixs.security</groupId>
|
||||
<artifactId>imixs-oidc</artifactId>
|
||||
<version>${org.imixs.security.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.security</groupId>
|
||||
<artifactId>imixs-oidc-marty</artifactId>
|
||||
<version>${org.imixs.security.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<exec executable="docker">
|
||||
<arg value="build" />
|
||||
<arg value="-t" />
|
||||
<arg
|
||||
value="imixs/${imixs-office.applicationname}:${project.version}" />
|
||||
<arg value="../." />
|
||||
</exec>
|
||||
<exec executable="docker">
|
||||
<arg value="tag" />
|
||||
<arg
|
||||
value="imixs/${imixs-office.applicationname}:${project.version}" />
|
||||
<arg
|
||||
value="${org.imixs.docker.registry}/imixs/${imixs-office.applicationname}:${project.version}" />
|
||||
</exec>
|
||||
<exec executable="docker">
|
||||
<arg value="push" />
|
||||
<arg
|
||||
value="${org.imixs.docker.registry}/imixs/${imixs-office.applicationname}:${project.version}" />
|
||||
</exec>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<!-- enable resource filtering for multi language version -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<webResources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<!-- this is relative to the pom.xml directory -->
|
||||
<directory>${custom.webResources}</directory>
|
||||
<includes>
|
||||
<include>**/WEB-INF/*</include>
|
||||
<!-- include any other file types you want to filter -->
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
<workDirectory>target/overlay-war-folder</workDirectory>
|
||||
<!-- We exclude libs form the parent WAR artifact -->
|
||||
<overlays>
|
||||
<overlay>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-office-workflow-app</artifactId>
|
||||
<excludes>
|
||||
<exclude>WEB-INF/lib/*.jar</exclude>
|
||||
</excludes>
|
||||
</overlay>
|
||||
</overlays>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
<plugin>
|
||||
<groupId>org.imixs.maven</groupId>
|
||||
<artifactId>manik-hotdeploy-maven-plugin</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>deploy</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!-- List Source and Target folders for Autodeploy and Hotdeploy -->
|
||||
<autodeployments>
|
||||
<deployment>
|
||||
<!-- wildcard deployment -->
|
||||
<source>target/*.{war,ear,jar}</source>
|
||||
<target>../docker/deployments/</target>
|
||||
<unpack>true</unpack>
|
||||
</deployment>
|
||||
</autodeployments>
|
||||
<hotdeployments>
|
||||
<deployment>
|
||||
<source>src/main/webapp</source>
|
||||
<target>../docker/deployments/dynamixs-ai.war</target>
|
||||
</deployment>
|
||||
</hotdeployments>
|
||||
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
</plugins>
|
||||
|
||||
<finalName>dynamixs-ai</finalName>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
<!-- Imixs Workflow -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-core</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-engine</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-jax-rs</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-faces</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-index-lucene</artifactId>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- A2A -->
|
||||
<dependency>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<artifactId>dynamixs-ai-a2a</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MCP -->
|
||||
<dependency>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<artifactId>dynamixs-ai-mcp</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Marty -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-marty</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Metrics -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-metrics-monitor</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs-Office-Workflow Overlay -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-office-workflow-app</artifactId>
|
||||
<type>war</type>
|
||||
<version>${org.imixs.office.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-office-workflow-util</artifactId>
|
||||
<version>${org.imixs.office.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs-Archive -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-archive-api</artifactId>
|
||||
<version>${org.imixs.archive.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs Data -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-groups</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-views</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-documents</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-importer</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- -->
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>${apache.pdfbox.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs-AI -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-ai-rag</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-ai-workflow</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-ai-bpmn</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs-QR-Code -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-qrcode</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs-Wopi -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-wopi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-odf</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs Signature Feature -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-signature-api</artifactId>
|
||||
<version>${org.imixs.signature.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SEPA -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-sepa</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- DATEV -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-datev</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- POI Adapter -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-poi</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- OIDC
|
||||
<dependency>
|
||||
<groupId>org.imixs.security</groupId>
|
||||
<artifactId>imixs-oidc</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.security</groupId>
|
||||
<artifactId>imixs-oidc-marty</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
-->
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,546 +0,0 @@
|
|||
package ai.dynamixs;
|
||||
|
||||
/*******************************************************************************
|
||||
* Imixs Workflow Technology
|
||||
* Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public
|
||||
* License at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Contributors:
|
||||
* Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.ai.workflow.ImixsAIPromptEvent;
|
||||
import org.imixs.workflow.FileData;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.ItemCollectionComparator;
|
||||
import org.imixs.workflow.WorkflowKernel;
|
||||
import org.imixs.workflow.engine.DocumentService;
|
||||
import org.imixs.workflow.engine.plugins.HistoryPlugin;
|
||||
import org.imixs.workflow.exceptions.QueryException;
|
||||
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The ChronicleTextBuilder is a CDI Bean observing the CDI event
|
||||
* `ImixsAIPromptEvent` and replaces the placeholder {chronicle} with the
|
||||
* chronicle data of the given workitem.
|
||||
* <p>
|
||||
* The class creates a text representation of all chronicle data for a given
|
||||
* workitem.
|
||||
* <p>
|
||||
* The output format is structured by year and month:
|
||||
*
|
||||
* <pre>
|
||||
* 2025
|
||||
*
|
||||
* December
|
||||
* 27. Dec 2025 (14:37) - Ralph Soika
|
||||
* Offer sent
|
||||
* Products are out of stock now!
|
||||
*
|
||||
* 27. Dec 2025 (14:35) - imixs-workflow-service
|
||||
* Retrieve Products
|
||||
* Retrieve Address
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Usage example:
|
||||
*
|
||||
* <pre>
|
||||
* ChronicleTextBuilder builder = new ChronicleTextBuilder(workitem, locale);
|
||||
* builder.setDmsController(dmsController);
|
||||
* builder.setWorkitemLinkController(workitemLinkController);
|
||||
* builder.setWorkitemService(workitemService);
|
||||
* builder.setDocumentService(documentService);
|
||||
* String chronicleText = builder.build();
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The builder supports filtering by entry type (history, comment, dms,
|
||||
* reference, version, imixs-ai).
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
public class ChronicleTextBuilder implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Logger logger = Logger.getLogger(ChronicleTextBuilder.class.getName());
|
||||
|
||||
private ItemCollection workitem;
|
||||
private Locale locale;
|
||||
private String filterType;
|
||||
|
||||
// @Inject
|
||||
// private WorkitemService workitemService;
|
||||
|
||||
@Inject
|
||||
private DocumentService documentService;
|
||||
|
||||
// Internal data structures
|
||||
private List<ChronicleEntry> chronicleEntries;
|
||||
private Map<Integer, Set<Integer>> yearsMonths;
|
||||
|
||||
// Date formatters
|
||||
private DateTimeFormatter dayFormatter;
|
||||
private DateTimeFormatter timeFormatter;
|
||||
private DateTimeFormatter monthFormatter;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public ChronicleTextBuilder() {
|
||||
this.locale = Locale.ENGLISH;
|
||||
this.filterType = null;
|
||||
this.chronicleEntries = new ArrayList<>();
|
||||
this.yearsMonths = new HashMap<>();
|
||||
|
||||
// Initialize date formatters
|
||||
this.dayFormatter = DateTimeFormatter.ofPattern("d. MMM yyyy", this.locale);
|
||||
this.timeFormatter = DateTimeFormatter.ofPattern("HH:mm", this.locale);
|
||||
this.monthFormatter = DateTimeFormatter.ofPattern("MMMM", this.locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with workitem and locale.
|
||||
*
|
||||
* @param workitem the workitem to build the chronicle for
|
||||
* @param locale the locale for date formatting (e.g., Locale.ENGLISH,
|
||||
* Locale.GERMAN)
|
||||
*/
|
||||
public ChronicleTextBuilder(ItemCollection workitem, Locale locale) {
|
||||
this.workitem = workitem;
|
||||
this.locale = locale != null ? locale : Locale.ENGLISH;
|
||||
this.filterType = null;
|
||||
this.chronicleEntries = new ArrayList<>();
|
||||
this.yearsMonths = new HashMap<>();
|
||||
|
||||
// Initialize date formatters
|
||||
this.dayFormatter = DateTimeFormatter.ofPattern("d. MMM yyyy", this.locale);
|
||||
this.timeFormatter = DateTimeFormatter.ofPattern("HH:mm", this.locale);
|
||||
this.monthFormatter = DateTimeFormatter.ofPattern("MMMM", this.locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with workitem only (uses English locale as default).
|
||||
*
|
||||
* @param workitem the workitem to build the chronicle for
|
||||
*/
|
||||
public ChronicleTextBuilder(ItemCollection workitem) {
|
||||
this(workitem, Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
* This CDI class reacts on the CDI Event `ImixsAIPromptEvent` and replaces the
|
||||
* placeholder {chronicle} with the chronicle data of the given workitem.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public void onEvent(@Observes ImixsAIPromptEvent event) {
|
||||
if (event.getWorkitem() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String prompt = event.getPromptTemplate();
|
||||
if (prompt.contains("{chronicle}")) {
|
||||
this.workitem = event.getWorkitem();
|
||||
String result = build();
|
||||
|
||||
prompt = prompt.replace("{chronicle}", result);
|
||||
// update the prompt tempalte
|
||||
event.setPromptTemplate(prompt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a filter to include only entries of a specific type. Valid types:
|
||||
* history, comment, dms, reference, version, imixs-ai
|
||||
*
|
||||
* @param filterType the type to filter by, or null to include all
|
||||
* @return this builder for method chaining
|
||||
*/
|
||||
public ChronicleTextBuilder setFilter(String filterType) {
|
||||
this.filterType = filterType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns the text representation of the chronicle.
|
||||
*
|
||||
* @return formatted chronicle text
|
||||
*/
|
||||
public String build() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
if (workitem == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Collect all chronicle data
|
||||
collectHistoryEntries();
|
||||
collectCommentEntries();
|
||||
|
||||
collectDMSEntries();
|
||||
|
||||
collectVersionEntries();
|
||||
|
||||
// Sort entries by date (newest first)
|
||||
Collections.sort(chronicleEntries, new ChronicleEntryComparator(false));
|
||||
|
||||
// Build the text output
|
||||
String result = buildTextOutput();
|
||||
|
||||
logger.fine("ChronicleTextBuilder.build() completed in " + (System.currentTimeMillis() - startTime) + "ms");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects workflow history entries from the workitem.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void collectHistoryEntries() {
|
||||
List<List<?>> history = null;
|
||||
|
||||
// Check for deprecated field 'txtworkflowhistory'
|
||||
if (!workitem.hasItem(HistoryPlugin.ITEM_HISTORY_LOG)
|
||||
&& workitem.hasItem("txtworkflowhistory")) {
|
||||
history = workitem.getItemValue("txtworkflowhistory");
|
||||
// Sort old history entries chronologically
|
||||
Collections.sort(history, new Comparator<List<?>>() {
|
||||
@Override
|
||||
public int compare(List<?> entry1, List<?> entry2) {
|
||||
Date date1 = (Date) entry1.get(0);
|
||||
Date date2 = (Date) entry2.get(0);
|
||||
return date1.compareTo(date2);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
history = workitem.getItemValue(HistoryPlugin.ITEM_HISTORY_LOG);
|
||||
}
|
||||
|
||||
// Reverse to get newest first
|
||||
// Collections.reverse(history);
|
||||
|
||||
if (history.size() > 0 && history.get(0) instanceof List) {
|
||||
for (List<?> entries : history) {
|
||||
Date date = (Date) entries.get(0);
|
||||
String message = (String) entries.get(1);
|
||||
String user = (String) entries.get(2);
|
||||
addEntry(date, user, message, "history");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects comment entries from the workitem.
|
||||
*/
|
||||
private void collectCommentEntries() {
|
||||
List<Map<String, List<Object>>> comments = workitem.getItemValue("txtCommentLog");
|
||||
for (Map<String, List<Object>> comment : comments) {
|
||||
ItemCollection itemCol = new ItemCollection(comment);
|
||||
Date date = itemCol.getItemValueDate("datcomment");
|
||||
String message = itemCol.getItemValueString("txtcomment");
|
||||
String user = itemCol.getItemValueString("nameditor");
|
||||
addEntry(date, user, message, "comment");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects DMS (attachment) entries if dmsController is available.
|
||||
*/
|
||||
private void collectDMSEntries() {
|
||||
|
||||
List<FileData> fileDataList = workitem.getFileData();
|
||||
for (FileData fileData : fileDataList) {
|
||||
|
||||
ItemCollection fileAttributes = new ItemCollection(fileData.getAttributes());
|
||||
|
||||
String content = fileAttributes.getItemValueString("text");
|
||||
if (!content.isBlank()) {
|
||||
String user = fileAttributes.getItemValueString("$creator");
|
||||
Date date = fileAttributes.getItemValueDate("$created");
|
||||
if (fileData.getAttribute("$modified") != null) {
|
||||
date = fileAttributes.getItemValueDate("$modified");
|
||||
}
|
||||
if (date == null) {
|
||||
date = new Date();
|
||||
}
|
||||
addEntry(date, user, "Attachment: " + fileData.getName() + "\n\n" + content + "\n\n", "dms");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects version entries if workitemService and documentService are
|
||||
* available.
|
||||
*/
|
||||
private void collectVersionEntries() {
|
||||
|
||||
List<ItemCollection> versions = findAllVersions(workitem);
|
||||
for (ItemCollection version : versions) {
|
||||
// Skip current workitem
|
||||
if (workitem.getUniqueID().equals(version.getUniqueID())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemCollection versionFull = documentService.load(version.getUniqueID());
|
||||
Date date = version.getItemValueDate(WorkflowKernel.CREATED);
|
||||
String message = version.getItemValueString("$WorkflowSummary");
|
||||
String user = version.getItemValueString(WorkflowKernel.EDITOR);
|
||||
|
||||
if (!versionFull.getItemValueString("$uniqueIdSource").isEmpty()) {
|
||||
if (versionFull.hasItem(WorkflowKernel.CREATED + ".version")) {
|
||||
date = versionFull.getItemValueDate(WorkflowKernel.CREATED + ".version");
|
||||
}
|
||||
message = "Version (Branch): " + message;
|
||||
} else {
|
||||
message = "Version: " + message;
|
||||
}
|
||||
|
||||
addEntry(date, user, message, "version");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a chronicle entry to the internal list. Applies filter if set and
|
||||
* updates the year/month index.
|
||||
*/
|
||||
private void addEntry(Date date, String user, String message, String type) {
|
||||
if (date == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply filter if set
|
||||
if (filterType != null && !filterType.isEmpty() && !filterType.equals(type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Truncate to minutes
|
||||
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
localDateTime = localDateTime.truncatedTo(ChronoUnit.MINUTES);
|
||||
|
||||
ChronicleEntry entry = new ChronicleEntry(localDateTime, user, message, type);
|
||||
chronicleEntries.add(entry);
|
||||
|
||||
// Update year/month index
|
||||
LocalDate localDate = localDateTime.toLocalDate();
|
||||
int year = localDate.getYear();
|
||||
int month = localDate.getMonthValue();
|
||||
yearsMonths.computeIfAbsent(year, k -> new HashSet<>()).add(month);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the formatted text output from collected entries.
|
||||
*/
|
||||
private String buildTextOutput() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// Add title
|
||||
sb.append(
|
||||
"# " + workitem.getWorkflowGroup() + " : " + workitem.getItemValueString(WorkflowKernel.WORKFLOWSTATUS))
|
||||
.append("\n\n");
|
||||
|
||||
// Get sorted years (descending)
|
||||
List<Integer> years = new ArrayList<>(yearsMonths.keySet());
|
||||
|
||||
for (int i = 0; i < years.size(); i++) {
|
||||
int year = years.get(i);
|
||||
|
||||
// Year header
|
||||
// sb.append(year).append("\n\n");
|
||||
|
||||
// Get sorted months for this year (descending)
|
||||
List<Integer> months = new ArrayList<>(yearsMonths.get(year));
|
||||
|
||||
for (int j = 0; j < months.size(); j++) {
|
||||
int month = months.get(j);
|
||||
|
||||
// Get entries for this month
|
||||
List<ChronicleEntry> monthEntries = getEntriesForMonth(year, month);
|
||||
|
||||
if (monthEntries.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Month header
|
||||
// String monthName = LocalDate.of(year, month, 1).format(monthFormatter);
|
||||
// sb.append(monthName).append("\n\n");
|
||||
|
||||
// Group entries by user and timestamp
|
||||
List<GroupedEntry> groupedEntries = groupEntries(monthEntries);
|
||||
|
||||
for (GroupedEntry grouped : groupedEntries) {
|
||||
// Format: "27. Dec 2025 (14:37) - Ralph Soika"
|
||||
String dayStr = grouped.dateTime.format(dayFormatter);
|
||||
String timeStr = grouped.dateTime.format(timeFormatter);
|
||||
sb.append("\n" + dayStr).append(" (").append(timeStr).append(") - ").append(grouped.user)
|
||||
.append("\n");
|
||||
|
||||
// Add all messages for this group
|
||||
for (String message : grouped.messages) {
|
||||
sb.append(message).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Add spacing between months (but not after the last month of the last year)
|
||||
if (j < months.size() - 1 || i < years.size() - 1) {
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all entries for a specific year and month.
|
||||
*/
|
||||
private List<ChronicleEntry> getEntriesForMonth(int year, int month) {
|
||||
List<ChronicleEntry> result = new ArrayList<>();
|
||||
for (ChronicleEntry entry : chronicleEntries) {
|
||||
if (entry.dateTime.getYear() == year && entry.dateTime.getMonthValue() == month) {
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups entries by user and timestamp (same minute). This consolidates
|
||||
* multiple actions by the same user at the same time.
|
||||
*/
|
||||
private List<GroupedEntry> groupEntries(List<ChronicleEntry> entries) {
|
||||
List<GroupedEntry> grouped = new ArrayList<>();
|
||||
GroupedEntry current = null;
|
||||
|
||||
for (ChronicleEntry entry : entries) {
|
||||
if (current == null ||
|
||||
!current.user.equals(entry.user) ||
|
||||
!current.dateTime.equals(entry.dateTime)) {
|
||||
// Start a new group
|
||||
current = new GroupedEntry(entry.dateTime, entry.user);
|
||||
grouped.add(current);
|
||||
}
|
||||
current.messages.add(entry.message);
|
||||
}
|
||||
|
||||
return grouped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class representing a single chronicle entry.
|
||||
*/
|
||||
private static class ChronicleEntry {
|
||||
LocalDateTime dateTime;
|
||||
String user;
|
||||
String message;
|
||||
String type;
|
||||
|
||||
ChronicleEntry(LocalDateTime dateTime, String user, String message, String type) {
|
||||
this.dateTime = dateTime;
|
||||
this.user = user != null ? user : "";
|
||||
this.message = message != null ? message : "";
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class for grouping entries by user and timestamp.
|
||||
*/
|
||||
private static class GroupedEntry {
|
||||
LocalDateTime dateTime;
|
||||
String user;
|
||||
List<String> messages;
|
||||
|
||||
GroupedEntry(LocalDateTime dateTime, String user) {
|
||||
this.dateTime = dateTime;
|
||||
this.user = user;
|
||||
this.messages = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator for sorting chronicle entries by date.
|
||||
*/
|
||||
private static class ChronicleEntryComparator implements Comparator<ChronicleEntry> {
|
||||
private boolean descending;
|
||||
|
||||
ChronicleEntryComparator(boolean descending) {
|
||||
this.descending = descending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(ChronicleEntry e1, ChronicleEntry e2) {
|
||||
int result = e1.dateTime.compareTo(e2.dateTime);
|
||||
return descending ? -result : result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method finds all versions of a given workitem.
|
||||
*
|
||||
*/
|
||||
private List<ItemCollection> findAllVersions(ItemCollection workitem) {
|
||||
List<ItemCollection> versions = new ArrayList<ItemCollection>();
|
||||
if (null == workitem)
|
||||
return versions;
|
||||
List<ItemCollection> col = null;
|
||||
String sRefID = workitem.getItemValueString("$workitemId");
|
||||
String refQuery = "( (type:\"workitem\" OR type:\"workitemarchive\" OR type:\"workitemversion\") AND $workitemid:\""
|
||||
+ sRefID + "\")";
|
||||
try {
|
||||
col = documentService.findStubs(refQuery, 999, 0, WorkflowKernel.LASTEVENTDATE, true);
|
||||
// sort by $modified
|
||||
Collections.sort(col, new ItemCollectionComparator("$modified", true));
|
||||
// Only return version list if more than one version was found!
|
||||
if (col.size() > 1) {
|
||||
for (ItemCollection aworkitem : col) {
|
||||
versions.add(aworkitem);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (QueryException e) {
|
||||
logger.warning("findAllVersions - invalid query: " + e.getMessage());
|
||||
}
|
||||
return versions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
/****************************************************************************
|
||||
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* This Source Code may also be made available under the terms of the
|
||||
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
|
||||
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
****************************************************************************/
|
||||
|
||||
package ai.dynamixs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.ai.rag.index.IndexService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.WorkflowKernel;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.AdapterException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.imixs.workflow.exceptions.QueryException;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The OrderPlugin is a generic plugin for Order workflows.
|
||||
* <p>
|
||||
* The plugin collects a list of $uniqueids for the last 5 orders for the given
|
||||
* customer.ref. The list is stored in the item `order.history.ref`
|
||||
*
|
||||
* <p>
|
||||
* The plugin extends the default imixs-ai RAGIndexPlugin. In the mode INDEX
|
||||
* this plugins generates a default prompt template.This is to simplify the
|
||||
* models.
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
{@code
|
||||
<dynamixs-ai name="INDEX">
|
||||
<debug>false</debug>
|
||||
</dynamixs-ai>
|
||||
}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The tag 'debug' is optional
|
||||
*
|
||||
*
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
public class OrderPlugin extends org.imixs.ai.rag.workflow.RAGIndexPlugin {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(OrderPlugin.class.getName());
|
||||
public static final String LINK_PROPERTY = "$workitemref";
|
||||
public static final int MAX_HISTORY_RESULT = 5;
|
||||
@Inject
|
||||
private WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
private IndexService ragService;
|
||||
|
||||
@Override
|
||||
public ItemCollection run(ItemCollection workitem, ItemCollection event) throws PluginException {
|
||||
|
||||
// do not run on Snapshots!
|
||||
if (workitem.getType().startsWith("snapshot-")) {
|
||||
// no op!
|
||||
return workitem;
|
||||
}
|
||||
|
||||
logger.info("├── running Dynamixs.AI Order Plugin");
|
||||
|
||||
// Update History....
|
||||
updateOrderHistory(workitem);
|
||||
|
||||
// read optional configuration form the model or imixs.properties....
|
||||
List<ItemCollection> ragIndexDefinitions = workflowService.evalWorkflowResultXML(event, "dynamixs-ai",
|
||||
IndexService.RAG_INDEX, workitem, false);
|
||||
|
||||
try {
|
||||
// INDEX Mode?
|
||||
if (ragIndexDefinitions != null && ragIndexDefinitions.size() > 0) {
|
||||
|
||||
// do we have a prompt template?
|
||||
ItemCollection indexDefinition = ragIndexDefinitions.get(0);
|
||||
String promptTemplate = indexDefinition.getItemValueString("promptTemplate");
|
||||
if (promptTemplate.isBlank()) {
|
||||
// generate default template
|
||||
ChronicleTextBuilder chronicleTextBuilder = new ChronicleTextBuilder(workitem);
|
||||
promptTemplate = chronicleTextBuilder.build();
|
||||
workitem.setItemValue("ai.chronicle.summary", promptTemplate);
|
||||
indexDefinition.setItemValue("promptTemplate", embedTemplate(promptTemplate));
|
||||
|
||||
loadPromptDefinition(indexDefinition, event);
|
||||
|
||||
ragService.indexWorkitem(indexDefinition, workitem);
|
||||
}
|
||||
}
|
||||
} catch (AdapterException e) {
|
||||
throw new PluginException(e);
|
||||
}
|
||||
|
||||
return workitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates the item `order.history.ref` with the latest 5 orders for
|
||||
* the current customer
|
||||
*
|
||||
* @param workitem
|
||||
*/
|
||||
private void updateOrderHistory(ItemCollection workitem) {
|
||||
|
||||
workitem.removeItem("order.history.ref");
|
||||
String customerRef = workitem.getItemValueString("customer.ref");
|
||||
if (!customerRef.isEmpty()) {
|
||||
// append customer ref to $workitemref
|
||||
workitem.appendItemValueUnique("$workitemref", customerRef);
|
||||
|
||||
// collect all history orders....
|
||||
|
||||
String sQuery = "(";
|
||||
sQuery = " (type:\"workitem\" OR type:\"workitemarchive\") AND (" + LINK_PROPERTY + ":\"" + customerRef
|
||||
+ "\") AND ($workflowgroup:\"" + workitem.getWorkflowGroup() + "\")";
|
||||
|
||||
List<ItemCollection> orderHistory = null;
|
||||
try {
|
||||
orderHistory = workflowService.getDocumentService().findStubs(sQuery, MAX_HISTORY_RESULT, 0,
|
||||
WorkflowKernel.LASTEVENTDATE, true);
|
||||
} catch (QueryException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (orderHistory != null) {
|
||||
List<String> orderHistoryRefList = new ArrayList<>();
|
||||
for (ItemCollection order : orderHistory) {
|
||||
if (!workitem.getUniqueID().equals(order.getUniqueID())) { // skip current id!
|
||||
orderHistoryRefList.add(order.getUniqueID());
|
||||
}
|
||||
}
|
||||
workitem.setItemValue("order.history.ref", orderHistoryRefList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Embedds a prompt into a imixs prompt template
|
||||
*
|
||||
*
|
||||
* @param prompt
|
||||
* @return
|
||||
*/
|
||||
private String embedTemplate(String prompt) {
|
||||
|
||||
String template = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
|
||||
"<PromptDefinition>\n" + //
|
||||
" <prompt_options>{}</prompt_options>\n" + //
|
||||
" <prompt><![CDATA[";
|
||||
template = template + prompt;
|
||||
|
||||
template = template + "]]>\n" + //
|
||||
"</prompt>\n" + //
|
||||
"</PromptDefinition> ";
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
package ai.dynamixs.agent;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.ai.ImixsAIContextHandler;
|
||||
import org.imixs.ai.workflow.ImixsAIToolCallEvent;
|
||||
import org.imixs.ai.workflow.OpenAIAPIService;
|
||||
import org.imixs.workflow.exceptions.ModelException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.imixs.workflow.faces.data.WorkflowController;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.enterprise.event.Reception;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
|
||||
@Named("aiAgentController")
|
||||
@SessionScoped
|
||||
public class AIAgentController implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Logger logger = Logger.getLogger(AIAgentController.class.getName());
|
||||
|
||||
@Inject
|
||||
private OpenAIAPIService openAIAPIService;
|
||||
|
||||
@Inject
|
||||
private ImixsAIContextHandler contextHandler;
|
||||
|
||||
@Inject
|
||||
protected WorkflowController workflowController;
|
||||
|
||||
@Inject
|
||||
protected SkillController skillController;
|
||||
|
||||
private String userMessage;
|
||||
|
||||
private String agentResponse;
|
||||
private String redirectUrl;
|
||||
|
||||
private static final int MAX_ITERATIONS = 10; // prevent infinite loops
|
||||
|
||||
/**
|
||||
* Starts the conversation scope and initializes the context.
|
||||
*/
|
||||
public void init() {
|
||||
logger.info("├── Initialize AI Agent");
|
||||
redirectUrl = null;
|
||||
agentResponse = null;
|
||||
contextHandler.init();
|
||||
// Build system prompt with skill headers
|
||||
|
||||
try {
|
||||
contextHandler.addSystemMessage(
|
||||
"You are a workflow assistant in Imixs-Office-Workflow. " +
|
||||
"When a user wants to start a process, call start_process with the " +
|
||||
"matching modelversion and taskId from the list below.\n\n" +
|
||||
"Do NOT explain what you are doing. Just call the tool directly.\n\n" +
|
||||
skillController.getSkillHeaders());
|
||||
|
||||
// Register start_process function
|
||||
contextHandler.addFunction(
|
||||
"start_process",
|
||||
"Starts a BPMN workflow process for the user",
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$modelversion": {
|
||||
"type": "string",
|
||||
"description": "The model version of the process"
|
||||
},
|
||||
"$taskid": {
|
||||
"type": "integer",
|
||||
"description": "The task ID of the initial task"
|
||||
},
|
||||
"process.ref": {
|
||||
"type": "string",
|
||||
"description": "The unique ID referring of the process"
|
||||
}
|
||||
},
|
||||
"required": ["$modelversion", "$taskid", "process.ref"]
|
||||
}
|
||||
""");
|
||||
|
||||
} catch (PluginException e) {
|
||||
logger.warning("Failed to init AIAgent: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point for the frontend. Runs the agent loop and returns either a
|
||||
* text response or a redirect URL.
|
||||
*/
|
||||
public String startChat() throws PluginException {
|
||||
|
||||
init();
|
||||
|
||||
logger.info("├── Starting new chat");
|
||||
logger.info("│ ├── User Question: " + userMessage);
|
||||
contextHandler.addQuestion(userMessage, null, null);
|
||||
|
||||
// Agent Loop
|
||||
int iterations = 0;
|
||||
while (iterations < MAX_ITERATIONS) {
|
||||
iterations++;
|
||||
|
||||
String response = openAIAPIService.postPromptCompletion(
|
||||
contextHandler, null, true);
|
||||
|
||||
// Tool call? → processToolCallResult handles CDI events
|
||||
boolean wasToolCall = openAIAPIService.processToolCallResult(
|
||||
response, contextHandler);
|
||||
|
||||
if (!wasToolCall) {
|
||||
// Normal text response → done
|
||||
agentResponse = openAIAPIService.processPromptResult(
|
||||
response, null, null);
|
||||
return null; // stay on current page
|
||||
}
|
||||
|
||||
// Check if a tool call produced a redirect URL
|
||||
if (redirectUrl != null) {
|
||||
return redirectUrl; // JSF redirect
|
||||
}
|
||||
}
|
||||
|
||||
throw new PluginException(AIAgentController.class.getSimpleName(),
|
||||
"AGENT_LOOP_ERROR", "Max iterations reached!");
|
||||
}
|
||||
|
||||
public void onToolCall(@Observes(notifyObserver = Reception.IF_EXISTS) ImixsAIToolCallEvent event)
|
||||
throws PluginException {
|
||||
try {
|
||||
if ("start_process".equals(event.getToolName())) {
|
||||
String modelVersion = event.getArguments().getString("$modelversion");
|
||||
int taskId = event.getArguments().getInt("$taskid");
|
||||
String processRef = event.getArguments().getString("process.ref");
|
||||
|
||||
workflowController.create(modelVersion, taskId, processRef);
|
||||
|
||||
// Set redirect URL directly on this bean - startChat() will pick it up
|
||||
this.redirectUrl = "/pages/workitems/workitem.xhtml?id="
|
||||
+ workflowController.getWorkitem().getUniqueID()
|
||||
+ "&faces-redirect=true";
|
||||
|
||||
event.setResult("New Process started: " + workflowController.getWorkitem().getUniqueID());
|
||||
}
|
||||
} catch (ModelException e) {
|
||||
throw new PluginException(e.getErrorContext(), e.getErrorCode(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setRedirectUrl(String url) {
|
||||
this.redirectUrl = url;
|
||||
}
|
||||
|
||||
public String getUserMessage() {
|
||||
return userMessage;
|
||||
}
|
||||
|
||||
public void setUserMessage(String userMessage) {
|
||||
this.userMessage = userMessage;
|
||||
}
|
||||
|
||||
public String getAgentResponse() {
|
||||
return agentResponse;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
package ai.dynamixs.agent;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility class to convert HTML content into clean, LLM-friendly markup text.
|
||||
*/
|
||||
public class HtmlStripper {
|
||||
|
||||
// Precompiled patterns for performance
|
||||
private static final Pattern P_SCRIPT_STYLE = Pattern.compile(
|
||||
"<(script|style)[^>]*>[\\s\\S]*?</\\1>", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private static final Pattern P_HEADING = Pattern.compile(
|
||||
"<h[1-5][^>]*>(.*?)</h[1-5]>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
|
||||
private static final Pattern P_STRONG = Pattern.compile(
|
||||
"<(strong|b)[^>]*>(.*?)</(strong|b)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
|
||||
private static final Pattern P_EM = Pattern.compile(
|
||||
"<(em|i)[^>]*>(.*?)</(em|i)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
|
||||
private static final Pattern P_LI = Pattern.compile(
|
||||
"<li[^>]*>(.*?)</li>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
|
||||
private static final Pattern P_BLOCK = Pattern.compile(
|
||||
"<(p|div|br|tr|blockquote|pre|ul|ol|table)[^>]*/?>",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern P_CLOSE_BLOCK = Pattern.compile(
|
||||
"</(p|div|tr|blockquote|pre|ul|ol|table)>",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern P_TAGS = Pattern.compile("<[^>]+>");
|
||||
private static final Pattern P_MULTI_NEWLINE = Pattern.compile("\\n{3,}");
|
||||
private static final Pattern P_BLANK_LINE = Pattern.compile("(?m)^[ \\t]+$");
|
||||
|
||||
/**
|
||||
* Converts an HTML string into clean, LLM-readable markdown-style text. Handles
|
||||
* headings, bold/italic, lists, images, HTML entities and removes all remaining
|
||||
* tags. Designed to be minimal and allocation-efficient.
|
||||
*
|
||||
* @param content raw HTML input (may be null)
|
||||
* @return clean markup text, or empty string if input is null/blank
|
||||
*/
|
||||
public static String stripHtml(String content) {
|
||||
if (content == null || content.isBlank()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String s = content;
|
||||
|
||||
// 1. Normalize line endings
|
||||
s = s.replace("\r\n", "\n").replace("\r", "\n");
|
||||
|
||||
// 2. Remove script / style blocks entirely
|
||||
s = P_SCRIPT_STYLE.matcher(s).replaceAll("");
|
||||
|
||||
// 3. Images → [Image: alt] or drop silently
|
||||
// s = P_IMG.matcher(s).replaceAll("[Image: $1]");
|
||||
// s = P_IMG_NO_ALT.matcher(s).replaceAll("");
|
||||
|
||||
// 4. Headings → Markdown headings
|
||||
s = P_HEADING.matcher(s).replaceAll("\n**$1**\n");
|
||||
|
||||
// 5. Bold / Italic → Markdown
|
||||
s = P_STRONG.matcher(s).replaceAll("**$2**");
|
||||
s = P_EM.matcher(s).replaceAll("*$2*");
|
||||
|
||||
// 6. List items → Markdown bullets
|
||||
s = P_LI.matcher(s).replaceAll("\n- $1");
|
||||
|
||||
// 7. Block-level elements → newlines
|
||||
s = P_BLOCK.matcher(s).replaceAll("\n");
|
||||
s = P_CLOSE_BLOCK.matcher(s).replaceAll("\n");
|
||||
|
||||
// 8. Strip all remaining tags
|
||||
s = P_TAGS.matcher(s).replaceAll("");
|
||||
|
||||
// 9. Decode HTML entities
|
||||
s = decodeEntities(s);
|
||||
|
||||
// 10. Clean up whitespace
|
||||
s = P_BLANK_LINE.matcher(s).replaceAll("");
|
||||
s = P_MULTI_NEWLINE.matcher(s).replaceAll("\n\n");
|
||||
|
||||
return s.strip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes common named and numeric HTML entities. Covers the full ISO-8859-1 /
|
||||
* HTML4 named entity set plus numeric references.
|
||||
*/
|
||||
private static String decodeEntities(String s) {
|
||||
|
||||
// Use a simple regex-replace loop for correctness
|
||||
s = decodeNumericEntities(s);
|
||||
|
||||
// Named entities – most frequent ones in German/English business docs
|
||||
s = s
|
||||
.replace(" ", " ")
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace(""", "\"")
|
||||
.replace("'", "'")
|
||||
.replace("ä", "ä").replace("Ä", "Ä")
|
||||
.replace("ö", "ö").replace("Ö", "Ö")
|
||||
.replace("ü", "ü").replace("Ü", "Ü")
|
||||
.replace("ß", "ß")
|
||||
.replace("é", "é").replace("É", "É")
|
||||
.replace("è", "è").replace("È", "È")
|
||||
.replace("ê", "ê").replace("Ê", "Ê")
|
||||
.replace("à", "à").replace("À", "À")
|
||||
.replace("â", "â").replace("Â", "Â")
|
||||
.replace("ô", "ô").replace("Ô", "Ô")
|
||||
.replace("û", "û").replace("Û", "Û")
|
||||
.replace("ç", "ç").replace("Ç", "Ç")
|
||||
.replace("ñ", "ñ").replace("Ñ", "Ñ")
|
||||
.replace("©", "©")
|
||||
.replace("®", "®")
|
||||
.replace("™", "™")
|
||||
.replace("—", "—")
|
||||
.replace("–", "–")
|
||||
.replace("…", "…")
|
||||
.replace("«", "«").replace("»", "»")
|
||||
.replace("•", "•")
|
||||
.replace("€", "€");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static final Pattern P_DEC_ENTITY = Pattern.compile("&#(\\d+);");
|
||||
private static final Pattern P_HEX_ENTITY = Pattern.compile("&#x([0-9a-fA-F]+);");
|
||||
|
||||
/**
|
||||
* Replaces numeric HTML entities (decimal and hex) with their Unicode
|
||||
* characters.
|
||||
*/
|
||||
private static String decodeNumericEntities(String s) {
|
||||
// Hex
|
||||
var m = P_HEX_ENTITY.matcher(s);
|
||||
var sb = new StringBuilder(); // ← StringBuilder statt StringBuffer
|
||||
while (m.find()) {
|
||||
int cp = Integer.parseInt(m.group(1), 16);
|
||||
m.appendReplacement(sb, new String(Character.toChars(cp)));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
s = sb.toString();
|
||||
|
||||
// Decimal
|
||||
m = P_DEC_ENTITY.matcher(s);
|
||||
sb = new StringBuilder(); // ← StringBuilder
|
||||
while (m.find()) {
|
||||
int cp = Integer.parseInt(m.group(1));
|
||||
m.appendReplacement(sb, new String(Character.toChars(cp)));
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Imixs Workflow
|
||||
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public
|
||||
* License at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Project:
|
||||
* http://www.imixs.org
|
||||
* http://java.net/projects/imixs-workflow
|
||||
*
|
||||
* Contributors:
|
||||
* Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika - Software Developer
|
||||
*******************************************************************************/
|
||||
|
||||
package ai.dynamixs.agent;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import org.imixs.marty.team.TeamController;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.DocumentEvent;
|
||||
import org.imixs.workflow.office.model.ModelController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.ejb.SessionContext;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The SkillController is a CDI bean handling workflow skills from the current
|
||||
* process models.
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
@SessionScoped
|
||||
public class SkillController implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
TeamController teamController;
|
||||
|
||||
@Inject
|
||||
ModelController modelController;
|
||||
|
||||
@Resource
|
||||
SessionContext ctx;
|
||||
|
||||
String skillHeaders = null;
|
||||
|
||||
/**
|
||||
* This method refreshes the cache of skillHeaders
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public void onDocumentEvent(@Observes DocumentEvent event) {
|
||||
|
||||
String type = event.getDocument().getType();
|
||||
|
||||
if ((type.startsWith("process") || type.startsWith("model"))
|
||||
|
||||
&& (event.getEventType() == DocumentEvent.ON_DOCUMENT_SAVE
|
||||
|| event.getEventType() == DocumentEvent.ON_DOCUMENT_DELETE)) {
|
||||
|
||||
skillHeaders = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current skill headers. The method supports a lazy loading
|
||||
* mechanism.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getSkillHeaders() {
|
||||
loadSkillHeaders();
|
||||
return skillHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to load the skill headers for all available processes and
|
||||
* assigned workflows
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private void loadSkillHeaders() {
|
||||
if (skillHeaders == null) {
|
||||
StringBuilder skillHeaderBuilder = new StringBuilder();
|
||||
skillHeaderBuilder.append("Available Workflow Processes:\n\n");
|
||||
|
||||
List<ItemCollection> processList = teamController.getProcessList();
|
||||
|
||||
for (ItemCollection process : processList) {
|
||||
if (process.getTaskID() == 301 || teamController.isManagerOf(process.getUniqueID())) {
|
||||
|
||||
String processName = process.getItemValueString("name");
|
||||
String processDescription = HtmlStripper
|
||||
.stripHtml(process.getItemValueString("txtdescription"));
|
||||
|
||||
List<String> workflowList = process.getItemValueList("txtWorkflowList", String.class);
|
||||
|
||||
// Collect workflow entries first - skip process if none found
|
||||
StringBuilder workflowEntries = new StringBuilder();
|
||||
for (String group : workflowList) {
|
||||
String modelVersion = modelController.getVersionByGroup(group);
|
||||
List<ItemCollection> startTasks = modelController.findAllStartTasksByGroup(modelVersion, group);
|
||||
if (!startTasks.isEmpty()) {
|
||||
ItemCollection initialTask = startTasks.get(0);
|
||||
int taskId = initialTask.getItemValueInteger("taskid");
|
||||
String taskDescription = HtmlStripper.stripHtml(
|
||||
modelController.getProcessDescriptionByInitialTask(initialTask, modelVersion,
|
||||
group));
|
||||
|
||||
workflowEntries.append("- ").append(group).append(": ");
|
||||
if (taskDescription != null && !taskDescription.isBlank()) {
|
||||
workflowEntries.append(taskDescription);
|
||||
} else if (processDescription != null && !processDescription.isBlank()) {
|
||||
workflowEntries.append(processDescription);
|
||||
}
|
||||
workflowEntries.append(" (model: ").append(modelVersion)
|
||||
.append(", taskid: ").append(taskId)
|
||||
.append(", process.ref: ").append(process.getUniqueID())
|
||||
.append(")\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Only add process section if it has at least one workflow
|
||||
if (workflowEntries.length() > 0) {
|
||||
skillHeaderBuilder.append("[").append(processName).append("]");
|
||||
if (processDescription != null && !processDescription.isBlank()) {
|
||||
skillHeaderBuilder.append(" - ").append(processDescription);
|
||||
}
|
||||
skillHeaderBuilder.append("\n");
|
||||
skillHeaderBuilder.append(workflowEntries);
|
||||
skillHeaderBuilder.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
skillHeaders = skillHeaderBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Manifest-Version: 1.0
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<!--
|
||||
Imixs JPA definition Make sure that the imixs-workflow-jee library
|
||||
version maches the version provided by the EAR/EJB
|
||||
-->
|
||||
<!-- eclipselink -->
|
||||
<persistence-unit name="org.imixs.workflow.jpa" transaction-type="JTA">
|
||||
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
|
||||
<jta-data-source>${imixs-office.jta-data-source}</jta-data-source>
|
||||
<jar-file>lib/imixs-workflow-engine-${org.imixs.workflow.version}.jar</jar-file>
|
||||
<jar-file>lib/imixs-marty-${org.imixs.marty.version}.jar</jar-file>
|
||||
<properties>
|
||||
<!-- target-database Auto MySQL PostgreSQL -->
|
||||
<property name="eclipselink.target-database" value="Auto" />
|
||||
<property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
|
||||
<property name="eclipselink.deploy-on-startup" value="true" />
|
||||
<property name="eclipselink.logging.level" value="INFO" />
|
||||
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
</persistence>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
# Build Information
|
||||
build.version=${project.version}
|
||||
build.timestamp=${org.imixs.build.timestamp}
|
||||
build.office.version=${org.imixs.office.version}
|
||||
build.marty.version=${org.imixs.marty.version}
|
||||
build.workflow.version=${org.imixs.workflow.version}
|
||||
build.name=${imixs-office.applicationname}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
##############################
|
||||
# Imixs-Workflow
|
||||
##############################
|
||||
model.default.data=system-de-1.3.0.bpmn
|
||||
lucence.indexDir=${imixs-office.IndexDir}
|
||||
index.fields=txtsearchstring,txtSubject,txtname,txtEmail,txtUserName,namCreator,txtworkflowgroup,txtworkflowstatus,txtWorkflowAbstract,txtWorkflowSummary,txtworkflowhistory,txtspacename,txtprocessname,_subject,_description,_name,_projectnumber,_projectname,_ordernumber,_contractnumber,datDueDate,txtcommentlog,htmldescription,htmldocumentation,_childitems
|
||||
index.fields.analyze=txtUsername
|
||||
index.fields.noanalyze=type,$UniqueIDRef,$created,$modified,$ModelVersion,namCreator,$ProcessID,datDate,txtWorkflowGroup,txtemail, datdate, datfrom, datto, numsequencenumber,dms_count,
|
||||
index.fields.store=process.name,txtProcessName,txtWorkflowImageURL
|
||||
index.fields.category=space.name,space.ref
|
||||
|
||||
##############################
|
||||
# Model Setup
|
||||
##############################
|
||||
setup.system.model=system-de-1.3
|
||||
|
||||
# Office Properties
|
||||
BASIC.maxviewentries=10
|
||||
|
||||
##############################
|
||||
# Marty Security
|
||||
##############################
|
||||
security.setup.mode=auto
|
||||
security.userid.input.mode=LOWERCASE
|
||||
security.email.unique=true
|
||||
#security.userid.input.pattern=
|
||||
|
||||
|
||||
# Profile - autoprocess event
|
||||
profile.login.event=100
|
||||
|
||||
# Marty Mail Plugin
|
||||
# mail.defaultSender=info@imixs.com
|
||||
|
||||
|
||||
# Image reziser
|
||||
image.fileExtension=jpg,gif
|
||||
image.maxWidth=2048
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
dms.search=true
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
|
||||
bean-discovery-mode="all" version="3.0">
|
||||
</beans>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
|
||||
version="2.2">
|
||||
|
||||
|
||||
|
||||
</faces-config>
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||
version="6.0">
|
||||
<display-name>imixs-office-workflow</display-name>
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.xhtml</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<!-- -->
|
||||
<context-param>
|
||||
<param-name>jakarta.faces.STATE_SAVING_METHOD</param-name>
|
||||
<param-value>server</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>jakarta.faces.CONFIG_FILES</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/faces-config-office.xml,
|
||||
/WEB-INF/faces-config-custom.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<!-- project stage is computed by the maven profile settings -->
|
||||
<context-param>
|
||||
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
|
||||
<param-value>Production</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- Session Timeout 180 = 3h -->
|
||||
<session-config>
|
||||
<session-timeout>60</session-timeout>
|
||||
</session-config>
|
||||
|
||||
|
||||
<!-- Facelets -->
|
||||
<servlet>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
|
||||
<load-on-startup>0</load-on-startup>
|
||||
<multipart-config>
|
||||
<location>/tmp</location>
|
||||
<!-- 20MB (20848820) *2MB (2097152)-->
|
||||
<max-file-size>2097152</max-file-size>
|
||||
<!-- 400MB (418018841) *20MB (20848820)-->
|
||||
<max-request-size>20848820</max-request-size>
|
||||
<file-size-threshold>1048576</file-size-threshold>
|
||||
</multipart-config>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<url-pattern>*.jsf</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<url-pattern>*.xhtml</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<!-- Error handling -->
|
||||
<error-page>
|
||||
<error-code>401</error-code>
|
||||
<location>/loginerror.jsf</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>403</error-code>
|
||||
<location>/authorizationerror.html</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>404</error-code>
|
||||
<location>/error.jsf</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>500</error-code>
|
||||
<location>/error.jsf</location>
|
||||
</error-page>
|
||||
|
||||
|
||||
<!-- Login Modul - Form-Login -->
|
||||
<login-config>
|
||||
<auth-method>FORM</auth-method>
|
||||
<realm-name>imixsrealm</realm-name>
|
||||
<form-login-config>
|
||||
<form-login-page>/login.jsf</form-login-page>
|
||||
<form-error-page>/loginerror.jsf</form-error-page>
|
||||
</form-login-config>
|
||||
</login-config>
|
||||
|
||||
<!-- Wildfly OIDC Login Module
|
||||
Note: WEB-INF/oidc.yaml file is mandatory!
|
||||
|
||||
<login-config>
|
||||
<auth-method>OIDC</auth-method>
|
||||
</login-config>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Security Roles -->
|
||||
<security-constraint>
|
||||
<display-name>Access Manager Security Constraint</display-name>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>AUTHENTICATED_RESOURCE</web-resource-name>
|
||||
<url-pattern>/pages/*</url-pattern>
|
||||
<url-pattern>/api/workflow/*</url-pattern>
|
||||
<url-pattern>/api/model/*</url-pattern>
|
||||
<url-pattern>/api/documents/*</url-pattern>
|
||||
<url-pattern>/api/report/*</url-pattern>
|
||||
<url-pattern>/api/snapshot/*</url-pattern>
|
||||
<url-pattern>/api/adminp/*</url-pattern>
|
||||
<url-pattern>/api/eventlog/*</url-pattern>
|
||||
<url-pattern>/api/logout</url-pattern>
|
||||
<!-- exclude /api/metrics and /api/wopi -->
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
|
||||
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
|
||||
<role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
|
||||
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>AUTHENTICATED_ADMIN_RESOURCE</web-resource-name>
|
||||
<url-pattern>/pages/admin/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-role>
|
||||
<role-name>org.imixs.ACCESSLEVEL.NOACCESS</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// custom scripts
|
||||
|
||||
/**
|
||||
* This method renders $workflowabstarct as markup
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
|
||||
});
|
||||
|
||||
function showTooltip(trigger) {
|
||||
const tooltip = trigger.nextElementSibling;
|
||||
const rect = trigger.getBoundingClientRect();
|
||||
|
||||
// Position relativ zum Viewport berechnen
|
||||
tooltip.style.left = rect.left + 'px';
|
||||
tooltip.style.top = (rect.bottom + 5) + 'px';
|
||||
|
||||
|
||||
// Markdown nur einmal parsen (lazy loading)
|
||||
const markdownContainer = tooltip.querySelector('.imixs-workflowabstract');
|
||||
if (markdownContainer && !markdownContainer.dataset.parsed) {
|
||||
const rawMarkdown = markdownContainer.textContent;
|
||||
markdownContainer.innerHTML = marked.parse(rawMarkdown);
|
||||
markdownContainer.dataset.parsed = 'true'; // Flag setzen
|
||||
}
|
||||
|
||||
|
||||
tooltip.classList.add('visible');
|
||||
|
||||
// Optional: Prüfen ob Tooltip aus dem Viewport ragt
|
||||
const tooltipRect = tooltip.getBoundingClientRect();
|
||||
if (tooltipRect.right > window.innerWidth) {
|
||||
tooltip.style.left = (window.innerWidth - tooltipRect.width - 10) + 'px';
|
||||
}
|
||||
if (tooltipRect.bottom > window.innerHeight) {
|
||||
tooltip.style.top = (rect.top - tooltipRect.height - 5) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
function hideTooltip(trigger) {
|
||||
const tooltip = trigger.nextElementSibling;
|
||||
tooltip.classList.remove('visible');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to trigger the workflowabstract element in the form
|
||||
* @param {} trigger
|
||||
*/
|
||||
function toggleWorkflowAbstract(trigger) {
|
||||
const content = trigger.nextElementSibling;
|
||||
|
||||
|
||||
|
||||
// Markdown nur einmal parsen (lazy loading)
|
||||
const markdownContainer = content.querySelector('.imixs-markdown-output');
|
||||
if (markdownContainer && !markdownContainer.dataset.parsed) {
|
||||
const rawMarkdown = markdownContainer.textContent;
|
||||
markdownContainer.innerHTML = marked.parse(rawMarkdown);
|
||||
markdownContainer.dataset.parsed = 'true';
|
||||
}
|
||||
|
||||
content.classList.toggle('hidden');
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/* --- Custom Layout --- */
|
||||
|
||||
#imixs-header {
|
||||
background-color: #599191;
|
||||
}
|
||||
|
||||
#imixs-branding {
|
||||
background-color: #599191;
|
||||
background-image: url("./logo-01.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 10px 15px;
|
||||
background-size: 140px;
|
||||
min-height: 120px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default, .ui-button, html .ui-button.ui-state-disabled:hover, html .ui-button.ui-state-disabled:active {
|
||||
border: 1px solid #599191;
|
||||
background: #599191;
|
||||
|
||||
}
|
||||
|
||||
.imixsfileupload input[type="file"] + label {
|
||||
background-color: #599191;
|
||||
}
|
||||
.imixsfileupload input[type="file"] + label:hover {
|
||||
background-color: #62a2a2;
|
||||
}
|
||||
|
||||
.ui-button:hover {
|
||||
background: #62a2a2;
|
||||
|
||||
}
|
||||
|
||||
.imixs-workitem-chronicle-tabs ul li.active a {
|
||||
color: #599191;
|
||||
}
|
||||
|
||||
.imixsdatatable th {
|
||||
background: #599191;
|
||||
color: #fff;
|
||||
border-left: 4px solid #599191;
|
||||
border-bottom: 1px solid #599191;
|
||||
}
|
||||
|
||||
|
||||
.imixs-llm, .imixs-llm:focus, .imixs-date.imixs-llm, .imixs-date.imixs-llm:focus {
|
||||
border: none !important;
|
||||
border-bottom: 2px solid #faa732 !important;
|
||||
box-shadow: none !important;
|
||||
text-align: left !important;
|
||||
border-radius: 0;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Neues Abstract markup */
|
||||
.tooltip-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip-trigger {
|
||||
cursor: pointer;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.tooltip-content {
|
||||
display: none;
|
||||
position: fixed;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.75;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
z-index: 1200;
|
||||
background: white;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
|
||||
min-width: 420px;
|
||||
max-width: 650px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
|
||||
|
||||
background-color: #ffffff;
|
||||
|
||||
padding: 10px;
|
||||
transition: opacity 0.5s ease-in-out, visibility 0.3s ease-in-out;
|
||||
|
||||
}
|
||||
|
||||
.tooltip-container:hover .tooltip-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.imixs-workflowabstract-toggle-icon {
|
||||
margin-left: auto;
|
||||
align-self: flex-end;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
font-size: 1.25rem;
|
||||
color: #599191;
|
||||
}
|
||||
|
||||
.imixs-workflowabstract-content {
|
||||
flex-basis: 100%;
|
||||
padding: 0 15px;
|
||||
border: 1px solid #599191;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -1,15 +0,0 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
|
||||
xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
|
||||
|
||||
<f:view>
|
||||
<div class="toolbar agent">
|
||||
<h:inputText a:data-id="nav_input_phrase" style="margin-right: 10px;" a:placeholder="What do you need?"
|
||||
value="#{aiAgentController.userMessage}" />
|
||||
<h:commandLink action="#{aiAgentController.startChat()}" a:data-id="nav_search_link"><span
|
||||
class="typcn typcn-lightbulb" style="font-size:1.4em;"></span>
|
||||
</h:commandLink>
|
||||
</div>
|
||||
</f:view>
|
||||
</ui:composition>
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
|
||||
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions" xmlns:marty="http://xmlns.jcp.org/jsf/composite/marty"
|
||||
xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
|
||||
|
||||
<!-- Build with link ? -->
|
||||
|
||||
|
||||
<span class="imixs-icon tooltip-container" title=" ">
|
||||
<span class="tooltip-trigger" onmouseenter="showTooltip(this)" onmouseleave="hideTooltip(this)">
|
||||
<ui:fragment rendered="#{showlink}">
|
||||
<h:link outcome="/pages/workitems/workitem">
|
||||
<!-- typcn -->
|
||||
<ui:fragment rendered="#{fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
|
||||
<span class="imixs-typicon" data-typicon="#{workitem.item['txtWorkflowImageURL']}"></span>
|
||||
</ui:fragment>
|
||||
<!-- Image -->
|
||||
<ui:fragment rendered="#{!fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
|
||||
<h:graphicImage rendered="#{!empty workitem.item['txtWorkflowImageURL']}"
|
||||
url="#{workitem.item['txtWorkflowImageURL']}" style="max-height: 24px; margin: 4px;">
|
||||
</h:graphicImage>
|
||||
<h:graphicImage rendered="#{empty workitem.item['txtWorkflowImageURL']}"
|
||||
value="/layout/icons/vwicn070.png" style="max-height: 24px; margin: 4px;"></h:graphicImage>
|
||||
</ui:fragment>
|
||||
<f:param name="id" value="#{workitem.item['$uniqueid']}" />
|
||||
</h:link>
|
||||
</ui:fragment>
|
||||
<!-- Build without link -->
|
||||
<ui:fragment rendered="#{!showlink}">
|
||||
<!-- typcn -->
|
||||
<ui:fragment rendered="#{fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
|
||||
<span class="imixs-typicon" data-typicon="#{workitem.item['txtWorkflowImageURL']}"></span>
|
||||
</ui:fragment>
|
||||
<!-- Image -->
|
||||
<ui:fragment rendered="#{!fn:startsWith(workitem.item['txtWorkflowImageURL'],'typcn')}">
|
||||
<h:graphicImage rendered="#{!empty workitem.item['txtWorkflowImageURL']}"
|
||||
url="#{workitem.item['txtWorkflowImageURL']}" style="max-height: 24px; margin: 4px;">
|
||||
</h:graphicImage>
|
||||
<h:graphicImage rendered="#{empty workitem.item['txtWorkflowImageURL']}"
|
||||
value="/layout/icons/vwicn070.png" style="max-height: 24px; margin: 4px;"></h:graphicImage>
|
||||
</ui:fragment>
|
||||
</ui:fragment>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h:panelGroup class="tooltip-content">
|
||||
<h:outputText value="#{message.created}: " style="font-weight:bold;" />
|
||||
<h:outputText value="#{workitem.item['$created']}">
|
||||
<f:convertDateTime timeZone="#{message.timeZone}" type="both" pattern="#{message.dateTimePattern}" />
|
||||
</h:outputText>
|
||||
<h:outputText value=" #{message.by} #{userController.getUserName(workitem.item['$creator'])}" />
|
||||
|
||||
<!-- Modified -->
|
||||
<br />
|
||||
<span>
|
||||
<h:outputText style="font-weight: bold;" value="#{message.edited}: " />
|
||||
<h:outputText value="#{workitem.item['$lasteventdate']}" style="font-weight: normal;">
|
||||
<f:convertDateTime timeZone="#{message.timeZone}" pattern="#{message.dateTimePattern}" />
|
||||
</h:outputText>
|
||||
<h:outputText value=" #{message.by} #{userController.getUserName(workitem.item['$editor'])}" />
|
||||
</span>
|
||||
<hr />
|
||||
<!-- Markup -->
|
||||
<div class="imixs-workflowabstract">
|
||||
|
||||
<h:outputText styleClass="imixs-markdown-output" value="#{workitem.item['$WorkflowAbstract']}"
|
||||
escape="false" />
|
||||
</div>
|
||||
</h:panelGroup>
|
||||
|
||||
|
||||
|
||||
</span>
|
||||
|
||||
</ui:composition>
|
||||
|
|
@ -1,317 +0,0 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:i="http://java.sun.com/jsf/composite/imixs" xmlns:c="http://java.sun.com/jsp/jstl/core"
|
||||
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
|
||||
xmlns:marty="http://java.sun.com/jsf/composite/marty" template="/layout/template.xhtml">
|
||||
|
||||
<ui:define name="content">
|
||||
<f:view>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function () {
|
||||
//$('.imixsdatatable').layoutImixsTable();
|
||||
});
|
||||
|
||||
|
||||
// This method refreshs the layout
|
||||
function updateOptions(data) {
|
||||
if (data.status === 'success') {
|
||||
$('[id$=Optionlist]').imixsLayout();
|
||||
|
||||
/* var id='#'+data.source.id;
|
||||
if (id.indexOf("input")>-1) {
|
||||
$(id).focus();
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
|
||||
<h:form id="import_form_id">
|
||||
<!-- ########## Error ########## -->
|
||||
<ui:include src="/error_message.xhtml" />
|
||||
|
||||
<div class="imixs-form">
|
||||
<div class="imixs-header">
|
||||
<h1>Document Importer</h1>
|
||||
</div>
|
||||
<div class="imixs-body">
|
||||
<div class="imixs-tabs">
|
||||
<ul>
|
||||
<li><a href="#tab-1">Timer Setting</a></li>
|
||||
<li><a href="#tab-2">Data Sources</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- ### Timer ### -->
|
||||
<div id="tab-1">
|
||||
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<p><span class="typcn typcn-lightbulb"></span> Define a crontab to schedule the
|
||||
import processor.</p>
|
||||
</div>
|
||||
<ui:include src="sub_scheduler_control.xhtml">
|
||||
<ui:param name="schedulerController" value="#{documentImportController}" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<!-- ### SMTP ### -->
|
||||
<div id="tab-2">
|
||||
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<p><span class="typcn typcn-lightbulb"></span> Define a destination IMAP server and
|
||||
assign mail addresses to specific workflow groups.</p>
|
||||
</div>
|
||||
<div class="imixs-form-panel">
|
||||
|
||||
<!-- ### Sources ### -->
|
||||
<h:panelGroup layout="block" id="imapOptionlist"
|
||||
binding="#{imapOptionlistContainer}">
|
||||
<f:ajax onevent="updateOptions">
|
||||
<table class="imixsdatatable" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10px;text-align: center;">Pos</th>
|
||||
<th style="width: 100px;text-align: center;">Type</th>
|
||||
<th style="">Workflowgroup</th>
|
||||
<th style="">Modelversion</th>
|
||||
<th style="">Task</th>
|
||||
<th style="">Event</th>
|
||||
<th style="width: 110px;">
|
||||
<!-- delete -->
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<ui:repeat var="source" value="#{documentImportController.sources}">
|
||||
|
||||
<tr>
|
||||
<!-- pos -->
|
||||
<td style=" text-align: center;">
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.selectSource(source.item['index'])}">
|
||||
#
|
||||
<h:outputText value="#{source.item['index']}" />
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
</td>
|
||||
|
||||
<!-- type -->
|
||||
<td style="text-align: center;">
|
||||
<h:outputText value="#{source.item['type']}" />
|
||||
</td>
|
||||
<!-- Workflowgroup -->
|
||||
<td>
|
||||
<h:outputText value="#{source.item['workflowgroup']}" />
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<h:outputText value="#{source.item['workflowmodel']}" />
|
||||
</td>
|
||||
<td>
|
||||
<h:outputText value="#{source.item['task']}" />
|
||||
</td>
|
||||
<td>
|
||||
<h:outputText value="#{source.item['event']}" />
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.moveSourceDown(source.item['index'])}">
|
||||
<span
|
||||
class="typcn typcn-arrow-down-thick imixs-state-info"></span>
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.moveSourceUp(source.item['index'])}">
|
||||
<span
|
||||
class="typcn typcn-arrow-up-thick imixs-state-info"></span>
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.removeSource(source.item['index'])}">
|
||||
<span
|
||||
class="typcn typcn-trash imixs-state-info"></span>
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</ui:repeat>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<!-- add button -->
|
||||
<h:commandButton value="#{message.add}"
|
||||
actionListener="#{documentImportController.addSource()}">
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandButton>
|
||||
|
||||
|
||||
|
||||
<!-- ### Subform for selected source ### -->
|
||||
|
||||
<h:panelGroup layout="block"
|
||||
rendered="#{! empty documentImportController.source}"
|
||||
styleClass="imixs-form-panel">
|
||||
<h3>Order ID #
|
||||
<h:outputText
|
||||
value="#{documentImportController.source.item['index']}" />
|
||||
</h3>
|
||||
<div class="imixs-form-section-3">
|
||||
<dl>
|
||||
<dt>Type</dt>
|
||||
<dd>
|
||||
<h:selectOneRadio
|
||||
value="#{documentImportController.source.item['type']}">
|
||||
<f:selectItem itemLabel="IMAP" itemValue="IMAP" />
|
||||
<f:selectItem itemLabel="FTP" itemValue="FTP" />
|
||||
<f:selectItem itemLabel="CSV" itemValue="CSV" />
|
||||
</h:selectOneRadio>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Workflowgroup</dt>
|
||||
<dd>
|
||||
<h:selectOneMenu
|
||||
value="#{documentImportController.source.item['workflowgroup']}">
|
||||
<f:selectItem itemLabel=" - " itemValue="" />
|
||||
<c:forEach items="#{modelController.workflowGroups}"
|
||||
var="group">
|
||||
<f:selectItem itemLabel="#{group}"
|
||||
itemValue="#{group}" />
|
||||
</c:forEach>
|
||||
</h:selectOneMenu>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="imixs-form-section-3">
|
||||
|
||||
<dl>
|
||||
<dt>Workflowmodel</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{documentImportController.source.item['workflowmodel']}" />
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Task ID</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{documentImportController.source.item['task']}" />
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Event ID</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{documentImportController.source.item['event']}" />
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<!-- IMAP -->
|
||||
<div class="imixs-form-section-3">
|
||||
<dl>
|
||||
<dt>Server : Port</dt>
|
||||
<dd>
|
||||
<h:inputText style="width:80%;"
|
||||
value="#{documentImportController.source.item['server']}">
|
||||
</h:inputText> : <h:inputText style="width:15%;"
|
||||
value="#{documentImportController.source.item['port']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>User</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{documentImportController.source.item['user']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Password</dt>
|
||||
<dd>
|
||||
<h:inputSecret required="false" redisplay="true"
|
||||
value="#{documentImportController.source.item['password']}">
|
||||
</h:inputSecret>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="imixs-form-section">
|
||||
<dl>
|
||||
<dt>Selector</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{documentImportController.source.item['selector']}">
|
||||
</h:inputText>
|
||||
<p class="small">A selector can be an optional regular
|
||||
expression to be used to select a subset of data</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Options</dt>
|
||||
<dd>
|
||||
<h:inputTextarea required="false"
|
||||
style="height: 5em; width: 100%;"
|
||||
value="#{documentImportController.source.item['options']}">
|
||||
</h:inputTextarea>
|
||||
<p class="small">You can apply custom properties here.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</h:panelGroup> <!-- end of source subform -->
|
||||
</f:ajax>
|
||||
</h:panelGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="imixs-footer">
|
||||
<h:outputLabel value="#{message.modified}: " />
|
||||
<h:outputText value="#{documentImportController.configuration.item['$modified']}">
|
||||
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
|
||||
pattern="#{message.dateTimePattern}" />
|
||||
</h:outputText>
|
||||
<br />
|
||||
<h:commandButton actionListener="#{documentImportController.saveConfiguration()}"
|
||||
action="/pages/admin/document_import" value="#{message.save}">
|
||||
</h:commandButton>
|
||||
<h:commandButton value="#{message.close}" action="notes" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</h:form>
|
||||
</f:view>
|
||||
</ui:define>
|
||||
|
||||
|
||||
|
||||
</ui:composition>
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
|
||||
xmlns:marty="http://xmlns.jcp.org/jsf/composite/marty" xmlns:i="http://xmlns.jcp.org/jsf/composite/imixs">
|
||||
|
||||
<div style="display: flex;">
|
||||
<div style="flex:1;">
|
||||
<h1>
|
||||
<h:outputText value="#{workflowController.workitem.item['$workflowgroup']}" />
|
||||
»
|
||||
<h:outputText value=" #{workflowController.workitem.item['$workflowstatus']}" />
|
||||
<!-- Display Deleted status -->
|
||||
<h:outputText rendered="#{workflowController.workitem.item['type'] eq 'workitemdeleted'}"
|
||||
value="- #{message.deleted}!" style="color:red;" />
|
||||
</h1>
|
||||
|
||||
|
||||
<!-- Workitem Info Header -->
|
||||
<div class="imixs-form-header">
|
||||
<!-- *** Image *** -->
|
||||
<div class="image-block">
|
||||
<ui:include src="/layout/workitem_icon.xhtml">
|
||||
<ui:param name="workitem" value="#{workflowController.workitem}" />
|
||||
<ui:param name="hidetooltip" value="#{true}" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<ui:remove><!-- *** Standard Info *** --></ui:remove>
|
||||
<div class="content-block">
|
||||
<h2>
|
||||
<h:outputText escape="false"
|
||||
rendered="#{empty workflowController.workitem.item['$WorkflowSummary']}"
|
||||
value="#{message.new_workitem}" />
|
||||
<h:outputText escape="false"
|
||||
rendered="#{!empty workflowController.workitem.item['$WorkflowSummary']}"
|
||||
value="#{workflowController.workitem.item['$WorkflowSummary']}" />
|
||||
</h2>
|
||||
<h:outputLabel value="#{message['process.title']}: " />
|
||||
<h:link outcome="/pages/notes_board?processref=#{workflowController.workitem.item['process.Ref']}">
|
||||
<h:outputText value="#{workflowController.workitem.item['Process.Name']}" />
|
||||
</h:link>
|
||||
|
||||
<ui:remove><!-- *** Owners *** --></ui:remove>
|
||||
<h:panelGroup styleClass="imixs-no-print" layout="block">
|
||||
<ui:repeat value="#{workflowController.workitem.itemList['$owner']}" var="name">
|
||||
|
||||
<ui:param name="profile" value="#{userController.getProfile(name)}"></ui:param>
|
||||
<ui:fragment rendered="#{! empty profile}">
|
||||
<h:graphicImage styleClass="imixs-workitem-chronicle-usericon"
|
||||
title="#{profile.item['txtusername']}"
|
||||
rendered="#{! empty profile.item['txtusericon']}"
|
||||
value="/api/snapshot/#{profile.item['$uniqueid']}/file/#{profile.item['txtusericon']}">
|
||||
</h:graphicImage>
|
||||
|
||||
<!-- optional - user initials -->
|
||||
<h:panelGroup layout="block" rendered="#{empty profile.item['txtusericon']}">
|
||||
<h:outputText styleClass="imixs-workitem-chronicle-usericon"
|
||||
title="#{profile.item['txtusername']}" value="#{profile.item['txtinitials']}" />
|
||||
</h:panelGroup>
|
||||
</ui:fragment>
|
||||
</ui:repeat>
|
||||
</h:panelGroup>
|
||||
</div>
|
||||
|
||||
<!-- *** Comment Toggle *** -->
|
||||
<div class="imixs-workflowabstract-toggle-icon" onclick="toggleWorkflowAbstract(this)">
|
||||
<i class="fa-regular fa-comment-dots"></i>
|
||||
</div>
|
||||
|
||||
<!-- Extra Content - volle Breite -->
|
||||
<div class="imixs-workflowabstract-content hidden">
|
||||
<h:outputText styleClass="imixs-markdown-output"
|
||||
rendered="#{workflowController.workitem.taskID eq 1210}"
|
||||
value="#{indexController.getContent(workflowController.workitem.uniqueID, 'CSDDD')}"
|
||||
escape="false" />
|
||||
<h:outputText styleClass="imixs-markdown-output"
|
||||
rendered="#{workflowController.workitem.taskID ne 1210}"
|
||||
value="#{indexController.getContent(workflowController.workitem.uniqueID, '')}"
|
||||
escape="false" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- QR-Code displayed only if property 'qr-code.url.prafix' is filled -->
|
||||
<ui:param name=" qrprafix" value="#{propertyController.getProperty('qr-code.url.prafix')}">
|
||||
</ui:param>
|
||||
<ui:fragment
|
||||
rendered="#{(! empty workflowController.workitem.uniqueID) and (!userController.mobileUser) and (!empty qrprafix)}">
|
||||
<div style="flex-grow: 1;"></div>
|
||||
<div>
|
||||
<a href="#" onclick="imixsOfficeWorkitem.printQRCode();">
|
||||
<h:graphicImage styleClass="imixsQrCode"
|
||||
url="/api/qr-code?size=130&key=#{qrprafix}#{workflowController.workitem.uniqueID}">
|
||||
</h:graphicImage>
|
||||
</a>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</ui:composition>
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
/****************************************************************************
|
||||
* Copyright (c) 2022-2025 Imixs Software Solutions GmbH and others.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* This Source Code may also be made available under the terms of the
|
||||
* GNU General Public License, version 2 or later (GPL-2.0-or-later),
|
||||
* which is available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
****************************************************************************/
|
||||
|
||||
package ai.dynamixs.agent;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.imixs.ai.ImixsAIContextHandler;
|
||||
import org.imixs.ai.workflow.OpenAIAPIConnector;
|
||||
import org.imixs.ai.workflow.OpenAIAPIService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/**
|
||||
* Test class to test a function call
|
||||
*
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class TestAgentCall {
|
||||
|
||||
private static final String MISTRAL_ENDPOINT = "https://api.llama.cpp.imixs.com/";
|
||||
public static final String MISTRAL_API_KEY = "7fdb663fa87ea16731c1e0ece8ad3214e358423eabf2403188110c731ce07321";
|
||||
|
||||
private OpenAIAPIService service;
|
||||
private OpenAIAPIConnector connector;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
connector = new OpenAIAPIConnector();
|
||||
connector.setServiceEndpointApiKey(Optional.of(MISTRAL_API_KEY));
|
||||
connector.setServiceEndpointUser(Optional.empty());
|
||||
connector.setServiceEndpointPassword(Optional.empty());
|
||||
injectField(connector, "serviceTimeout", 30000);
|
||||
injectField(connector, "serviceEndpoint", Optional.of(MISTRAL_ENDPOINT));
|
||||
|
||||
service = new OpenAIAPIService();
|
||||
injectField(service, "openAIAPIConnector", connector);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHelloWorld() throws Exception {
|
||||
// Build a simple "Hello World" prompt
|
||||
ImixsAIContextHandler contextHandler = new ImixsAIContextHandler();
|
||||
contextHandler.addQuestion("Say hello world!", null, null);
|
||||
|
||||
String response = service.postPromptCompletion(contextHandler, MISTRAL_ENDPOINT, true);
|
||||
|
||||
assertNotNull(response);
|
||||
System.out.println("Response: " + response);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFunctionCalling() throws Exception {
|
||||
ImixsAIContextHandler contextHandler = new ImixsAIContextHandler();
|
||||
|
||||
// Define system context
|
||||
contextHandler.addSystemMessage("""
|
||||
You are a workflow assistant integrated into the Imixs-Office-Workflow suite.
|
||||
The following BPMN processes are available:
|
||||
- urlaubsantrag: Vacation request process
|
||||
- reisekostenabrechnung: Travel expense process
|
||||
- eingangsrechnung: Incoming invoice process
|
||||
|
||||
When a user wants to start a process, always call the load_skill tool
|
||||
with the matching process_id. Never ask the user for the process ID.
|
||||
""");
|
||||
|
||||
// Define the load_skill function
|
||||
contextHandler.addFunction(
|
||||
"load_skill",
|
||||
"Loads details about an available BPMN workflow process",
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"process_id": {
|
||||
"type": "string",
|
||||
"description": "The ID of the BPMN process, e.g. urlaubsantrag"
|
||||
}
|
||||
},
|
||||
"required": ["process_id"]
|
||||
}
|
||||
""");
|
||||
|
||||
contextHandler.addQuestion(
|
||||
"I need next week off. Can you start the vacation request process?",
|
||||
"tom.clancy", new Date());
|
||||
|
||||
// Print the full request JSON to verify it looks correct
|
||||
System.out.println("Request: " + contextHandler.toString());
|
||||
|
||||
String response = service.postPromptCompletion(contextHandler, MISTRAL_ENDPOINT, true);
|
||||
assertNotNull(response);
|
||||
System.out.println("Response: " + response);
|
||||
|
||||
// Check if Mistral responded with a tool call
|
||||
assertTrue(response.contains("load_skill"),
|
||||
"Expected Mistral to call load_skill tool");
|
||||
|
||||
// Verify Mistral responded with a tool call
|
||||
assertTrue(response.contains("\"finish_reason\":\"tool_calls\""));
|
||||
assertTrue(response.contains("\"name\":\"load_skill\""));
|
||||
assertTrue(response.contains("urlaubsantrag"));
|
||||
}
|
||||
|
||||
private void injectField(Object target, String fieldName, Object value) throws Exception {
|
||||
Class<?> clazz = target.getClass();
|
||||
while (clazz != null) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
return;
|
||||
} catch (NoSuchFieldException e) {
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(fieldName);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,583 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
||||
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtfieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
|
||||
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttimefieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtplugins" type="xs:string">
|
||||
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
|
||||
</imixs:item>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
|
||||
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
|
||||
<bpmn2:documentation id="documentation_3xKpCQ"/>
|
||||
</bpmn2:participant>
|
||||
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
|
||||
</bpmn2:collaboration>
|
||||
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
|
||||
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
||||
<bpmn2:lane id="Lane_1" name="Team">
|
||||
<bpmn2:documentation id="documentation_gvQWYQ"/>
|
||||
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_yrC2dw</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_J0JjAg</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_1FAZgA</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_cjoSqg</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>gateway_SVo89A</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_5P6uhg</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_5RftUw" name="Contract Management">
|
||||
<bpmn2:documentation id="documentation_AW2roA"/>
|
||||
<bpmn2:flowNodeRef>task_0W5Llw</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_0k30Ug</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_vJ0eNA</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_a0dlhQ" name="Contract Owner">
|
||||
<bpmn2:documentation id="documentation_fATy7A"/>
|
||||
<bpmn2:flowNodeRef>task_GgAr6w</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_zpkT5A</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_v7oUjw</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_A6bDCA" name="Sales">
|
||||
<bpmn2:documentation id="documentation_l0BSxA"/>
|
||||
</bpmn2:lane>
|
||||
</bpmn2:laneSet>
|
||||
<bpmn2:startEvent id="StartEvent_1" name="Start">
|
||||
<bpmn2:documentation id="documentation_IUTaAQ"/>
|
||||
<bpmn2:outgoing>sequenceFlow_mCJiSA</bpmn2:outgoing>
|
||||
</bpmn2:startEvent>
|
||||
<bpmn2:endEvent id="EndEvent_2" name="End">
|
||||
<bpmn2:documentation id="documentation_mHDfBQ"/>
|
||||
</bpmn2:endEvent>
|
||||
<bpmn2:task id="task_yrC2dw" imixs:processid="2100" name="Contract Creation">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_BN3NHA"><![CDATA[Erstellung eines neuen Vertrags mit folgenden Pflichtfeldern: - **Vertragspartner** (Name, Adresse, Kontaktdaten, Vertragsnummer) - **Waren/Lieferungen** (Beschreibung, Menge, Einheit, Preis pro Einheit, Gesamtpreis, ggf. SKU/Artikelnummer) - **Lagerort** (falls relevant: Lagerstandort, Lagerverantwortlicher) - **Termine** (Liefertermin(e), Vertragslaufzeit, Fristen für Zahlungen/Meldungen) Optional: **Sonderbedingungen** (z. B. Rabatte, Penalties, Zahlungsmodalitäten).]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-5</bpmn2:incoming>
|
||||
<bpmn2:incoming>sequenceFlow_mCJiSA</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-8</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_vJ0eNA" imixs:processid="2300" name="Approval by Management">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_6PFUVg"><![CDATA[Freigabe des Vertrags unter Berücksichtigung: - **Finanzielle Auswirkungen** (Budget, Liquidität, Forecast) - **Strategische Bedeutung** (Neukunde, Langfristpartner) - **Risikoanalyse** (Bonität des Partners, Marktrisiken)]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sequenceFlow_4076SQ</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_XQfsfg" imixs:processid="2400" name="Contract Execution">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_ds3A0w"><![CDATA[**Finaler Schritt zur Vertragsaktivierung:** - **Vertragsunterzeichnung** (digital/physisch) durch beide Parteien. - **Datenaktualisierung im System**: - **Vertragspartner** → CRM/ERP (z. B. SAP, Salesforce). - **Waren/Lieferungen** → Lagerverwaltung/Logistik (z. B. Warehouse-Management-System). - **Termine** → Kalender/Projektmanagement (z. B. Microsoft Project, Jira). - **Finanzen** → Buchhaltung (Rechnungslauf, Zahlungspläne). - **Lagerort** → Bei physischen Gütern: Einlagerung und Zuordnung (z. B. per Barcode).]]></bpmn2:documentation>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_GgAr6w" imixs:processid="2900" name="Contract Completed">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_uK2mxw"><![CDATA[**Vertragsbeendigung:** - Kündigungsfristen einhalten. - **Liquidation**: - Offene Rechnungen prüfen (Zahlungseingang/Stornierung). - Lagerbestände bereinigen (Rücklieferung/Rücknahme). - **Dokumentation**: - Grund der Kündigung festhalten (für zukünftige Entscheidungen). - Vertrag aus dem System löschen.]]></bpmn2:documentation>
|
||||
<bpmn2:outgoing>sf-44</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_0W5Llw" imixs:processid="2990" name="Request/Contract Rejected">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_XDZRNw"><![CDATA[**Abgelehter Vertrag oder Anfrage:** - Grund für die Ablehnung dokumentieren (z. B. "Partner nicht solvent"). - Feedback an Initiator geben. - END]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-4</bpmn2:incoming>
|
||||
<bpmn2:incoming>sf-9</bpmn2:incoming>
|
||||
<bpmn2:incoming>sf-45</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:intermediateCatchEvent id="event_5P6uhg" imixs:activityid="20" name="Reject Request">
|
||||
<bpmn2:documentation id="documentation_FFCYJw"/>
|
||||
<bpmn2:outgoing>sf-4</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_J0JjAg" imixs:activityid="10" name="Save Draft">
|
||||
<bpmn2:documentation id="documentation_2D4qfg"/>
|
||||
<bpmn2:outgoing>sf-5</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_cjoSqg" imixs:activityid="20" name="Submit for Review">
|
||||
<bpmn2:documentation id="documentation_44KEYA"/>
|
||||
<bpmn2:incoming>sf-6</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_4076SQ</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_1FAZgA" imixs:activityid="30" name="Cancel Request">
|
||||
<bpmn2:documentation id="documentation_ysbsYg"/>
|
||||
<bpmn2:incoming>sequenceFlow_Jp2oQQ</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-9</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_0k30Ug" imixs:activityid="10" name="Request Adjustments">
|
||||
<bpmn2:documentation id="documentation_gmDYqA"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_Xdll0Q" imixs:activityid="20" name="Final Approval">
|
||||
<bpmn2:documentation id="documentation_md4VQA"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_W0tDdA" imixs:activityid="30" name="Decline Approval">
|
||||
<bpmn2:documentation id="documentation_mRacqQ"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_yurw7A" imixs:activityid="10" name="Completed">
|
||||
<bpmn2:documentation id="documentation_sqwDNg"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_c4BtJg" imixs:activityid="20" name="Execution Failed">
|
||||
<bpmn2:documentation id="documentation_thihzw"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_zpkT5A" imixs:activityid="20" name="Correction Needed">
|
||||
<bpmn2:documentation id="documentation_iUtChg"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_v7oUjw" imixs:activityid="10" name="Termination Completed">
|
||||
<bpmn2:documentation id="documentation_bwy4xQ"/>
|
||||
<bpmn2:incoming>sf-44</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-45</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:sequenceFlow id="sf-4" sourceRef="event_5P6uhg" targetRef="task_0W5Llw">
|
||||
<bpmn2:documentation id="documentation_rBwcmQ"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sf-5" sourceRef="event_J0JjAg" targetRef="task_yrC2dw">
|
||||
<bpmn2:documentation id="documentation_QaeCdA"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sf-6" sourceRef="gateway_SVo89A" targetRef="event_cjoSqg">
|
||||
<bpmn2:documentation id="documentation_BUeEdQ"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sf-8" sourceRef="task_yrC2dw" targetRef="gateway_SVo89A">
|
||||
<bpmn2:documentation id="documentation_Sd5bvw"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sf-9" sourceRef="event_1FAZgA" targetRef="task_0W5Llw">
|
||||
<bpmn2:documentation id="documentation_bJindA"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sf-44" sourceRef="task_GgAr6w" targetRef="event_v7oUjw">
|
||||
<bpmn2:documentation id="documentation_to0tvg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sf-45" sourceRef="event_v7oUjw" targetRef="task_0W5Llw">
|
||||
<bpmn2:documentation id="documentation_CjUGog"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:intermediateCatchEvent id="event_H7qtPg" imixs:activityid="20" name="Create Kundenauftrag">
|
||||
<bpmn2:documentation id="documentation_w9TwIQ"/>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_mCJiSA" sourceRef="StartEvent_1" targetRef="task_yrC2dw">
|
||||
<bpmn2:documentation id="documentation_rnZlMw"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_4076SQ" sourceRef="event_cjoSqg" targetRef="task_vJ0eNA">
|
||||
<bpmn2:documentation id="documentation_2UZmwA"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:eventBasedGateway gatewayDirection="Diverging" id="gateway_SVo89A" name="">
|
||||
<bpmn2:documentation id="documentation_C4eyaQ"/>
|
||||
<bpmn2:incoming>sf-8</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_Jp2oQQ</bpmn2:outgoing>
|
||||
<bpmn2:outgoing>sf-6</bpmn2:outgoing>
|
||||
</bpmn2:eventBasedGateway>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_Jp2oQQ" sourceRef="gateway_SVo89A" targetRef="event_1FAZgA">
|
||||
<bpmn2:documentation id="documentation_Wzw9Yg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="process_2" name="Default Process" processType="Public">
|
||||
<bpmn2:documentation id="documentation_imRbaw"/>
|
||||
<bpmn2:extensionElements>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
</bpmn2:process>
|
||||
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
|
||||
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
|
||||
<bpmn2:message id="message_1" name="Message 1">
|
||||
<bpmn2:documentation id="documentation_lq3hSg"/>
|
||||
</bpmn2:message>
|
||||
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
|
||||
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
|
||||
<dc:Bounds height="2300.0" width="4430.0" x="130.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
|
||||
<dc:Bounds height="420.25001525878906" width="4400.0" x="160.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
|
||||
<dc:Bounds height="36.0" width="36.0" x="217.0" y="177.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="189.5" y="214.10797119140625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
|
||||
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_30">
|
||||
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1027.0" y="197.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1001.138671875" y="235.10791015625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
|
||||
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
|
||||
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
|
||||
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_5RftUw" id="BPMNShape_Lane_EXH7Fg">
|
||||
<dc:Bounds height="651.2500152587891" width="4400.0" x="160.0" y="510.25001525878906"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_a0dlhQ" id="BPMNShape_Lane_lMjKqQ">
|
||||
<dc:Bounds height="614.2500152587891" width="4400.0" x="160.0" y="1161.5000305175781"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_A6bDCA" id="BPMNShape_Lane_ErklDA">
|
||||
<dc:Bounds height="614.2500152587891" width="4400.0" x="160.0" y="1775.7500457763672"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_yrC2dw" id="BPMNShape_mtNu0w">
|
||||
<dc:Bounds height="50.0" width="110.0" x="340.0" y="170.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_vJ0eNA" id="BPMNShape_VSjVPA">
|
||||
<dc:Bounds height="50.0" width="110.0" x="980.0" y="670.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_XQfsfg" id="BPMNShape_Vk1kAw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="1540.0" y="1080.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_GgAr6w" id="BPMNShape_PSzHWw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="2260.0" y="1300.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_0W5Llw" id="BPMNShape_WjH04g">
|
||||
<dc:Bounds height="50.0" width="110.0" x="2420.0" y="400.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_5P6uhg" id="BPMNShape_1ACHNw">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1227.0" y="397.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_IsYLwA">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1195.0" y="436.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_J0JjAg" id="BPMNShape_zrh0rg">
|
||||
<dc:Bounds height="36.0" width="36.0" x="377.0" y="97.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_fwqgDg">
|
||||
<dc:Bounds height="20.0" width="100.0" x="345.0" y="136.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_cjoSqg" id="BPMNShape_POp4IQ">
|
||||
<dc:Bounds height="36.0" width="36.0" x="827.0" y="367.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_zhSm0g">
|
||||
<dc:Bounds height="20.0" width="100.0" x="795.0" y="406.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_1FAZgA" id="BPMNShape_bSO6tQ">
|
||||
<dc:Bounds height="36.0" width="36.0" x="897.0" y="177.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_gAvpBQ">
|
||||
<dc:Bounds height="20.0" width="100.0" x="865.0" y="216.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_0k30Ug" id="BPMNShape_Zn0P3A">
|
||||
<dc:Bounds height="36.0" width="36.0" x="757.0" y="667.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_umknQA">
|
||||
<dc:Bounds height="20.0" width="100.0" x="725.0" y="706.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_Xdll0Q" id="BPMNShape_Eq39Kg">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1317.0" y="920.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_G1WeRA">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1285.0" y="959.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_W0tDdA" id="BPMNShape_5yHEow">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1407.0" y="857.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_HkKcBw">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1375.0" y="896.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_yurw7A" id="BPMNShape_rWONBg">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1887.0" y="1147.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_s0S0ng">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1855.0" y="1186.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_c4BtJg" id="BPMNShape_iclF5g">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1857.0" y="1047.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_Gi1kIA">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1825.0" y="1086.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_zpkT5A" id="BPMNShape_TbcBcA">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1487.0" y="1317.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_9UFuzg">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1455.0" y="1356.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_v7oUjw" id="BPMNShape_p2C5FA">
|
||||
<dc:Bounds height="36.0" width="36.0" x="2727.0" y="1357.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_DFJutA">
|
||||
<dc:Bounds height="20.0" width="100.0" x="2695.0" y="1396.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_H7qtPg" id="BPMNShape_zXH5Wg">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1317.0" y="1087.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_BcZSCQ">
|
||||
<dc:Bounds height="20.0" width="100.0" x="1285.0" y="1126.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="gateway_SVo89A" id="BPMNShape_rffh8A">
|
||||
<dc:Bounds height="50.0" width="50.0" x="600.0" y="170.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_eaxusQ">
|
||||
<dc:Bounds height="20.0" width="100.0" x="575.0" y="223.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-4" id="BPMNEdge_oO9ZTA" sourceElement="BPMNShape_1ACHNw" targetElement="BPMNShape_WjH04g">
|
||||
<di:waypoint x="1263.0" y="415.0"/>
|
||||
<di:waypoint x="1267.0" y="415.0"/>
|
||||
<di:waypoint x="1267.0" y="425.0"/>
|
||||
<di:waypoint x="2420.0" y="425.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-5" id="BPMNEdge_GZrbVw" sourceElement="BPMNShape_zrh0rg" targetElement="BPMNShape_mtNu0w">
|
||||
<di:waypoint x="395.0" y="133.0"/>
|
||||
<di:waypoint x="395.0" y="170.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-6" id="BPMNEdge_SKcIKQ" sourceElement="BPMNShape_rffh8A" targetElement="BPMNShape_POp4IQ">
|
||||
<di:waypoint x="625.0" y="220.0"/>
|
||||
<di:waypoint x="625.0" y="385.0"/>
|
||||
<di:waypoint x="827.0" y="385.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-8" id="BPMNEdge_J17Pgg" sourceElement="BPMNShape_mtNu0w" targetElement="BPMNShape_rffh8A">
|
||||
<di:waypoint x="450.0" y="195.0"/>
|
||||
<di:waypoint x="600.0" y="195.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-9" id="BPMNEdge_oJE2uQ" sourceElement="BPMNShape_bSO6tQ" targetElement="BPMNShape_WjH04g">
|
||||
<di:waypoint x="933.0" y="195.0"/>
|
||||
<di:waypoint x="1677.0" y="195.0"/>
|
||||
<di:waypoint x="1677.0" y="425.0"/>
|
||||
<di:waypoint x="2420.0" y="425.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-44" id="BPMNEdge_IzbEkA" sourceElement="BPMNShape_PSzHWw" targetElement="BPMNShape_p2C5FA">
|
||||
<di:waypoint x="2370.0" y="1329.0"/>
|
||||
<di:waypoint x="3230.0" y="1329.0"/>
|
||||
<di:waypoint x="3230.0" y="1375.0"/>
|
||||
<di:waypoint x="2763.0" y="1375.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-45" id="BPMNEdge_TxZz3A" sourceElement="BPMNShape_p2C5FA" targetElement="BPMNShape_WjH04g">
|
||||
<di:waypoint x="2763.0" y="1375.0"/>
|
||||
<di:waypoint x="3282.0" y="1375.0"/>
|
||||
<di:waypoint x="2474.0" y="1375.0"/>
|
||||
<di:waypoint x="2474.0" y="450.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_mCJiSA" id="BPMNEdge_m1mtfw" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_mtNu0w">
|
||||
<di:waypoint x="253.0" y="195.0"/>
|
||||
<di:waypoint x="340.0" y="195.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_4076SQ" id="BPMNEdge_8zpyew" sourceElement="BPMNShape_POp4IQ" targetElement="BPMNShape_VSjVPA">
|
||||
<di:waypoint x="863.0" y="385.0"/>
|
||||
<di:waypoint x="917.0" y="385.0"/>
|
||||
<di:waypoint x="917.0" y="695.0"/>
|
||||
<di:waypoint x="980.0" y="695.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Jp2oQQ" id="BPMNEdge_HivQDQ" sourceElement="BPMNShape_rffh8A" targetElement="BPMNShape_bSO6tQ">
|
||||
<di:waypoint x="650.0" y="195.0"/>
|
||||
<di:waypoint x="897.0" y="195.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
|
||||
<dc:Font name="arial" size="9.0"/>
|
||||
</bpmndi:BPMNLabelStyle>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
START
|
||||
|
|
||||
|- [Task: 2000] **New Contract Request**
|
||||
Team: **Contract Management**
|
||||
Description:
|
||||
Ein neuer Vertragsanfrag wird eingereicht (z. B. durch Vertrieb oder Einkauf). Grundlegende Daten wie Vertragstyp (Kauf/Verkauf/Leasing) und Verantwortlicher müssen erfasst werden.
|
||||
|-- [Event: 10] **Forward to Contract Creation** --> [Task: 2100] **Contract Creation**
|
||||
|-- [Event: 20] **Reject Request** --> [Task: 2990] **Request Rejected**
|
||||
|
||||
|
|
||||
|- [Task: 2100] **Contract Creation**
|
||||
Team: **Contract Management**
|
||||
Description:
|
||||
Erstellung eines neuen Vertrags mit folgenden Pflichtfeldern:
|
||||
- **Vertragspartner** (Name, Adresse, Kontaktdaten, Vertragsnummer)
|
||||
- **Waren/Lieferungen** (Beschreibung, Menge, Einheit, Preis pro Einheit, Gesamtpreis, ggf. SKU/Artikelnummer)
|
||||
- **Lagerort** (falls relevant: Lagerstandort, Lagerverantwortlicher)
|
||||
- **Termine** (Liefertermin(e), Vertragslaufzeit, Fristen für Zahlungen/Meldungen)
|
||||
Optional: **Sonderbedingungen** (z. B. Rabatte, Penalties, Zahlungsmodalitäten).
|
||||
|-- [Event: 10] **Save Draft** --> [Task: 2100] **Contract Creation** *(Iteration für Korrekturen)*
|
||||
|-- [Event: 20] **Submit for Review** --> [Task: 2200] **Legal Review**
|
||||
|-- [Event: 30] **Cancel Request** --> [Task: 2990] **Request Rejected**
|
||||
|
||||
|
|
||||
|- [Task: 2200] **Legal Review**
|
||||
Team: **Legal/Compliance**
|
||||
Description:
|
||||
Prüfung auf rechtliche Korrektheit und Vollständigkeit:
|
||||
- Vertragsklauseln (AGB, Gewährleistungen, Haftung)
|
||||
- Compliance mit internen Richtlinien (z. B. Risikobewertung bei neuen Partnern)
|
||||
- Terminpläne (z. B. Prüfung von Fristen)
|
||||
|-- [Event: 10] **Request Changes** --> [Task: 2100] **Contract Creation** *(Rückgabe zur Korrektur)*
|
||||
|-- [Event: 20] **Approve Contract** --> [Task: 2300] **Approval by Management**
|
||||
|-- [Event: 30] **Reject Contract** --> [Task: 2990] **Contract Rejected**
|
||||
|
||||
|
|
||||
|- [Task: 2300] **Approval by Management**
|
||||
Team: **Senior Management/Finance**
|
||||
Description:
|
||||
Freigabe des Vertrags unter Berücksichtigung:
|
||||
- **Finanzielle Auswirkungen** (Budget, Liquidität, Forecast)
|
||||
- **Strategische Bedeutung** (Neukunde, Langfristpartner)
|
||||
- **Risikoanalyse** (Bonität des Partners, Marktrisiken)
|
||||
|-- [Event: 10] **Request Adjustments** --> [Task: 2100] **Contract Creation** *(z. B. Preisanpassung)*
|
||||
|-- [Event: 20] **Final Approval** --> [Task: 2400] **Contract Execution**
|
||||
|-- [Event: 30] **Decline Approval** --> [Task: 2990] **Contract Rejected**
|
||||
|
||||
|
|
||||
|- [Task: 2400] **Contract Execution**
|
||||
Team: **Contract Management / Operations**
|
||||
Description:
|
||||
**Finaler Schritt zur Vertragsaktivierung:**
|
||||
- **Vertragsunterzeichnung** (digital/physisch) durch beide Parteien.
|
||||
- **Datenaktualisierung im System**:
|
||||
- **Vertragspartner** → CRM/ERP (z. B. SAP, Salesforce).
|
||||
- **Waren/Lieferungen** → Lagerverwaltung/Logistik (z. B. Warehouse-Management-System).
|
||||
- **Termine** → Kalender/Projektmanagement (z. B. Microsoft Project, Jira).
|
||||
- **Finanzen** → Buchhaltung (Rechnungslauf, Zahlungspläne).
|
||||
- **Lagerort** → Bei physischen Gütern: Einlagerung und Zuordnung (z. B. per Barcode).
|
||||
|-- [Event: 10] **Contract Signed** --> [Task: 2500] **Post-Contract Setup**
|
||||
|-- [Event: 20] **Execution Failed** --> [Task: 2990] **Contract Rejected** *(z. B. Unterzeichnung gescheitert)*
|
||||
|
||||
|
|
||||
|- [Task: 2500] **Post-Contract Setup**
|
||||
Team: **Cross-Functional (Logistik, Sales, Finance)**
|
||||
Description:
|
||||
**Nachbereitung nach Vertragsunterzeichnung:**
|
||||
- **Logistik**:
|
||||
- Lagerbestände anpassen (bei Lieferverträgen).
|
||||
- Lieferpläne erstellen (Termine, Routen, Verantwortliche).
|
||||
- **Vertrieb**:
|
||||
- Kundenkommunikation (Bestätigungsmail, nächste Schritte).
|
||||
- **Finanzen**:
|
||||
- Zahlungsbedingungen konfigurieren (z. B. Skonto, Raten).
|
||||
- Budgetreservierungen freigeben.
|
||||
- **Monitoring**:
|
||||
- **KPIs** festlegen (z. B. Liefertreue, Zahlungseingänge).
|
||||
- **Audit-Trail** für Nachverfolgung.
|
||||
|-- [Event: 10] **Setup Completed** --> [Task: 2600] **Contract Active**
|
||||
|-- [Event: 20] **Correction Needed** --> [Task: 2400] **Contract Execution** *(z. B. Lagerfehler korrigieren)*
|
||||
|
||||
|
|
||||
|- [Task: 2600] **Contract Active**
|
||||
Team: **Contract Owner (z. B. Account Manager)**
|
||||
Description:
|
||||
**Laufender Vertrag:**
|
||||
- **Regelmäßige Überprüfungen**:
|
||||
- Terminpläne (Lieferungen, Zahlungen, Kündigungsfristen).
|
||||
- Performance des Partners (z. B. Lieferzuverlässigkeit).
|
||||
- **Änderungsmanagement**:
|
||||
- Anpassungen (z. B. Mengenänderungen, Preisanpassungen) müssen neu freigegeben werden (→ Rückkehr zu [Task: 2100]).
|
||||
|-- [Event: 10] **Renewal Due** --> [Task: 2700] **Contract Renewal**
|
||||
|-- [Event: 20] **Termination Requested** --> [Task: 2900] **Contract Termination**
|
||||
|-- [Event: 30] **Escalation** --> [Task: 2800] **Contract Dispute**
|
||||
|
||||
|
|
||||
|- [Task: 2700] **Contract Renewal**
|
||||
Team: **Contract Management / Sales**
|
||||
Description:
|
||||
**Vertragsverlängerung/Anpassung:**
|
||||
- Analyse der Vertragsperformance (z. B. Umsatz, Partnerzufriedenheit).
|
||||
- Angebot für Verlängerung oder neue Bedingungen erstellen.
|
||||
- Prozess wie [Task: 2100] **Contract Creation** wiederholen.
|
||||
|-- [Event: 10] **Renewal Approved** --> [Task: 2600] **Contract Active**
|
||||
|-- [Event: 20] **Renewal Rejected** --> [Task: 2900] **Contract Termination**
|
||||
|
||||
|
|
||||
|- [Task: 2800] **Contract Dispute**
|
||||
Team: **Legal / Dispute Resolution**
|
||||
Description:
|
||||
**Konfliktmanagement:**
|
||||
- Ursache analysieren (z. B. nicht erfüllte Liefertermine, Preisstreitigkeiten).
|
||||
- Mediation oder rechtliche Schritte einleiten.
|
||||
- Bei Einigung: Anpassung des Vertrags ([Task: 2100]).
|
||||
- Bei Scheitern: [Task: 2900] **Contract Termination**.
|
||||
|-- [Event: 10] **Dispute Resolved** --> [Task: 2600] **Contract Active**
|
||||
|-- [Event: 20] **Termination Due to Dispute** --> [Task: 2900] **Contract Termination**
|
||||
|
||||
|
|
||||
|- [Task: 2900] **Contract Termination**
|
||||
Team: **Contract Management / Legal**
|
||||
Description:
|
||||
**Vertragsbeendigung:**
|
||||
- Kündigungsfristen einhalten.
|
||||
- **Liquidation**:
|
||||
- Offene Rechnungen prüfen (Zahlungseingang/Stornierung).
|
||||
- Lagerbestände bereinigen (Rücklieferung/Rücknahme).
|
||||
- **Dokumentation**:
|
||||
- Grund der Kündigung festhalten (für zukünftige Entscheidungen).
|
||||
- Vertrag aus dem System löschen.
|
||||
|-- [Event: 10] **Termination Completed** --> [Task: 2990] **Process Ended**
|
||||
|
||||
|
|
||||
|- [Task: 2990] **Request/Contract Rejected**
|
||||
Team: **Contract Management**
|
||||
Description:
|
||||
**Abgelehter Vertrag oder Anfrage:**
|
||||
- Grund für die Ablehnung dokumentieren (z. B. "Partner nicht solvent").
|
||||
- Feedback an Initiator geben.
|
||||
|-- [Event: 10] **Close Case** --> END
|
||||
|
||||
|
|
||||
|- END
|
||||
Description: **Workflow abgeschlossen** (Vertrag aktiv, beendet oder abgelehnt).
|
||||
|
|
@ -1,820 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
||||
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtfieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
|
||||
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttimefieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtplugins" type="xs:string">
|
||||
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
|
||||
</imixs:item>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
|
||||
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
|
||||
<bpmn2:documentation id="documentation_3xKpCQ"/>
|
||||
</bpmn2:participant>
|
||||
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
|
||||
</bpmn2:collaboration>
|
||||
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
|
||||
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
||||
<bpmn2:lane id="Lane_1" name="Team">
|
||||
<bpmn2:documentation id="documentation_gvQWYQ"/>
|
||||
<bpmn2:flowNodeRef>Task_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_vIjHLQ</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_DG70UA" name="Sales Operations">
|
||||
<bpmn2:flowNodeRef>task_X3JEMQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_DsQHAA</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_UdE1FQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_RDx0tQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_hNqu8Q</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_0Uti6Q</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_00ytag" name="Finance / Legal">
|
||||
<bpmn2:flowNodeRef>task_0qFkuw</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_LsGwGw</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_VDjbDQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_YIeVQg</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_4fHTYA" name="Pre-Sales / Engineers">
|
||||
<bpmn2:flowNodeRef>task_q3AJTA</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_w7iCNQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_tPPF0w</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_aGk1Mw" name="Purchasing / Procurement">
|
||||
<bpmn2:flowNodeRef>task_U17j4w</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_79P3wA" name="Logistics / Technical Support">
|
||||
<bpmn2:flowNodeRef>task_dkvx9A</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_u6xa6w</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_zdkmmA" name="Finance">
|
||||
<bpmn2:flowNodeRef>task_T7gMeg</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_rukJhQ</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
</bpmn2:laneSet>
|
||||
<bpmn2:startEvent id="StartEvent_1" name="Start">
|
||||
<bpmn2:documentation id="documentation_IUTaAQ"/>
|
||||
<bpmn2:outgoing>sequenceFlow_8NDJxA</bpmn2:outgoing>
|
||||
</bpmn2:startEvent>
|
||||
<bpmn2:task id="Task_2" imixs:processid="1000" name="Import">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="Documentation_2"/>
|
||||
<bpmn2:incoming>sequenceFlow_khuDtw</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_Gj9mmA</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:endEvent id="EndEvent_2" name="End">
|
||||
<bpmn2:documentation id="documentation_mHDfBQ"/>
|
||||
<bpmn2:incoming>sequenceFlow_Gj9mmA</bpmn2:incoming>
|
||||
</bpmn2:endEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_8NDJxA" sourceRef="StartEvent_1" targetRef="event_vIjHLQ">
|
||||
<bpmn2:documentation id="documentation_RKidfg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_Gj9mmA" sourceRef="Task_2" targetRef="EndEvent_2">
|
||||
<bpmn2:documentation id="documentation_V7pFuw"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:intermediateCatchEvent id="event_vIjHLQ" imixs:activityid="10" name="Event-1">
|
||||
<bpmn2:documentation id="documentation_e2Geig"/>
|
||||
<bpmn2:incoming>sequenceFlow_8NDJxA</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_khuDtw</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_khuDtw" sourceRef="event_vIjHLQ" targetRef="Task_2">
|
||||
<bpmn2:documentation id="documentation_d1EdlQ"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:task id="task_X3JEMQ" imixs:processid="2000" name="Order Received">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_sesL1g"><![CDATA[A new purchase order from a Reseller has been received via EDI, Email or Portal. Initial check for completeness of SKU and quantities.]]></bpmn2:documentation>
|
||||
<bpmn2:outgoing>sf-1</bpmn2:outgoing>
|
||||
<bpmn2:incoming>sf-3</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_0qFkuw" imixs:processid="2100" name="Credit & Compliance Check">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_HNaSKw"><![CDATA[Verification of the Reseller's credit limit and export control compliance (especially for US-based cybersecurity vendors).]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-2</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-4</bpmn2:outgoing>
|
||||
<bpmn2:incoming>sf-6</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-7</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_q3AJTA" imixs:processid="2200" name="Technical Validation">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_eH1H6Q"><![CDATA[VAD Service: Review if the ordered configuration/solution is technically sound and compatible (e.g., bundles, maintenance periods).]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-5</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-9</bpmn2:outgoing>
|
||||
<bpmn2:incoming>sf-11</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_U17j4w" imixs:processid="2300" name="Vendor Ordering">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_5oT1YQ"><![CDATA[Order is placed at the Vendor (e.g., Fortinet, Check Point). Waiting for Vendor confirmation and license/hardware allocation. |-- [Event: 10] Confirmed by Vendor --> [Task: 2400] Delivery & Provisioning |-- [Event: 20] Delay Notification --> [Task: 2300] Vendor Ordering]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-10</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_dkvx9A" imixs:processid="2400" name="Delivery & Provisioning">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_aNWqug"><![CDATA[Physical shipment of hardware or digital provisioning of license keys/cloud access to the Reseller.]]></bpmn2:documentation>
|
||||
<bpmn2:outgoing>sf-12</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_T7gMeg" imixs:processid="2500" name="Invoicing">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_ggUUuQ"><![CDATA[Final invoice is generated and sent to the Reseller. Update of ERP system records. |-- [Event: 10] Invoice Sent --> [Task: 2800] Completed]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-13</bpmn2:incoming>
|
||||
<bpmn2:incoming>sf-14</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_DsQHAA" imixs:processid="2800" name="Completed">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_2wE86A"><![CDATA[Order successfully fulfilled and invoiced. |-- [Event: 10] Archive Order --> [Task: 2800] Completed]]></bpmn2:documentation>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_UdE1FQ" imixs:processid="2900" name="Cancelled">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_aXvupw"><![CDATA[The order was cancelled due to commercial, technical, or compliance reasons. |-- [Event: 10] Inform Vendor & Reseller --> [Task: 2800] Completed |-- [Event: 30] Delete Record --> [Task: 2990] Deleted END]]></bpmn2:documentation>
|
||||
<bpmn2:incoming>sf-8</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:task id="task_RDx0tQ" imixs:processid="2990" name="Deleted">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_WSBv0w"/>
|
||||
</bpmn2:task>
|
||||
<bpmn2:intermediateCatchEvent id="event_hNqu8Q" imixs:activityid="10" name="Validated">
|
||||
<bpmn2:documentation id="documentation_HpkRIg"/>
|
||||
<bpmn2:incoming>sf-1</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-2</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_0Uti6Q" imixs:activityid="20" name="Data Missing">
|
||||
<bpmn2:documentation id="documentation_jke3RA"/>
|
||||
<bpmn2:outgoing>sf-3</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_LsGwGw" imixs:activityid="10" name="Approved">
|
||||
<bpmn2:documentation id="documentation_1Z7lLQ"/>
|
||||
<bpmn2:incoming>sf-4</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-5</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_VDjbDQ" imixs:activityid="20" name="Hold">
|
||||
<bpmn2:documentation id="documentation_c39vVA"/>
|
||||
<bpmn2:outgoing>sf-6</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_YIeVQg" imixs:activityid="30" name="Rejected">
|
||||
<bpmn2:documentation id="documentation_ezlA2Q"/>
|
||||
<bpmn2:incoming>sf-7</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-8</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_w7iCNQ" imixs:activityid="10" name="Technical Clear">
|
||||
<bpmn2:documentation id="documentation_L830uw"/>
|
||||
<bpmn2:incoming>sf-9</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-10</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_tPPF0w" imixs:activityid="20" name="Adjustment Needed">
|
||||
<bpmn2:documentation id="documentation_yfTMmg"/>
|
||||
<bpmn2:outgoing>sf-11</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_u6xa6w" imixs:activityid="10" name="Fulfilled">
|
||||
<bpmn2:documentation id="documentation_ffDPSg"/>
|
||||
<bpmn2:incoming>sf-12</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sf-13</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:intermediateCatchEvent id="event_rukJhQ" imixs:activityid="10" name="Dispute">
|
||||
<bpmn2:documentation id="documentation_J0NUmg"/>
|
||||
<bpmn2:outgoing>sf-14</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:sequenceFlow id="sf-1" sourceRef="task_X3JEMQ" targetRef="event_hNqu8Q"/>
|
||||
<bpmn2:sequenceFlow id="sf-2" sourceRef="event_hNqu8Q" targetRef="task_0qFkuw"/>
|
||||
<bpmn2:sequenceFlow id="sf-3" sourceRef="event_0Uti6Q" targetRef="task_X3JEMQ"/>
|
||||
<bpmn2:sequenceFlow id="sf-4" sourceRef="task_0qFkuw" targetRef="event_LsGwGw"/>
|
||||
<bpmn2:sequenceFlow id="sf-5" sourceRef="event_LsGwGw" targetRef="task_q3AJTA"/>
|
||||
<bpmn2:sequenceFlow id="sf-6" sourceRef="event_VDjbDQ" targetRef="task_0qFkuw"/>
|
||||
<bpmn2:sequenceFlow id="sf-7" sourceRef="task_0qFkuw" targetRef="event_YIeVQg"/>
|
||||
<bpmn2:sequenceFlow id="sf-8" sourceRef="event_YIeVQg" targetRef="task_UdE1FQ"/>
|
||||
<bpmn2:sequenceFlow id="sf-9" sourceRef="task_q3AJTA" targetRef="event_w7iCNQ"/>
|
||||
<bpmn2:sequenceFlow id="sf-10" sourceRef="event_w7iCNQ" targetRef="task_U17j4w"/>
|
||||
<bpmn2:sequenceFlow id="sf-11" sourceRef="event_tPPF0w" targetRef="task_q3AJTA"/>
|
||||
<bpmn2:sequenceFlow id="sf-12" sourceRef="task_dkvx9A" targetRef="event_u6xa6w"/>
|
||||
<bpmn2:sequenceFlow id="sf-13" sourceRef="event_u6xa6w" targetRef="task_T7gMeg"/>
|
||||
<bpmn2:sequenceFlow id="sf-14" sourceRef="event_rukJhQ" targetRef="task_T7gMeg"/>
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="process_2" name="Default Process" processType="Public">
|
||||
<bpmn2:documentation id="documentation_imRbaw"/>
|
||||
<bpmn2:extensionElements>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
</bpmn2:process>
|
||||
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
|
||||
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
|
||||
<bpmn2:message id="message_1" name="Message 1">
|
||||
<bpmn2:documentation id="documentation_lq3hSg"/>
|
||||
</bpmn2:message>
|
||||
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
|
||||
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
|
||||
<dc:Bounds height="1610.0" width="4430.0" x="130.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
|
||||
<dc:Bounds height="36.0" width="36.0" x="237.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="209.5" y="174.10797119140625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
|
||||
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_30">
|
||||
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Task_2" id="BPMNShape_Task_5">
|
||||
<dc:Bounds height="50.0" width="110.0" x="490.0" y="130.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
|
||||
<dc:Bounds height="36.0" width="36.0" x="697.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="671.138671875" y="175.10791015625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
|
||||
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
|
||||
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
|
||||
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_vIjHLQ" id="BPMNShape_U2OU0Q">
|
||||
<dc:Bounds height="36.0" width="36.0" x="367.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_vd0n1w">
|
||||
<dc:Bounds height="20.0" width="100.0" x="335.0" y="176.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_8NDJxA" id="BPMNEdge_5jeXwQ" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_U2OU0Q">
|
||||
<di:waypoint x="273.0" y="155.0"/>
|
||||
<di:waypoint x="367.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Gj9mmA" id="BPMNEdge_D8ZZAw" sourceElement="BPMNShape_Task_5" targetElement="BPMNShape_EndEvent_2">
|
||||
<di:waypoint x="600.0" y="155.0"/>
|
||||
<di:waypoint x="697.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_khuDtw" id="BPMNEdge_vHtmSA" sourceElement="BPMNShape_U2OU0Q" targetElement="BPMNShape_Task_5">
|
||||
<di:waypoint x="403.0" y="155.0"/>
|
||||
<di:waypoint x="490.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_DG70UA" id="BPMNShape_Lane_jFYG6Q">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="320.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_00ytag" id="BPMNShape_Lane_xhK1gw">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="550.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_4fHTYA" id="BPMNShape_Lane_6GK7cA">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="780.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_aGk1Mw" id="BPMNShape_Lane_tjmgKA">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="1010.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_79P3wA" id="BPMNShape_Lane_pPNT5g">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="1240.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_zdkmmA" id="BPMNShape_Lane_FtseBQ">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="1470.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_X3JEMQ" id="BPMNShape_jq7RHA">
|
||||
<dc:Bounds height="50.0" width="110.0" x="300.0" y="390.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_0qFkuw" id="BPMNShape_3K2f0Q">
|
||||
<dc:Bounds height="50.0" width="110.0" x="610.0" y="620.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_q3AJTA" id="BPMNShape_sUEenw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="920.0" y="850.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_U17j4w" id="BPMNShape_W8fe4Q">
|
||||
<dc:Bounds height="50.0" width="110.0" x="1230.0" y="1080.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_dkvx9A" id="BPMNShape_ubdkUw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="1540.0" y="1310.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_T7gMeg" id="BPMNShape_hIOUAw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="1850.0" y="1540.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_DsQHAA" id="BPMNShape_Vn2fuQ">
|
||||
<dc:Bounds height="50.0" width="110.0" x="2160.0" y="390.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_UdE1FQ" id="BPMNShape_QQ4bfw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="2470.0" y="390.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_RDx0tQ" id="BPMNShape_3XWFIw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="2780.0" y="390.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_hNqu8Q" id="BPMNShape_KOADdw">
|
||||
<dc:Bounds height="36.0" width="36.0" x="337.0" y="460.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_BF0Ebw">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_0Uti6Q" id="BPMNShape_DcRdSQ">
|
||||
<dc:Bounds height="36.0" width="36.0" x="387.0" y="460.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_t2gQcA">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_LsGwGw" id="BPMNShape_UiA5Yg">
|
||||
<dc:Bounds height="36.0" width="36.0" x="647.0" y="690.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_ryMLDA">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_VDjbDQ" id="BPMNShape_xBD1vQ">
|
||||
<dc:Bounds height="36.0" width="36.0" x="697.0" y="690.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_BSXHzQ">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_YIeVQg" id="BPMNShape_BgjXgw">
|
||||
<dc:Bounds height="36.0" width="36.0" x="747.0" y="690.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_v8qOow">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_w7iCNQ" id="BPMNShape_qw6I8A">
|
||||
<dc:Bounds height="36.0" width="36.0" x="957.0" y="920.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_y0gzLg">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_tPPF0w" id="BPMNShape_e93ltA">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1007.0" y="920.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_7bv15g">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_u6xa6w" id="BPMNShape_Zgddmw">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1577.0" y="1380.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_jnAdow">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_rukJhQ" id="BPMNShape_GQobtA">
|
||||
<dc:Bounds height="36.0" width="36.0" x="1887.0" y="1610.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_BqocNw">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-1" id="BPMNEdge_6SOP2w" sourceElement="BPMNShape_jq7RHA" targetElement="BPMNShape_KOADdw">
|
||||
<di:waypoint x="355.0" y="415.0"/>
|
||||
<di:waypoint x="355.0" y="478.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-2" id="BPMNEdge_LM1Ncg" sourceElement="BPMNShape_KOADdw" targetElement="BPMNShape_3K2f0Q">
|
||||
<di:waypoint x="355.0" y="478.0"/>
|
||||
<di:waypoint x="665.0" y="645.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-3" id="BPMNEdge_JI0a9g" sourceElement="BPMNShape_DcRdSQ" targetElement="BPMNShape_jq7RHA">
|
||||
<di:waypoint x="405.0" y="478.0"/>
|
||||
<di:waypoint x="355.0" y="415.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-4" id="BPMNEdge_qQOQfA" sourceElement="BPMNShape_3K2f0Q" targetElement="BPMNShape_UiA5Yg">
|
||||
<di:waypoint x="665.0" y="645.0"/>
|
||||
<di:waypoint x="665.0" y="708.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-5" id="BPMNEdge_L6cT5A" sourceElement="BPMNShape_UiA5Yg" targetElement="BPMNShape_sUEenw">
|
||||
<di:waypoint x="665.0" y="708.0"/>
|
||||
<di:waypoint x="975.0" y="875.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-6" id="BPMNEdge_pTz0gg" sourceElement="BPMNShape_xBD1vQ" targetElement="BPMNShape_3K2f0Q">
|
||||
<di:waypoint x="715.0" y="708.0"/>
|
||||
<di:waypoint x="665.0" y="645.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-7" id="BPMNEdge_fcnNzw" sourceElement="BPMNShape_3K2f0Q" targetElement="BPMNShape_BgjXgw">
|
||||
<di:waypoint x="665.0" y="645.0"/>
|
||||
<di:waypoint x="765.0" y="708.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-8" id="BPMNEdge_oL0lZw" sourceElement="BPMNShape_BgjXgw" targetElement="BPMNShape_QQ4bfw">
|
||||
<di:waypoint x="765.0" y="708.0"/>
|
||||
<di:waypoint x="2525.0" y="415.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-9" id="BPMNEdge_y0BJxQ" sourceElement="BPMNShape_sUEenw" targetElement="BPMNShape_qw6I8A">
|
||||
<di:waypoint x="975.0" y="875.0"/>
|
||||
<di:waypoint x="975.0" y="938.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-10" id="BPMNEdge_e6L0iA" sourceElement="BPMNShape_qw6I8A" targetElement="BPMNShape_W8fe4Q">
|
||||
<di:waypoint x="975.0" y="938.0"/>
|
||||
<di:waypoint x="1285.0" y="1105.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-11" id="BPMNEdge_s8Telw" sourceElement="BPMNShape_e93ltA" targetElement="BPMNShape_sUEenw">
|
||||
<di:waypoint x="1025.0" y="938.0"/>
|
||||
<di:waypoint x="975.0" y="875.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-12" id="BPMNEdge_7D51VA" sourceElement="BPMNShape_ubdkUw" targetElement="BPMNShape_Zgddmw">
|
||||
<di:waypoint x="1595.0" y="1335.0"/>
|
||||
<di:waypoint x="1595.0" y="1398.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-13" id="BPMNEdge_kX1vjg" sourceElement="BPMNShape_Zgddmw" targetElement="BPMNShape_hIOUAw">
|
||||
<di:waypoint x="1595.0" y="1398.0"/>
|
||||
<di:waypoint x="1905.0" y="1565.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sf-14" id="BPMNEdge_lDS21g" sourceElement="BPMNShape_GQobtA" targetElement="BPMNShape_hIOUAw">
|
||||
<di:waypoint x="1905.0" y="1628.0"/>
|
||||
<di:waypoint x="1905.0" y="1565.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
|
||||
<dc:Font name="arial" size="9.0"/>
|
||||
</bpmndi:BPMNLabelStyle>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
Ordermanagement
|
||||
|
||||
START
|
||||
|
|
||||
|- [Task: 2000] Order Received
|
||||
| Team: Sales Operations
|
||||
| Description:
|
||||
| A new purchase order from a Reseller has been received via EDI, Email or Portal. Initial check for completeness of SKU and quantities.
|
||||
| |-- [Event: 10] Validated (Order complete) --> [Task: 2100] Credit & Compliance Check
|
||||
| |-- [Event: 20] Data Missing (Contact Reseller) --> [Task: 2000] Order Received
|
||||
| |-- [Event: 30] Cancel Order --> [Task: 2900] Cancelled
|
||||
|
|
||||
|- [Task: 2100] Credit & Compliance Check
|
||||
| Team: Finance / Legal
|
||||
| Description:
|
||||
| Verification of the Reseller's credit limit and export control compliance (especially for US-based cybersecurity vendors).
|
||||
| |-- [Event: 10] Approved (Credit and Compliance OK) --> [Task: 2200] Technical Validation
|
||||
| |-- [Event: 20] Hold (Credit limit exceeded) --> [Task: 2100] Credit & Compliance Check
|
||||
| |-- [Event: 30] Rejected (Compliance risk) --> [Task: 2900] Cancelled
|
||||
|
|
||||
|- [Task: 2200] Technical Validation
|
||||
| Team: Pre-Sales / Engineers
|
||||
| Description:
|
||||
| VAD Service: Review if the ordered configuration/solution is technically sound and compatible (e.g., bundles, maintenance periods).
|
||||
| |-- [Event: 10] Technical Clear (Configuration valid) --> [Task: 2300] Vendor Ordering
|
||||
| |-- [Event: 20] Adjustment Needed (Consult with Reseller) --> [Task: 2200] Technical Validation
|
||||
| |-- [Event: 30] Reject Design --> [Task: 2900] Cancelled
|
||||
|
|
||||
|- [Task: 2300] Vendor Ordering
|
||||
| Team: Purchasing / Procurement
|
||||
| Description:
|
||||
| Order is placed at the Vendor (e.g., Fortinet, Check Point). Waiting for Vendor confirmation and license/hardware allocation.
|
||||
| |-- [Event: 10] Confirmed by Vendor --> [Task: 2400] Delivery & Provisioning
|
||||
| |-- [Event: 20] Delay Notification --> [Task: 2300] Vendor Ordering
|
||||
|
|
||||
|- [Task: 2400] Delivery & Provisioning
|
||||
| Team: Logistics / Technical Support
|
||||
| Description:
|
||||
| Physical shipment of hardware or digital provisioning of license keys/cloud access to the Reseller.
|
||||
| |-- [Event: 10] Fulfilled (Delivery/Provisioning completed) --> [Task: 2500] Invoicing
|
||||
| |-- [Event: 11] Partial Delivery --> [Task: 2400] Delivery & Provisioning
|
||||
|
|
||||
|- [Task: 2500] Invoicing
|
||||
| Team: Finance
|
||||
| Description:
|
||||
| Final invoice is generated and sent to the Reseller. Update of ERP system records.
|
||||
| |-- [Event: 10] Invoice Sent --> [Task: 2800] Completed
|
||||
| |-- [Event: 20] Dispute (Correction required) --> [Task: 2500] Invoicing
|
||||
|
|
||||
|- [Task: 2800] Completed
|
||||
| Team: Sales Operations
|
||||
| Description:
|
||||
| Order successfully fulfilled and invoiced.
|
||||
| |-- [Event: 10] Archive Order --> [Task: 2800] Completed
|
||||
|
|
||||
|- [Task: 2900] Cancelled
|
||||
| Team: Sales Operations
|
||||
| Description:
|
||||
| The order was cancelled due to commercial, technical, or compliance reasons.
|
||||
| |-- [Event: 10] Inform Vendor & Reseller --> [Task: 2800] Completed
|
||||
| |-- [Event: 30] Delete Record --> [Task: 2990] Deleted
|
||||
|
|
||||
END
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
Business Process: Risk Management
|
||||
|
||||
START
|
||||
|
|
||||
|- [Task: 1000] Risk Identification
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| A potential risk has been identified within an operational unit. The Risk Owner captures basic data (Category, Description, Early Warning Indicators) to initiate the process in accordance with KonTraG.
|
||||
| |-- [Event: 10] Submit Proposal (Forward to Central Risk Management) --> [Task: 1100] Validation
|
||||
| |-- [Event: 20] Discard (Draft deleted) --> [Task: 1990] Deleted
|
||||
|
|
||||
|- [Task: 1100] Validation
|
||||
| Team: Central Risk Management
|
||||
| Description:
|
||||
| Central function checks if the identified issued qualifies as a relevant risk or if it is a duplicate.
|
||||
| |-- [Event: 10] Confirm Risk (Risk is valid, proceed to assessment) --> [Task: 1200] Gross Assessment
|
||||
| |-- [Event: 20] Reject (Not a risk or duplicate) --> [Task: 1900] Archived
|
||||
| |-- [Event: 30] Request Info (Send back to Owner for details) --> [Task: 1000] Risk Identification
|
||||
|
|
||||
|- [Task: 1200] Gross Assessment
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Quantitative assessment of the risk WITHOUT considering planned or existing measures. Impact and Probability are estimated to determine the Gross Risk Score.
|
||||
| |-- [Event: 10] Save Gross Data (Proceed to Measure Definition) --> [Task: 1300] Measure Definition
|
||||
|
|
||||
|- [Task: 1300] Measure Definition
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Definition of risk mitigating measures (Avoid, Reduce, Transfer, Accept). Documentation of costs and responsibilities for these measures.
|
||||
| |-- [Event: 10] Measures Defined (Proceed to Net Assessment) --> [Task: 1400] Net Assessment
|
||||
| |-- [Event: 20] Update Assessment (Go back to Gross Assessment) --> [Task: 1200] Gross Assessment
|
||||
|
|
||||
|- [Task: 1400] Net Assessment
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Re-evaluation of Impact and Probability taking the defined measures into account (Residual Risk). Crucial for IDW PS 340 compliance.
|
||||
| |-- [Event: 10] Submit for Aggregation (Forward to Central RM) --> [Task: 1500] Aggregation & Analysis
|
||||
|
|
||||
|- [Task: 1500] Aggregation & Analysis
|
||||
| Team: Central Risk Management
|
||||
| Description:
|
||||
| The risk is analyzed in the context of the total risk portfolio (Risk Aggregation/Monte Carlo Simulation) to check against the company's Risk Bearing Capacity.
|
||||
| |-- [Event: 10] Approve (Risk within appetite, standard monitoring) --> [Task: 1600] Monitoring
|
||||
| |-- [Event: 20] Insufficient Mitigation (Measures not enough, send back) --> [Task: 1300] Measure Definition
|
||||
| |-- [Event: 30] Critical Escalation (Threat to existence, forward to Board) --> [Task: 1550] Board Review
|
||||
|
|
||||
|- [Task: 1550] Board Review
|
||||
| Team: Management Board / Risk Committee
|
||||
| Description:
|
||||
| High-level decision required. Risk exceeds risk bearing capacity or is a "bestandsgefährdendes Risiko" (§91 Abs. 2 AktG).
|
||||
| |-- [Event: 10] Accept Risk (Special approval granted) --> [Task: 1600] Monitoring
|
||||
| |-- [Event: 20] Demand Action (Force new measures) --> [Task: 1300] Measure Definition
|
||||
|
|
||||
|- [Task: 1600] Monitoring
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Continuous surveillance of the risk and the effectiveness of measures. Periodic review (e.g., quarterly).
|
||||
| |-- [Event: 10] Report: No Change (Keep monitoring) --> [Task: 1600] Monitoring
|
||||
| |-- [Event: 20] Risk Changed (Values or measures changed) --> [Task: 1200] Gross Assessment
|
||||
| |-- [Event: 30] Risk Obsolete (Risk no longer exists) --> [Task: 1800] Closure Review
|
||||
|
|
||||
|- [Task: 1800] Closure Review
|
||||
| Team: Central Risk Management
|
||||
| Description:
|
||||
| Final check if the risk can really be closed.
|
||||
| |-- [Event: 10] Close Risk (Archive) --> [Task: 1900] Archived
|
||||
| |-- [Event: 20] Deny Closure (Keep active) --> [Task: 1600] Monitoring
|
||||
|
|
||||
|- [Task: 1900] Archived
|
||||
| Team: System
|
||||
| Description:
|
||||
| Risk is closed but kept for audit trails and historical data analysis.
|
||||
| |-- [Event: 10] Reactivate --> [Task: 1100] Validation
|
||||
|
|
||||
END
|
||||
|
|
||||
|- [Task: 1990] Deleted
|
||||
|
|
||||
|
|
@ -1,319 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
||||
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtfieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
|
||||
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttimefieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtplugins" type="xs:string">
|
||||
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
|
||||
</imixs:item>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
|
||||
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
|
||||
<bpmn2:documentation id="documentation_3xKpCQ"/>
|
||||
</bpmn2:participant>
|
||||
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
|
||||
</bpmn2:collaboration>
|
||||
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
|
||||
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
||||
<bpmn2:lane id="Lane_1" name="Team">
|
||||
<bpmn2:documentation id="documentation_gvQWYQ"/>
|
||||
<bpmn2:flowNodeRef>Task_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_vIjHLQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_HQd8AQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_6HJvNQ</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>task_HQ9VcQ</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
<bpmn2:lane id="lane_EQOgOg" name="Accounting"/>
|
||||
<bpmn2:lane id="lane_2tdU0Q" name="Sales Team"/>
|
||||
</bpmn2:laneSet>
|
||||
<bpmn2:startEvent id="StartEvent_1" name="Start">
|
||||
<bpmn2:documentation id="documentation_IUTaAQ"/>
|
||||
<bpmn2:outgoing>sequenceFlow_8NDJxA</bpmn2:outgoing>
|
||||
</bpmn2:startEvent>
|
||||
<bpmn2:task id="Task_2" imixs:processid="1000" name="Import">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="Documentation_2"/>
|
||||
<bpmn2:incoming>sequenceFlow_khuDtw</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_Gj9mmA</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:endEvent id="EndEvent_2" name="End">
|
||||
<bpmn2:documentation id="documentation_mHDfBQ"/>
|
||||
<bpmn2:incoming>sequenceFlow_Gj9mmA</bpmn2:incoming>
|
||||
</bpmn2:endEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_8NDJxA" sourceRef="StartEvent_1" targetRef="event_vIjHLQ">
|
||||
<bpmn2:documentation id="documentation_RKidfg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_Gj9mmA" sourceRef="Task_2" targetRef="EndEvent_2">
|
||||
<bpmn2:documentation id="documentation_V7pFuw"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:intermediateCatchEvent id="event_vIjHLQ" imixs:activityid="10" name="Event-1">
|
||||
<bpmn2:documentation id="documentation_e2Geig"/>
|
||||
<bpmn2:incoming>sequenceFlow_8NDJxA</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_khuDtw</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_khuDtw" sourceRef="event_vIjHLQ" targetRef="Task_2">
|
||||
<bpmn2:documentation id="documentation_d1EdlQ"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:task id="task_HQd8AQ" imixs:processid="1000" name="Task-2">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_z6PPww"/>
|
||||
<bpmn2:outgoing>sequence-flow-1</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:intermediateCatchEvent id="event_6HJvNQ" imixs:activityid="10" name="Event-1">
|
||||
<bpmn2:documentation id="documentation_PoRwdg"/>
|
||||
<bpmn2:incoming>sequence-flow-1</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequence-flow-2</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:task id="task_HQ9VcQ" imixs:processid="1100" name="Import">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="documentation_CdXjvg"/>
|
||||
<bpmn2:incoming>sequence-flow-2</bpmn2:incoming>
|
||||
</bpmn2:task>
|
||||
<bpmn2:sequenceFlow id="sequence-flow-1" sourceRef="task_HQd8AQ" targetRef="event_6HJvNQ"/>
|
||||
<bpmn2:sequenceFlow id="sequence-flow-2" sourceRef="event_6HJvNQ" targetRef="task_HQ9VcQ"/>
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="process_2" name="Default Process" processType="Public">
|
||||
<bpmn2:documentation id="documentation_imRbaw"/>
|
||||
<bpmn2:extensionElements>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
</bpmn2:process>
|
||||
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
|
||||
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
|
||||
<bpmn2:message id="message_1" name="Message 1">
|
||||
<bpmn2:documentation id="documentation_lq3hSg"/>
|
||||
</bpmn2:message>
|
||||
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
|
||||
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
|
||||
<dc:Bounds height="690.0" width="4430.0" x="130.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
|
||||
<dc:Bounds height="36.0" width="36.0" x="237.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="209.5" y="174.10797119140625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
|
||||
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_30">
|
||||
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Task_2" id="BPMNShape_Task_5">
|
||||
<dc:Bounds height="50.0" width="110.0" x="490.0" y="130.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
|
||||
<dc:Bounds height="36.0" width="36.0" x="697.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="671.138671875" y="175.10791015625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
|
||||
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
|
||||
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
|
||||
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_vIjHLQ" id="BPMNShape_U2OU0Q">
|
||||
<dc:Bounds height="36.0" width="36.0" x="367.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_vd0n1w">
|
||||
<dc:Bounds height="20.0" width="100.0" x="335.0" y="176.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_8NDJxA" id="BPMNEdge_5jeXwQ" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_U2OU0Q">
|
||||
<di:waypoint x="273.0" y="155.0"/>
|
||||
<di:waypoint x="367.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Gj9mmA" id="BPMNEdge_D8ZZAw" sourceElement="BPMNShape_Task_5" targetElement="BPMNShape_EndEvent_2">
|
||||
<di:waypoint x="600.0" y="155.0"/>
|
||||
<di:waypoint x="697.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_khuDtw" id="BPMNEdge_vHtmSA" sourceElement="BPMNShape_U2OU0Q" targetElement="BPMNShape_Task_5">
|
||||
<di:waypoint x="403.0" y="155.0"/>
|
||||
<di:waypoint x="490.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_EQOgOg" id="BPMNShape_Lane_vbFCIg">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="320.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="lane_2tdU0Q" id="BPMNShape_Lane_AJQqiw">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="550.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_HQd8AQ" id="BPMNShape_SWNkXw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="150.0" y="200.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_6HJvNQ" id="BPMNShape_GCOCOA">
|
||||
<dc:Bounds height="36.0" width="36.0" x="350.0" y="200.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_K3GzxA">
|
||||
<dc:Bounds x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_HQ9VcQ" id="BPMNShape_0vb1vw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="450.0" y="200.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequence-flow-1" id="BPMNEdge_nhNbcg" sourceElement="BPMNShape_SWNkXw" targetElement="BPMNShape_GCOCOA">
|
||||
<di:waypoint x="205.0" y="225.0"/>
|
||||
<di:waypoint x="368.0" y="218.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequence-flow-2" id="BPMNEdge_NLlZ5g" sourceElement="BPMNShape_GCOCOA" targetElement="BPMNShape_0vb1vw">
|
||||
<di:waypoint x="368.0" y="218.0"/>
|
||||
<di:waypoint x="505.0" y="225.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
|
||||
<dc:Font name="arial" size="9.0"/>
|
||||
</bpmndi:BPMNLabelStyle>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
Business Process: Risk Management Cycle (IDW PS 340)
|
||||
|
||||
START
|
||||
|
|
||||
|- [Task: 1000] Risk Identification
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| A potential risk has been identified within an operational unit. The Risk Owner captures basic data (Category, Description, Early Warning Indicators) to initiate the process in accordance with KonTraG.
|
||||
| |-- [Event: 10] Submit Proposal (Forward to Central Risk Management) --> [Task: 1100] Validation
|
||||
| |-- [Event: 20] Discard (Draft deleted) --> [Task: 1990] Deleted
|
||||
|
|
||||
|- [Task: 1100] Validation
|
||||
| Team: Central Risk Management
|
||||
| Description:
|
||||
| Central function checks if the identified issue qualifies as a relevant risk or if it is a duplicate.
|
||||
| |-- [Event: 10] Confirm Risk (Risk is valid, proceed to assessment) --> [Task: 1200] Gross Assessment
|
||||
| |-- [Event: 20] Reject (Not a risk or duplicate) --> [Task: 1900] Archived
|
||||
| |-- [Event: 30] Request Info (Send back to Owner for details) --> [Task: 1000] Risk Identification
|
||||
|
|
||||
|- [Task: 1200] Gross Assessment
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Quantitative assessment of the risk WITHOUT considering planned or existing measures. Impact and Probability are estimated to determine the Gross Risk Score.
|
||||
| |-- [Event: 10] Save Gross Data (Proceed to Measure Definition) --> [Task: 1300] Measure Definition
|
||||
|
|
||||
|- [Task: 1300] Measure Definition
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Definition of risk mitigating measures (Avoid, Reduce, Transfer, Accept). Documentation of costs and responsibilities for these measures.
|
||||
| |-- [Event: 10] Measures Defined (Proceed to Net Assessment) --> [Task: 1400] Net Assessment
|
||||
| |-- [Event: 20] Update Assessment (Go back to Gross Assessment) --> [Task: 1200] Gross Assessment
|
||||
|
|
||||
|- [Task: 1400] Net Assessment
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Re-evaluation of Impact and Probability taking the defined measures into account (Residual Risk). Crucial for IDW PS 340 compliance.
|
||||
| |-- [Event: 10] Submit for Aggregation (Forward to Central RM) --> [Task: 1500] Aggregation & Analysis
|
||||
|
|
||||
|- [Task: 1500] Aggregation & Analysis
|
||||
| Team: Central Risk Management
|
||||
| Description:
|
||||
| The risk is analyzed in the context of the total risk portfolio (Risk Aggregation/Monte Carlo Simulation) to check against the company's Risk Bearing Capacity.
|
||||
| |-- [Event: 10] Approve (Risk within appetite, standard monitoring) --> [Task: 1600] Monitoring
|
||||
| |-- [Event: 20] Insufficient Mitigation (Measures not enough, send back) --> [Task: 1300] Measure Definition
|
||||
| |-- [Event: 30] Critical Escalation (Threat to existence, forward to Board) --> [Task: 1550] Board Review
|
||||
|
|
||||
|- [Task: 1550] Board Review
|
||||
| Team: Management Board / Risk Committee
|
||||
| Description:
|
||||
| High-level decision required. Risk exceeds risk bearing capacity or is a "bestandsgefährdendes Risiko" (§91 Abs. 2 AktG).
|
||||
| |-- [Event: 10] Accept Risk (Special approval granted) --> [Task: 1600] Monitoring
|
||||
| |-- [Event: 20] Demand Action (Force new measures) --> [Task: 1300] Measure Definition
|
||||
|
|
||||
|- [Task: 1600] Monitoring
|
||||
| Team: Risk Owner (Operational Unit)
|
||||
| Description:
|
||||
| Continuous surveillance of the risk and the effectiveness of measures. Periodic review (e.g., quarterly).
|
||||
| |-- [Event: 10] Report: No Change (Keep monitoring) --> [Task: 1600] Monitoring
|
||||
| |-- [Event: 20] Risk Changed (Values or measures changed) --> [Task: 1200] Gross Assessment
|
||||
| |-- [Event: 30] Risk Obsolete (Risk no longer exists) --> [Task: 1800] Closure Review
|
||||
|
|
||||
|- [Task: 1800] Closure Review
|
||||
| Team: Central Risk Management
|
||||
| Description:
|
||||
| Final check if the risk can really be closed.
|
||||
| |-- [Event: 10] Close Risk (Archive) --> [Task: 1900] Archived
|
||||
| |-- [Event: 20] Deny Closure (Keep active) --> [Task: 1600] Monitoring
|
||||
|
|
||||
|- [Task: 1900] Archived
|
||||
| Team: System
|
||||
| Description:
|
||||
| Risk is closed but kept for audit trails and historical data analysis.
|
||||
| |-- [Event: 10] Reactivate --> [Task: 1100] Validation
|
||||
|
|
||||
END
|
||||
|
|
||||
|- [Task: 1990] Deleted
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- origin at X=0.0 Y=0.0 --><bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:ext="http://org.eclipse.bpmn2/ext" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.eclipse.bpmn2.modeler.core" exporterVersion="1.5.4.RC1-v20220528-0836-B1" id="Definitions_1" targetNamespace="http://www.imixs.org/bpmn2">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
||||
<imixs:value><![CDATA[offer-en-1.0]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtfieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Creator|$Creator]]></imixs:value>
|
||||
<imixs:value><![CDATA[Current Editor|$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Manager|process.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Team|process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Process Assist|process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Manager|space.manager]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Team|space.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[Department Assist|space.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttimefieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Liefertermin|order.delivery]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtplugins" type="xs:string">
|
||||
<imixs:value><![CDATA[org.imixs.workflow.office.plugins.WorkitemLinkPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.ai.rag.RAGIndexPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.ProfilePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.CommentPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.plugins.SequenceNumberPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.team.TeamPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.DeputyPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.LogPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.marty.profile.MailPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[ai.dynamixs.cognition.CognitoPlugin]]></imixs:value>
|
||||
</imixs:item>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:collaboration id="Collaboration_1" name="Collaboration 1">
|
||||
<bpmn2:participant id="Participant_1" name="Example" processRef="Process_1">
|
||||
<bpmn2:documentation id="documentation_3xKpCQ"/>
|
||||
</bpmn2:participant>
|
||||
<bpmn2:participant id="participant_hnZfjA" name="Default Process" processRef="process_2"/>
|
||||
</bpmn2:collaboration>
|
||||
<bpmn2:process definitionalCollaborationRef="Collaboration_1" id="Process_1" isExecutable="false" name="Example" processType="Private">
|
||||
<bpmn2:laneSet id="LaneSet_1" name="Lane Set 1">
|
||||
<bpmn2:lane id="Lane_1" name="Team">
|
||||
<bpmn2:documentation id="documentation_gvQWYQ"/>
|
||||
<bpmn2:flowNodeRef>Task_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>EndEvent_2</bpmn2:flowNodeRef>
|
||||
<bpmn2:flowNodeRef>event_vIjHLQ</bpmn2:flowNodeRef>
|
||||
</bpmn2:lane>
|
||||
</bpmn2:laneSet>
|
||||
<bpmn2:startEvent id="StartEvent_1" name="Start">
|
||||
<bpmn2:documentation id="documentation_IUTaAQ"/>
|
||||
<bpmn2:outgoing>sequenceFlow_8NDJxA</bpmn2:outgoing>
|
||||
</bpmn2:startEvent>
|
||||
<bpmn2:task id="Task_2" imixs:processid="1000" name="Import">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txteditorid" type="xs:string">
|
||||
<imixs:value><![CDATA[form_basic]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtname" type="xs:string">
|
||||
<imixs:value><![CDATA[Rechnung erhalten]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtimageurl" type="xs:string">
|
||||
<imixs:value><![CDATA[typcn-business-card]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtworkflowsummary" type="xs:string">
|
||||
<imixs:value><![CDATA[<itemvalue>request.subject</itemvalue>]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyupdateacl" type="xs:string">
|
||||
<imixs:value><![CDATA[true]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txttype" type="xs:string">
|
||||
<imixs:value><![CDATA[workitem]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="namownershipnames" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddreadaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="namaddwriteaccess" type="xs:string">
|
||||
<imixs:value/>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyownershipfields" type="xs:string">
|
||||
<imixs:value><![CDATA[$Editor]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="keyaddwritefields" type="xs:string">
|
||||
<imixs:value><![CDATA[process.assist]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.team]]></imixs:value>
|
||||
<imixs:value><![CDATA[process.manager]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:documentation id="Documentation_2"/>
|
||||
<bpmn2:incoming>sequenceFlow_khuDtw</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_Gj9mmA</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:endEvent id="EndEvent_2" name="End">
|
||||
<bpmn2:documentation id="documentation_mHDfBQ"/>
|
||||
<bpmn2:incoming>sequenceFlow_Gj9mmA</bpmn2:incoming>
|
||||
</bpmn2:endEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_8NDJxA" sourceRef="StartEvent_1" targetRef="event_vIjHLQ">
|
||||
<bpmn2:documentation id="documentation_RKidfg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_Gj9mmA" sourceRef="Task_2" targetRef="EndEvent_2">
|
||||
<bpmn2:documentation id="documentation_V7pFuw"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:intermediateCatchEvent id="event_vIjHLQ" imixs:activityid="10" name="Event-1">
|
||||
<bpmn2:documentation id="documentation_e2Geig"/>
|
||||
<bpmn2:incoming>sequenceFlow_8NDJxA</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_khuDtw</bpmn2:outgoing>
|
||||
</bpmn2:intermediateCatchEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_khuDtw" sourceRef="event_vIjHLQ" targetRef="Task_2">
|
||||
<bpmn2:documentation id="documentation_d1EdlQ"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="process_2" name="Default Process" processType="Public">
|
||||
<bpmn2:documentation id="documentation_imRbaw"/>
|
||||
<bpmn2:extensionElements>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
</bpmn2:process>
|
||||
<bpmn2:signal id="signal_3" name="org.imixs.ai.workflow.OpenAIAPIAdapter"/>
|
||||
<bpmn2:signal id="signal_4" name="org.imixs.ai.rag.RAGRetrievalAdapter"/>
|
||||
<bpmn2:message id="message_1" name="Message 1">
|
||||
<bpmn2:documentation id="documentation_lq3hSg"/>
|
||||
</bpmn2:message>
|
||||
<bpmn2:signal id="signal_5" name="org.imixs.ai.workflow.ImixsAIAssistantAdapter"/>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane bpmnElement="Collaboration_1" id="BPMNPlane_Process_1">
|
||||
<bpmndi:BPMNShape bpmnElement="Participant_1" id="BPMNShape_Participant_1" isHorizontal="true">
|
||||
<dc:Bounds height="230.0" width="4430.0" x="130.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Lane_1" id="BPMNShape_Lane_1" isHorizontal="true">
|
||||
<dc:Bounds height="230.0" width="4400.0" x="160.0" y="90.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="StartEvent_1" id="BPMNShape_StartEvent_1">
|
||||
<dc:Bounds height="36.0" width="36.0" x="237.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_1" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="209.5" y="174.10797119140625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="BPMNShape_TextAnnotation_1">
|
||||
<dc:Bounds height="73.0" width="131.0" x="130.0" y="581.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_30">
|
||||
<dc:Bounds height="67.0" width="119.0" x="136.0" y="581.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="Task_2" id="BPMNShape_Task_5">
|
||||
<dc:Bounds height="50.0" width="110.0" x="490.0" y="130.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="EndEvent_2" id="BPMNShape_EndEvent_2">
|
||||
<dc:Bounds height="36.0" width="36.0" x="697.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_110" labelStyle="BPMNLabelStyle_1">
|
||||
<dc:Bounds height="20.0" width="100.0" x="671.138671875" y="175.10791015625"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="participant_hnZfjA" id="BPMNShape_iHhp5Q">
|
||||
<dc:Bounds height="210.0" width="800.0" x="0.0" y="0.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="message_1" id="BPMNShape_5X9D7w">
|
||||
<dc:Bounds height="20.0" width="30.0" x="80.0" y="10.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_20MvBw">
|
||||
<dc:Bounds height="20.0" width="100.0" x="45.86090087890625" y="37.66443634033203"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_vIjHLQ" id="BPMNShape_U2OU0Q">
|
||||
<dc:Bounds height="36.0" width="36.0" x="367.0" y="137.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_vd0n1w">
|
||||
<dc:Bounds height="20.0" width="100.0" x="335.0" y="176.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_8NDJxA" id="BPMNEdge_5jeXwQ" sourceElement="BPMNShape_StartEvent_1" targetElement="BPMNShape_U2OU0Q">
|
||||
<di:waypoint x="273.0" y="155.0"/>
|
||||
<di:waypoint x="367.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Gj9mmA" id="BPMNEdge_D8ZZAw" sourceElement="BPMNShape_Task_5" targetElement="BPMNShape_EndEvent_2">
|
||||
<di:waypoint x="600.0" y="155.0"/>
|
||||
<di:waypoint x="697.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_khuDtw" id="BPMNEdge_vHtmSA" sourceElement="BPMNShape_U2OU0Q" targetElement="BPMNShape_Task_5">
|
||||
<di:waypoint x="403.0" y="155.0"/>
|
||||
<di:waypoint x="490.0" y="155.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
|
||||
<dc:Font name="arial" size="9.0"/>
|
||||
</bpmndi:BPMNLabelStyle>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:BPMN2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:imixs="http://www.imixs.org/bpmn2" xmlns:open-bpmn="http://open-bpmn.org/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="org.openbpmn" exporterVersion="1.0.0" targetNamespace="http://open-bpmn.org">
|
||||
<bpmn2:extensionElements>
|
||||
<imixs:item name="txtworkflowmodelversion" type="xs:string">
|
||||
<imixs:value><![CDATA[default-en-1.0]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtplugins" type="xs:string">
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.RulePlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.SplitAndJoinPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.OwnerPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApproverPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.HistoryPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ApplicationPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.IntervalPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.MailPlugin]]></imixs:value>
|
||||
<imixs:value><![CDATA[org.imixs.workflow.engine.plugins.ResultPlugin]]></imixs:value>
|
||||
</imixs:item>
|
||||
<imixs:item name="txtfieldmapping" type="xs:string">
|
||||
<imixs:value><![CDATA[Creator|$creator]]></imixs:value>
|
||||
<imixs:value><![CDATA[Owner|$owner]]></imixs:value>
|
||||
<imixs:value><![CDATA[Editor|$editor]]></imixs:value>
|
||||
</imixs:item>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:process id="process_1" name="Default Process" processType="Public">
|
||||
<bpmn2:documentation id="documentation_dIsJlQ"/>
|
||||
<bpmn2:extensionElements>
|
||||
<open-bpmn:auto-align>true</open-bpmn:auto-align>
|
||||
</bpmn2:extensionElements>
|
||||
<bpmn2:task id="task_DzBmHg" imixs:processid="100" name="Approve">
|
||||
<bpmn2:documentation id="documentation_Dz7pPQ"/>
|
||||
<bpmn2:incoming>sequenceFlow_3VLCbQ</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_cE44xg</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_3VLCbQ" sourceRef="event_BQQVcw" targetRef="task_DzBmHg">
|
||||
<bpmn2:documentation id="documentation_Ib3jJg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:task id="task_Qx2B4g" imixs:processid="200" name="Send">
|
||||
<bpmn2:extensionElements/>
|
||||
<bpmn2:documentation id="documentation_rvNWnQ"/>
|
||||
<bpmn2:incoming>sequenceFlow_cE44xg</bpmn2:incoming>
|
||||
<bpmn2:outgoing>sequenceFlow_Sl9ddA</bpmn2:outgoing>
|
||||
</bpmn2:task>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_cE44xg" sourceRef="task_DzBmHg" targetRef="task_Qx2B4g">
|
||||
<bpmn2:documentation id="documentation_aElYrg"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
<bpmn2:dataStoreReference id="dataStoreReference_7e3Lqw" name="Data Store">
|
||||
<bpmn2:documentation id="documentation_7z4JLw"/>
|
||||
</bpmn2:dataStoreReference>
|
||||
<bpmn2:association id="association_iA0M8A" sourceRef="task_Qx2B4g" targetRef="dataStoreReference_7e3Lqw">
|
||||
<bpmn2:documentation id="documentation_UrXC7A"/>
|
||||
</bpmn2:association>
|
||||
<bpmn2:dataObject id="dataObject_gtbRDw" imixs:datatype="prompt-data" name="Data">
|
||||
<bpmn2:documentation id="documentation_0uxQUw"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PromptDefinition>
|
||||
<prompt_options>{}</prompt_options>
|
||||
<prompt><![CDATA[<itemvalue>request.subject</itemvalue>
|
||||
|
||||
<FILECONTEXT>^.+\.eml$</FILECONTEXT>
|
||||
]]]]><![CDATA[>
|
||||
</prompt>
|
||||
<loglevel>FINE</loglevel>
|
||||
</PromptDefinition> ]]></bpmn2:documentation>
|
||||
</bpmn2:dataObject>
|
||||
<bpmn2:association id="association_lWHmDQ" sourceRef="task_DzBmHg" targetRef="dataObject_gtbRDw">
|
||||
<bpmn2:documentation id="documentation_Fj4EFA"/>
|
||||
</bpmn2:association>
|
||||
<bpmn2:association id="association_pNef4Q" sourceRef="event_BQQVcw" targetRef="dataStoreReference_7e3Lqw">
|
||||
<bpmn2:documentation id="documentation_pbD1Sw"/>
|
||||
</bpmn2:association>
|
||||
<bpmn2:startEvent id="event_BQQVcw" name="Start">
|
||||
<bpmn2:documentation id="documentation_KSXkdw"/>
|
||||
<bpmn2:outgoing>association_pNef4Q</bpmn2:outgoing>
|
||||
<bpmn2:outgoing>sequenceFlow_3VLCbQ</bpmn2:outgoing>
|
||||
</bpmn2:startEvent>
|
||||
<bpmn2:endEvent id="event_uRSh7g" name="Completed">
|
||||
<bpmn2:documentation id="documentation_uzqyIA"/>
|
||||
<bpmn2:incoming>sequenceFlow_Sl9ddA</bpmn2:incoming>
|
||||
</bpmn2:endEvent>
|
||||
<bpmn2:sequenceFlow id="sequenceFlow_Sl9ddA" sourceRef="task_Qx2B4g" targetRef="event_uRSh7g">
|
||||
<bpmn2:documentation id="documentation_SpLy3Q"/>
|
||||
</bpmn2:sequenceFlow>
|
||||
</bpmn2:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="OpenBPMN Diagram">
|
||||
<bpmndi:BPMNPlane bpmnElement="process_1" id="BPMNPlane_d1zbGg">
|
||||
<bpmndi:BPMNShape bpmnElement="task_DzBmHg" id="BPMNShape_06Te5Q">
|
||||
<dc:Bounds height="50.0" width="110.0" x="200.0" y="40.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="task_Qx2B4g" id="BPMNShape_yer4kw">
|
||||
<dc:Bounds height="50.0" width="110.0" x="450.0" y="40.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="dataStoreReference_7e3Lqw" id="BPMNShape_xwZRRA">
|
||||
<dc:Bounds height="50.0" width="50.0" x="520.0" y="180.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_RaeA2w">
|
||||
<dc:Bounds height="20.0" width="100.0" x="495.0" y="230.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="dataObject_gtbRDw" id="BPMNShape_31X79A">
|
||||
<dc:Bounds height="50.0" width="35.0" x="270.0" y="150.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_bCydww">
|
||||
<dc:Bounds height="20.0" width="100.0" x="237.5" y="205.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_BQQVcw" id="BPMNShape_aIKvbQ">
|
||||
<dc:Bounds height="36.0" width="36.0" x="57.0" y="47.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_b5BxyA">
|
||||
<dc:Bounds height="20.0" width="100.0" x="25.0" y="86.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape bpmnElement="event_uRSh7g" id="BPMNShape_pDh8Gw">
|
||||
<dc:Bounds height="36.0" width="36.0" x="657.0" y="47.0"/>
|
||||
<bpmndi:BPMNLabel id="BPMNLabel_c4C4GQ">
|
||||
<dc:Bounds height="20.0" width="100.0" x="625.0" y="86.0"/>
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_3VLCbQ" id="BPMNEdge_lrjXGw" sourceElement="BPMNShape_aIKvbQ" targetElement="BPMNShape_06Te5Q">
|
||||
<di:waypoint x="93.0" y="65.0"/>
|
||||
<di:waypoint x="200.0" y="65.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_cE44xg" id="BPMNEdge_cZ0SNA" sourceElement="BPMNShape_06Te5Q" targetElement="BPMNShape_yer4kw">
|
||||
<di:waypoint x="310.0" y="65.0"/>
|
||||
<di:waypoint x="450.0" y="65.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="association_iA0M8A" id="BPMNEdge_xP9rlQ" sourceElement="BPMNShape_yer4kw" targetElement="BPMNShape_xwZRRA">
|
||||
<di:waypoint x="504.0" y="90.0"/>
|
||||
<di:waypoint x="504.0" y="137.0"/>
|
||||
<di:waypoint x="540.0" y="137.0"/>
|
||||
<di:waypoint x="540.0" y="180.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="association_lWHmDQ" id="BPMNEdge_kg3SHw" sourceElement="BPMNShape_06Te5Q" targetElement="BPMNShape_31X79A">
|
||||
<di:waypoint x="254.0" y="90.0"/>
|
||||
<di:waypoint x="254.0" y="174.0"/>
|
||||
<di:waypoint x="270.0" y="174.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="association_pNef4Q" id="BPMNEdge_PH7UMQ" sourceElement="BPMNShape_aIKvbQ" targetElement="BPMNShape_xwZRRA">
|
||||
<di:waypoint x="75.0" y="83.0"/>
|
||||
<di:waypoint x="75.0" y="243.0"/>
|
||||
<di:waypoint x="544.0" y="243.0"/>
|
||||
<di:waypoint x="544.0" y="230.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge bpmnElement="sequenceFlow_Sl9ddA" id="BPMNEdge_KkWFiA" sourceElement="BPMNShape_yer4kw" targetElement="BPMNShape_pDh8Gw">
|
||||
<di:waypoint x="560.0" y="65.0"/>
|
||||
<di:waypoint x="657.0" y="65.0"/>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
||||
|
Before Width: | Height: | Size: 62 KiB |
|
|
@ -1,148 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" class="sprotty-graph bpmnextension-imixs" height="818" id="bpmn-diagram_5_root_pTGI10VcLg3PlNVo" version="1.1" viewBox="0 0 815 545" width="1223">
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g transform="scale(1) translate(0,0)">
|
||||
|
||||
<g class="graph-content">
|
||||
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_DzBmHg" transform="translate(200, 40)">
|
||||
<defs>
|
||||
<clipPath id="task_DzBmHg_clip_path">
|
||||
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #00000024; stroke-width: 2px;"/>
|
||||
<g class="extension">
|
||||
<text style="fill: #00000024; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
|
||||
100</text>
|
||||
</g>
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_task_DzBmHg_multiline" transform="translate(0, 8)">
|
||||
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 9.92188px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
|
||||
<tspan dy="10" x="0">Approve </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_Qx2B4g" transform="translate(450, 40)">
|
||||
<defs>
|
||||
<clipPath id="task_Qx2B4g_clip_path">
|
||||
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #00000024; stroke-width: 2px;"/>
|
||||
<g class="extension">
|
||||
<text style="fill: #00000024; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
|
||||
200</text>
|
||||
</g>
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_task_Qx2B4g_multiline" transform="translate(0, 8)">
|
||||
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 6.21875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
|
||||
<tspan dy="10" x="0">Send </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g class="startEvent event" id="bpmn-diagram_5_event_BQQVcw" transform="translate(57, 47)">
|
||||
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #00000024; stroke-width: 2px;"/>
|
||||
<g class="symbol">
|
||||
<path d="" style="fill: #00000024; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel" transform="translate(25, 86)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1dabf9f7-0b63-4258-9ad2-4187f7af92c2" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Start </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="endEvent event" id="bpmn-diagram_5_event_uRSh7g" transform="translate(657, 47)">
|
||||
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #00000024; stroke-width: 3px;"/>
|
||||
<g class="symbol">
|
||||
<path d="" style="fill: #00000024; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel" transform="translate(625, 86)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_63a5fcfa-f28f-48d1-a957-e5d4e974b3e0" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Completed </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="dataObject bpmnextension-imixs" id="bpmn-diagram_5_dataObject_gtbRDw" transform="translate(270, 150)">
|
||||
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 144, 241); stroke-width: 0px;" width="35" x="0" y="0"/>
|
||||
<g class="sprotty-icon" style="stroke-width: 2px;">
|
||||
<path d=" M 0,0 L 25,0 L 35,10 L 35,50 L 0,50 Z" fill="none" stroke="#00000024" stroke-width="1.5" style="fill: #00000024;"/>
|
||||
<g class="symbol">
|
||||
<path d="M6.25 9.016C6.66421 9.016 7 9.35089 7 9.76399V11.26C7 11.6731 6.66421 12.008 6.25 12.008C5.83579 12.008 5.5 11.6731 5.5 11.26V9.76399C5.5 9.35089 5.83579 9.016 6.25 9.016Z M10.5 9.76399C10.5 9.35089 10.1642 9.016 9.75 9.016C9.33579 9.016 9 9.35089 9 9.76399V11.26C9 11.6731 9.33579 12.008 9.75 12.008C10.1642 12.008 10.5 11.6731 10.5 11.26V9.76399Z M7.86079 1.80482C7.91028 1.8577 7.95663 1.91232 8 1.96856C8.04337 1.91232 8.08972 1.8577 8.13921 1.80482C8.82116 1.07611 9.87702 0.90832 11.0828 1.04194C12.3131 1.17827 13.2283 1.56829 13.8072 2.29916C14.3725 3.01276 14.5 3.90895 14.5 4.77735C14.5 5.34785 14.447 5.92141 14.2459 6.428L14.4135 7.26391L14.4798 7.29699C15.4115 7.76158 16 8.71126 16 9.7501V11.0107C16 11.2495 15.9143 11.4478 15.844 11.5763C15.7691 11.7131 15.6751 11.8368 15.5851 11.9416C15.4049 12.1512 15.181 12.3534 14.9801 12.5202C14.7751 12.6907 14.5728 12.8419 14.4235 12.9494C14.1842 13.1217 13.9389 13.2807 13.6826 13.4277C13.3756 13.6038 12.9344 13.8361 12.3867 14.0679C11.2956 14.5296 9.75604 15 8 15C6.24396 15 4.70442 14.5296 3.61334 14.0679C3.06559 13.8361 2.62435 13.6038 2.31739 13.4277C2.0611 13.2807 1.81581 13.1217 1.57651 12.9494C1.42716 12.8419 1.2249 12.6907 1.01986 12.5202C0.819 12.3534 0.595113 12.1512 0.414932 11.9416C0.3249 11.8368 0.230849 11.7131 0.156031 11.5763C0.0857453 11.4478 0 11.2495 1.90735e-06 11.0107L0 9.7501C0 8.71126 0.588507 7.76158 1.52017 7.29699L1.5865 7.26391L1.75413 6.42799C1.55295 5.9214 1.5 5.34785 1.5 4.77735C1.5 3.90895 1.62745 3.01276 2.19275 2.29916C2.77172 1.56829 3.68694 1.17827 4.91718 1.04194C6.12298 0.90832 7.17884 1.07611 7.86079 1.80482ZM3.0231 7.7282L3 7.8434V12.0931C3.02086 12.1053 3.04268 12.1179 3.06543 12.131C3.32878 12.2821 3.71567 12.4861 4.19916 12.6907C5.17058 13.1017 6.50604 13.504 8 13.504C9.49396 13.504 10.8294 13.1017 11.8008 12.6907C12.2843 12.4861 12.6712 12.2821 12.9346 12.131C12.9573 12.1179 12.9791 12.1053 13 12.0931V7.8434L12.9769 7.7282C12.4867 7.93728 11.9022 8.01867 11.25 8.01867C10.1037 8.01867 9.19051 7.69201 8.54033 7.03004C8.3213 6.80703 8.14352 6.55741 8 6.28924C7.85648 6.55741 7.6787 6.80703 7.45967 7.03004C6.80949 7.69201 5.89633 8.01867 4.75 8.01867C4.09776 8.01867 3.51325 7.93728 3.0231 7.7282ZM6.76421 2.82557C6.57116 2.61928 6.12702 2.41307 5.08282 2.52878C4.06306 2.64179 3.60328 2.93176 3.36975 3.22656C3.12255 3.53861 3 4.01374 3 4.77735C3 5.56754 3.12905 5.94499 3.3082 6.1441C3.47045 6.32443 3.82768 6.52267 4.75 6.52267C5.60367 6.52267 6.08903 6.28769 6.38811 5.98319C6.70349 5.66209 6.91507 5.1591 7.00579 4.43524C7.12274 3.50212 6.96805 3.04338 6.76421 2.82557ZM9.23579 2.82557C9.03195 3.04338 8.87726 3.50212 8.99421 4.43524C9.08493 5.1591 9.29651 5.66209 9.61189 5.98319C9.91097 6.28769 10.3963 6.52267 11.25 6.52267C12.1723 6.52267 12.5295 6.32443 12.6918 6.1441C12.871 5.94499 13 5.56754 13 4.77735C13 4.01374 12.8775 3.53861 12.6303 3.22656C12.3967 2.93176 11.9369 2.64179 10.9172 2.52878C9.87298 2.41307 9.42884 2.61928 9.23579 2.82557Z" style="fill: #00000024; stroke-width: 0px;" transform="scale(1.5),translate(4,8)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel" transform="translate(237.5, 205)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1fa04718-497b-43aa-9a90-d5ba73fe6ebc" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Data </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="dataStoreReference" id="bpmn-diagram_5_dataStoreReference_7e3Lqw" transform="translate(520, 180)">
|
||||
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="50" x="0" y="0"/>
|
||||
<g class="sprotty-icon" style="stroke-width: 2px;" transform="translate(0,10)">
|
||||
<path d="M0 0 L0 30" fill="none" stroke="#00000024" stroke-width="1.5"/>
|
||||
<path d="M50 0 L50 30" fill="none" stroke="#00000024" stroke-width="1.5"/>
|
||||
<path d="M0 30 A25 8.5 0 0 0 50 30" fill="none" stroke="#00000024" stroke-width="1.5"/>
|
||||
<path d="M0 15 A25 8.5 0 0 0 50 15" fill="none" stroke="#00000024" stroke-width="1.5"/>
|
||||
<ellipse cx="25" cy="0" fill="none" rx="25" ry="8.5" stroke="#00000024" stroke-width="1.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel" transform="translate(495, 230)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_da9e09dd-e430-42ae-adbe-c2014dd27244" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.7344px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Data Store </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_3VLCbQ" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 93,65 L 200,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #00000024;" transform="rotate(180 200 65) translate(200 65 )"/>
|
||||
<path class="mouse-handle" d="M 93,65 L 200,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_3VLCbQ_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(146.5, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_cE44xg" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 310,65 L 450,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #00000024;" transform="rotate(180 450 65) translate(450 65 )"/>
|
||||
<path class="mouse-handle" d="M 310,65 L 450,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_cE44xg_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(380, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_Sl9ddA" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 560,65 L 657,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #00000024;" transform="rotate(180 657 65) translate(657 65 )"/>
|
||||
<path class="mouse-handle" d="M 560,65 L 657,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_Sl9ddA_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(608.5, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_iA0M8A" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_iA0M8A_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(520, 137) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_lWHmDQ" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_lWHmDQ_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(254, 140) translate(-3, 0)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_pNef4Q" style="fill: none; stroke: #00000024; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_pNef4Q_bpmnlabel" style="fill: #00000024; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(236, 243) translate(0, -3)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -1,148 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" class="sprotty-graph bpmnextension-imixs" height="818" id="bpmn-diagram_5_root_pTGI10VcLg3PlNVo" version="1.1" viewBox="0 0 815 545" width="1223">
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g transform="scale(1) translate(0,0)">
|
||||
|
||||
<g class="graph-content">
|
||||
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_DzBmHg" transform="translate(200, 40)">
|
||||
<defs>
|
||||
<clipPath id="task_DzBmHg_clip_path">
|
||||
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff24; stroke-width: 2px;"/>
|
||||
<g class="extension">
|
||||
<text style="fill: #ffffff24; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
|
||||
100</text>
|
||||
</g>
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_task_DzBmHg_multiline" transform="translate(0, 8)">
|
||||
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 9.92188px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
|
||||
<tspan dy="10" x="0">Approve </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_Qx2B4g" transform="translate(450, 40)">
|
||||
<defs>
|
||||
<clipPath id="task_Qx2B4g_clip_path">
|
||||
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff24; stroke-width: 2px;"/>
|
||||
<g class="extension">
|
||||
<text style="fill: #ffffff24; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
|
||||
200</text>
|
||||
</g>
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_task_Qx2B4g_multiline" transform="translate(0, 8)">
|
||||
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 6.21875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
|
||||
<tspan dy="10" x="0">Send </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g class="startEvent event" id="bpmn-diagram_5_event_BQQVcw" transform="translate(57, 47)">
|
||||
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff24; stroke-width: 2px;"/>
|
||||
<g class="symbol">
|
||||
<path d="" style="fill: #ffffff24; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel" transform="translate(25, 86)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1dabf9f7-0b63-4258-9ad2-4187f7af92c2" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Start </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="endEvent event" id="bpmn-diagram_5_event_uRSh7g" transform="translate(657, 47)">
|
||||
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff24; stroke-width: 3px;"/>
|
||||
<g class="symbol">
|
||||
<path d="" style="fill: #ffffff24; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel" transform="translate(625, 86)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_63a5fcfa-f28f-48d1-a957-e5d4e974b3e0" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Completed </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="dataObject bpmnextension-imixs" id="bpmn-diagram_5_dataObject_gtbRDw" transform="translate(270, 150)">
|
||||
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 144, 241); stroke-width: 0px;" width="35" x="0" y="0"/>
|
||||
<g class="sprotty-icon" style="stroke-width: 2px;">
|
||||
<path d=" M 0,0 L 25,0 L 35,10 L 35,50 L 0,50 Z" fill="none" stroke="#ffffff24" stroke-width="1.5" style="fill: #ffffff24;"/>
|
||||
<g class="symbol">
|
||||
<path d="M6.25 9.016C6.66421 9.016 7 9.35089 7 9.76399V11.26C7 11.6731 6.66421 12.008 6.25 12.008C5.83579 12.008 5.5 11.6731 5.5 11.26V9.76399C5.5 9.35089 5.83579 9.016 6.25 9.016Z M10.5 9.76399C10.5 9.35089 10.1642 9.016 9.75 9.016C9.33579 9.016 9 9.35089 9 9.76399V11.26C9 11.6731 9.33579 12.008 9.75 12.008C10.1642 12.008 10.5 11.6731 10.5 11.26V9.76399Z M7.86079 1.80482C7.91028 1.8577 7.95663 1.91232 8 1.96856C8.04337 1.91232 8.08972 1.8577 8.13921 1.80482C8.82116 1.07611 9.87702 0.90832 11.0828 1.04194C12.3131 1.17827 13.2283 1.56829 13.8072 2.29916C14.3725 3.01276 14.5 3.90895 14.5 4.77735C14.5 5.34785 14.447 5.92141 14.2459 6.428L14.4135 7.26391L14.4798 7.29699C15.4115 7.76158 16 8.71126 16 9.7501V11.0107C16 11.2495 15.9143 11.4478 15.844 11.5763C15.7691 11.7131 15.6751 11.8368 15.5851 11.9416C15.4049 12.1512 15.181 12.3534 14.9801 12.5202C14.7751 12.6907 14.5728 12.8419 14.4235 12.9494C14.1842 13.1217 13.9389 13.2807 13.6826 13.4277C13.3756 13.6038 12.9344 13.8361 12.3867 14.0679C11.2956 14.5296 9.75604 15 8 15C6.24396 15 4.70442 14.5296 3.61334 14.0679C3.06559 13.8361 2.62435 13.6038 2.31739 13.4277C2.0611 13.2807 1.81581 13.1217 1.57651 12.9494C1.42716 12.8419 1.2249 12.6907 1.01986 12.5202C0.819 12.3534 0.595113 12.1512 0.414932 11.9416C0.3249 11.8368 0.230849 11.7131 0.156031 11.5763C0.0857453 11.4478 0 11.2495 1.90735e-06 11.0107L0 9.7501C0 8.71126 0.588507 7.76158 1.52017 7.29699L1.5865 7.26391L1.75413 6.42799C1.55295 5.9214 1.5 5.34785 1.5 4.77735C1.5 3.90895 1.62745 3.01276 2.19275 2.29916C2.77172 1.56829 3.68694 1.17827 4.91718 1.04194C6.12298 0.90832 7.17884 1.07611 7.86079 1.80482ZM3.0231 7.7282L3 7.8434V12.0931C3.02086 12.1053 3.04268 12.1179 3.06543 12.131C3.32878 12.2821 3.71567 12.4861 4.19916 12.6907C5.17058 13.1017 6.50604 13.504 8 13.504C9.49396 13.504 10.8294 13.1017 11.8008 12.6907C12.2843 12.4861 12.6712 12.2821 12.9346 12.131C12.9573 12.1179 12.9791 12.1053 13 12.0931V7.8434L12.9769 7.7282C12.4867 7.93728 11.9022 8.01867 11.25 8.01867C10.1037 8.01867 9.19051 7.69201 8.54033 7.03004C8.3213 6.80703 8.14352 6.55741 8 6.28924C7.85648 6.55741 7.6787 6.80703 7.45967 7.03004C6.80949 7.69201 5.89633 8.01867 4.75 8.01867C4.09776 8.01867 3.51325 7.93728 3.0231 7.7282ZM6.76421 2.82557C6.57116 2.61928 6.12702 2.41307 5.08282 2.52878C4.06306 2.64179 3.60328 2.93176 3.36975 3.22656C3.12255 3.53861 3 4.01374 3 4.77735C3 5.56754 3.12905 5.94499 3.3082 6.1441C3.47045 6.32443 3.82768 6.52267 4.75 6.52267C5.60367 6.52267 6.08903 6.28769 6.38811 5.98319C6.70349 5.66209 6.91507 5.1591 7.00579 4.43524C7.12274 3.50212 6.96805 3.04338 6.76421 2.82557ZM9.23579 2.82557C9.03195 3.04338 8.87726 3.50212 8.99421 4.43524C9.08493 5.1591 9.29651 5.66209 9.61189 5.98319C9.91097 6.28769 10.3963 6.52267 11.25 6.52267C12.1723 6.52267 12.5295 6.32443 12.6918 6.1441C12.871 5.94499 13 5.56754 13 4.77735C13 4.01374 12.8775 3.53861 12.6303 3.22656C12.3967 2.93176 11.9369 2.64179 10.9172 2.52878C9.87298 2.41307 9.42884 2.61928 9.23579 2.82557Z" style="fill: #ffffff24; stroke-width: 0px;" transform="scale(1.5),translate(4,8)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel" transform="translate(237.5, 205)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1fa04718-497b-43aa-9a90-d5ba73fe6ebc" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Data </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="dataStoreReference" id="bpmn-diagram_5_dataStoreReference_7e3Lqw" transform="translate(520, 180)">
|
||||
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="50" x="0" y="0"/>
|
||||
<g class="sprotty-icon" style="stroke-width: 2px;" transform="translate(0,10)">
|
||||
<path d="M0 0 L0 30" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
|
||||
<path d="M50 0 L50 30" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
|
||||
<path d="M0 30 A25 8.5 0 0 0 50 30" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
|
||||
<path d="M0 15 A25 8.5 0 0 0 50 15" fill="none" stroke="#ffffff24" stroke-width="1.5"/>
|
||||
<ellipse cx="25" cy="0" fill="none" rx="25" ry="8.5" stroke="#ffffff24" stroke-width="1.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel" transform="translate(495, 230)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_da9e09dd-e430-42ae-adbe-c2014dd27244" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.7344px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Data Store </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_3VLCbQ" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 93,65 L 200,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff24;" transform="rotate(180 200 65) translate(200 65 )"/>
|
||||
<path class="mouse-handle" d="M 93,65 L 200,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_3VLCbQ_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(146.5, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_cE44xg" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 310,65 L 450,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff24;" transform="rotate(180 450 65) translate(450 65 )"/>
|
||||
<path class="mouse-handle" d="M 310,65 L 450,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_cE44xg_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(380, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_Sl9ddA" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 560,65 L 657,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff24;" transform="rotate(180 657 65) translate(657 65 )"/>
|
||||
<path class="mouse-handle" d="M 560,65 L 657,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_Sl9ddA_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(608.5, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_iA0M8A" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_iA0M8A_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(520, 137) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_lWHmDQ" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_lWHmDQ_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(254, 140) translate(-3, 0)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_pNef4Q" style="fill: none; stroke: #ffffff24; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_pNef4Q_bpmnlabel" style="fill: #ffffff24; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(236, 243) translate(0, -3)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -1,148 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" class="sprotty-graph bpmnextension-imixs" height="818" id="bpmn-diagram_5_root_pTGI10VcLg3PlNVo" version="1.1" viewBox="0 0 815 545" width="1223">
|
||||
<defs>
|
||||
|
||||
</defs>
|
||||
<g transform="scale(1) translate(0,0)">
|
||||
|
||||
<g class="graph-content">
|
||||
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_DzBmHg" transform="translate(200, 40)">
|
||||
<defs>
|
||||
<clipPath id="task_DzBmHg_clip_path">
|
||||
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff0a; stroke-width: 2px;"/>
|
||||
<g class="extension">
|
||||
<text style="fill: #ffffff0a; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
|
||||
100</text>
|
||||
</g>
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_task_DzBmHg_multiline" transform="translate(0, 8)">
|
||||
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 9.92188px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
|
||||
<tspan dy="10" x="0">Approve </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g class="node task bpmnextension-imixs" id="bpmn-diagram_5_task_Qx2B4g" transform="translate(450, 40)">
|
||||
<defs>
|
||||
<clipPath id="task_Qx2B4g_clip_path">
|
||||
<path d="M2,5q0,-3 3,-3h100q3,0 3,3v40q0,3 -3,3h-100q-3,0 -3,-3z "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path class="sprotty-node" d="M0,5q0,-5 5,-5h100q5,0 5,5v40q0,5 -5,5h-100q-5,0 -5,-5z " style="fill: transparent; stroke: #ffffff0a; stroke-width: 2px;"/>
|
||||
<g class="extension">
|
||||
<text style="fill: #ffffff0a; font-family: sans-serif; font-size: 9.33333px; stroke: rgb(0, 0, 0); stroke-width: 0px;" transform="translate(3,46)">Id:
|
||||
200</text>
|
||||
</g>
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_task_Qx2B4g_multiline" transform="translate(0, 8)">
|
||||
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 6.21875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(55,0)">
|
||||
<tspan dy="10" x="0">Send </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g class="startEvent event" id="bpmn-diagram_5_event_BQQVcw" transform="translate(57, 47)">
|
||||
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff0a; stroke-width: 2px;"/>
|
||||
<g class="symbol">
|
||||
<path d="" style="fill: #ffffff0a; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel" transform="translate(25, 86)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1dabf9f7-0b63-4258-9ad2-4187f7af92c2" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_event_BQQVcw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Start </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="endEvent event" id="bpmn-diagram_5_event_uRSh7g" transform="translate(657, 47)">
|
||||
<circle class="sprotty-node" cx="18" cy="18" r="18" style="fill: transparent; stroke: #ffffff0a; stroke-width: 3px;"/>
|
||||
<g class="symbol">
|
||||
<path d="" style="fill: #ffffff0a; stroke-width: 0px;" transform="scale(1.5),translate(4,4)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel" transform="translate(625, 86)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_63a5fcfa-f28f-48d1-a957-e5d4e974b3e0" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_event_uRSh7g_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.875px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Completed </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="dataObject bpmnextension-imixs" id="bpmn-diagram_5_dataObject_gtbRDw" transform="translate(270, 150)">
|
||||
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 144, 241); stroke-width: 0px;" width="35" x="0" y="0"/>
|
||||
<g class="sprotty-icon" style="stroke-width: 2px;">
|
||||
<path d=" M 0,0 L 25,0 L 35,10 L 35,50 L 0,50 Z" fill="none" stroke="#ffffff0a" stroke-width="1.5" style="fill: #ffffff0a;"/>
|
||||
<g class="symbol">
|
||||
<path d="M6.25 9.016C6.66421 9.016 7 9.35089 7 9.76399V11.26C7 11.6731 6.66421 12.008 6.25 12.008C5.83579 12.008 5.5 11.6731 5.5 11.26V9.76399C5.5 9.35089 5.83579 9.016 6.25 9.016Z M10.5 9.76399C10.5 9.35089 10.1642 9.016 9.75 9.016C9.33579 9.016 9 9.35089 9 9.76399V11.26C9 11.6731 9.33579 12.008 9.75 12.008C10.1642 12.008 10.5 11.6731 10.5 11.26V9.76399Z M7.86079 1.80482C7.91028 1.8577 7.95663 1.91232 8 1.96856C8.04337 1.91232 8.08972 1.8577 8.13921 1.80482C8.82116 1.07611 9.87702 0.90832 11.0828 1.04194C12.3131 1.17827 13.2283 1.56829 13.8072 2.29916C14.3725 3.01276 14.5 3.90895 14.5 4.77735C14.5 5.34785 14.447 5.92141 14.2459 6.428L14.4135 7.26391L14.4798 7.29699C15.4115 7.76158 16 8.71126 16 9.7501V11.0107C16 11.2495 15.9143 11.4478 15.844 11.5763C15.7691 11.7131 15.6751 11.8368 15.5851 11.9416C15.4049 12.1512 15.181 12.3534 14.9801 12.5202C14.7751 12.6907 14.5728 12.8419 14.4235 12.9494C14.1842 13.1217 13.9389 13.2807 13.6826 13.4277C13.3756 13.6038 12.9344 13.8361 12.3867 14.0679C11.2956 14.5296 9.75604 15 8 15C6.24396 15 4.70442 14.5296 3.61334 14.0679C3.06559 13.8361 2.62435 13.6038 2.31739 13.4277C2.0611 13.2807 1.81581 13.1217 1.57651 12.9494C1.42716 12.8419 1.2249 12.6907 1.01986 12.5202C0.819 12.3534 0.595113 12.1512 0.414932 11.9416C0.3249 11.8368 0.230849 11.7131 0.156031 11.5763C0.0857453 11.4478 0 11.2495 1.90735e-06 11.0107L0 9.7501C0 8.71126 0.588507 7.76158 1.52017 7.29699L1.5865 7.26391L1.75413 6.42799C1.55295 5.9214 1.5 5.34785 1.5 4.77735C1.5 3.90895 1.62745 3.01276 2.19275 2.29916C2.77172 1.56829 3.68694 1.17827 4.91718 1.04194C6.12298 0.90832 7.17884 1.07611 7.86079 1.80482ZM3.0231 7.7282L3 7.8434V12.0931C3.02086 12.1053 3.04268 12.1179 3.06543 12.131C3.32878 12.2821 3.71567 12.4861 4.19916 12.6907C5.17058 13.1017 6.50604 13.504 8 13.504C9.49396 13.504 10.8294 13.1017 11.8008 12.6907C12.2843 12.4861 12.6712 12.2821 12.9346 12.131C12.9573 12.1179 12.9791 12.1053 13 12.0931V7.8434L12.9769 7.7282C12.4867 7.93728 11.9022 8.01867 11.25 8.01867C10.1037 8.01867 9.19051 7.69201 8.54033 7.03004C8.3213 6.80703 8.14352 6.55741 8 6.28924C7.85648 6.55741 7.6787 6.80703 7.45967 7.03004C6.80949 7.69201 5.89633 8.01867 4.75 8.01867C4.09776 8.01867 3.51325 7.93728 3.0231 7.7282ZM6.76421 2.82557C6.57116 2.61928 6.12702 2.41307 5.08282 2.52878C4.06306 2.64179 3.60328 2.93176 3.36975 3.22656C3.12255 3.53861 3 4.01374 3 4.77735C3 5.56754 3.12905 5.94499 3.3082 6.1441C3.47045 6.32443 3.82768 6.52267 4.75 6.52267C5.60367 6.52267 6.08903 6.28769 6.38811 5.98319C6.70349 5.66209 6.91507 5.1591 7.00579 4.43524C7.12274 3.50212 6.96805 3.04338 6.76421 2.82557ZM9.23579 2.82557C9.03195 3.04338 8.87726 3.50212 8.99421 4.43524C9.08493 5.1591 9.29651 5.66209 9.61189 5.98319C9.91097 6.28769 10.3963 6.52267 11.25 6.52267C12.1723 6.52267 12.5295 6.32443 12.6918 6.1441C12.871 5.94499 13 5.56754 13 4.77735C13 4.01374 12.8775 3.53861 12.6303 3.22656C12.3967 2.93176 11.9369 2.64179 10.9172 2.52878C9.87298 2.41307 9.42884 2.61928 9.23579 2.82557Z" style="fill: #ffffff0a; stroke-width: 0px;" transform="scale(1.5),translate(4,8)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel" transform="translate(237.5, 205)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_1fa04718-497b-43aa-9a90-d5ba73fe6ebc" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_dataObject_gtbRDw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 5.625px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Data </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="dataStoreReference" id="bpmn-diagram_5_dataStoreReference_7e3Lqw" transform="translate(520, 180)">
|
||||
<rect class="sprotty-node" height="50" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="50" x="0" y="0"/>
|
||||
<g class="sprotty-icon" style="stroke-width: 2px;" transform="translate(0,10)">
|
||||
<path d="M0 0 L0 30" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
|
||||
<path d="M50 0 L50 30" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
|
||||
<path d="M0 30 A25 8.5 0 0 0 50 30" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
|
||||
<path d="M0 15 A25 8.5 0 0 0 50 15" fill="none" stroke="#ffffff0a" stroke-width="1.5"/>
|
||||
<ellipse cx="25" cy="0" fill="none" rx="25" ry="8.5" stroke="#ffffff0a" stroke-width="1.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="BPMNLabel" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel" transform="translate(495, 230)">
|
||||
<rect class="sprotty-node" height="22" style="fill: rgba(0, 0, 0, 0); stroke: rgb(0, 0, 0); stroke-width: 0px;" width="100" x="0" y="0"/>
|
||||
<g class="comp sprotty-comp label-container" id="bpmn-diagram_5_da9e09dd-e430-42ae-adbe-c2014dd27244" style="fill: rgba(0, 0, 0, 0); stroke: rgba(0, 0, 0, 0);" transform="translate(5, 5)">
|
||||
<g class="bpmn-text-node" id="bpmn-diagram_5_dataStoreReference_7e3Lqw_bpmnlabel_multiline">
|
||||
<text class="sprotty-label" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; perspective-origin: 12.7344px 6px; stroke: rgb(0, 0, 0); stroke-width: 0px; text-anchor: middle;" transform="translate(45,0)">
|
||||
<tspan dy="10" x="0">Data Store </tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_3VLCbQ" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 93,65 L 200,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff0a;" transform="rotate(180 200 65) translate(200 65 )"/>
|
||||
<path class="mouse-handle" d="M 93,65 L 200,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_3VLCbQ_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(146.5, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_cE44xg" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 310,65 L 450,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff0a;" transform="rotate(180 450 65) translate(450 65 )"/>
|
||||
<path class="mouse-handle" d="M 310,65 L 450,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_cE44xg_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(380, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge sequenceFlow bpmnedge" id="bpmn-diagram_5_sequenceFlow_Sl9ddA" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 560,65 L 657,65"/>
|
||||
<path class="sprotty-edge arrow" d="M 1,0 L 14,-4 L 14,4 Z" style="fill: #ffffff0a;" transform="rotate(180 657 65) translate(657 65 )"/>
|
||||
<path class="mouse-handle" d="M 560,65 L 657,65" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_sequenceFlow_Sl9ddA_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(608.5, 65) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_iA0M8A" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 504,90 L 504,127 Q 504,137 514,137 L 530,137 Q 540,137 540,147 L 540,180" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_iA0M8A_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(520, 137) translate(0, -3)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_lWHmDQ" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 254,90 L 254,166.8 Q 254,174 261.2,174 L 270,174" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_lWHmDQ_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(254, 140) translate(-3, 0)"/>
|
||||
</g>
|
||||
<g class="sprotty-edge association bpmnedge" id="bpmn-diagram_5_association_pNef4Q" style="fill: none; stroke: #ffffff0a; stroke-width: 1.5px;">
|
||||
<path class="sprotty-edge line" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-dasharray: 4px, 4px;"/>
|
||||
<path class="mouse-handle" d="M 75,83 L 75,233 Q 75,243 85,243 L 538.1,243 Q 544,243 544,237.1 L 544,230" style="stroke-width: 20; stroke: transparent; stroke-dasharray: none; stroke-dashoffset: 0;"/>
|
||||
<text class="heading sprotty-label" id="bpmn-diagram_5_association_pNef4Q_bpmnlabel" style="fill: #ffffff0a; font-family: sans-serif; font-size: 10.6667px; stroke-width: 0px; text-align: center; text-anchor: middle;" transform="translate(236, 243) translate(0, -3)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -1,494 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DYNAMIXS.AI - Die TRUSTED Enterprise AI Platform</title>
|
||||
|
||||
<style>
|
||||
/*
|
||||
*************************************************
|
||||
* CSS-GRUNDLAGEN (Zum schnellen Testen integriert) *
|
||||
*************************************************
|
||||
*/
|
||||
:root {
|
||||
--color-primary: #007bff;
|
||||
/* Starkes Blau */
|
||||
--color-secondary: #28a745;
|
||||
/* Akzent Grün/Akzent */
|
||||
--color-dark: #212529;
|
||||
--color-light: #f8f9fa;
|
||||
--font-family: 'Inter', sans-serif;
|
||||
--section-padding: 80px 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-family);
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding-top: 60px;
|
||||
/* Platz für die Fixed-Navigation */
|
||||
color: var(--color-dark);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
line-height: 1.2;
|
||||
font-weight: 800;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: var(--section-padding);
|
||||
scroll-margin-top: 60px;
|
||||
/* Für smooth scrolling */
|
||||
}
|
||||
|
||||
/* --- Navigation --- */
|
||||
.header-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: var(--color-dark);
|
||||
}
|
||||
|
||||
.nav-menu ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nav-menu ul li a {
|
||||
padding: 10px 15px;
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: var(--color-dark);
|
||||
}
|
||||
|
||||
.nav-menu ul li a:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* --- CTAs --- */
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 12px 25px;
|
||||
margin-top: 10px;
|
||||
border-radius: 5px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
transition: background-color 0.3s;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--color-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: transparent;
|
||||
color: var(--color-primary);
|
||||
border: 2px solid var(--color-primary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--color-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* --- Sektion: Hero/Home --- */
|
||||
#home {
|
||||
background-color: var(--color-light);
|
||||
text-align: center;
|
||||
padding: 100px 0;
|
||||
}
|
||||
|
||||
#home h1 {
|
||||
font-size: 3em;
|
||||
margin-bottom: 10px;
|
||||
color: var(--color-dark);
|
||||
}
|
||||
|
||||
#home .subtitle {
|
||||
font-size: 1.5em;
|
||||
font-weight: 400;
|
||||
margin-bottom: 40px;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.cta-group .btn {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
/* --- Sektion: Problem (Kontrast-Sektion) --- */
|
||||
#problem {
|
||||
background-color: var(--color-dark);
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#problem h2 {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#problem ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#problem ul li {
|
||||
max-width: 250px;
|
||||
text-align: left;
|
||||
padding: 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* --- Sektion: Features (Grid) --- */
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: var(--color-light);
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* --- Sektion: Prozess (Linearer Ablauf) --- */
|
||||
.process-step {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: var(--color-secondary);
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.step-content h3 {
|
||||
margin-top: 0;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* --- Sektion: Ergebnisse (Metriken/Testimonials) --- */
|
||||
.metric-grid {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.metric strong {
|
||||
display: block;
|
||||
font-size: 3em;
|
||||
color: var(--color-primary);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.testimonial-card {
|
||||
background-color: var(--color-light);
|
||||
padding: 30px;
|
||||
border-left: 5px solid var(--color-secondary);
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
/* --- Footer --- */
|
||||
footer {
|
||||
background-color: var(--color-dark);
|
||||
color: white;
|
||||
padding: 40px 0;
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: white;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
/* --- Media Queries für Responsivität --- */
|
||||
@media (max-width: 768px) {
|
||||
.nav-menu ul {
|
||||
display: none;
|
||||
/* Mobile Navigation vereinfacht (Hamburger-Menü würde hier folgen) */
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.header-nav {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#home h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
flex-direction: column;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.cta-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<header class="header-nav">
|
||||
<div class="container nav-content">
|
||||
<div class="logo">DYNAMIXS.AI</div>
|
||||
<nav class="nav-menu">
|
||||
<ul>
|
||||
<li><a href="#home">Start</a></li>
|
||||
<li><a href="#plattform">Plattform</a></li>
|
||||
<li><a href="#prozess">Prozess</a></li>
|
||||
<li><a href="#ergebnisse">Erfolge</a></li>
|
||||
<li><a href="#kontakt" class="btn btn-primary">Demo</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section id="home" class="container">
|
||||
<h1>Ihre Geschäftsprozesse sind einzigartig.<br>Unsere KI versteht sie.</h1>
|
||||
<p class="subtitle">Die **TRUSTED Enterprise AI Platform** – Modellierung, Verbesserung und Automatisierung
|
||||
Ihrer Prozesse, geerdet in Ihrer Business-Realität.</p>
|
||||
|
||||
<div class="cta-group">
|
||||
<a href="#plattform" class="btn btn-primary">Platform kennenlernen</a>
|
||||
<a href="#kontakt" class="btn btn-secondary">Experten sprechen</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="problem">
|
||||
<div class="container">
|
||||
<h2>Warum KI allein nicht genug ist</h2>
|
||||
<p>Ohne den Kontext Ihrer Abläufe bleibt KI eine Black Box. Die häufigsten Herausforderungen:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<i class="fas fa-sitemap"></i>
|
||||
<h3>Verstreute Workflows</h3>
|
||||
<p>Komplexe Abläufe sind über viele Systeme verteilt, Tools halten nicht Schritt.</p>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-database"></i>
|
||||
<h3>Datensilos</h3>
|
||||
<p>Wichtige Informationen sind isoliert, was Entscheidungen verlangsamt und die Zuverlässigkeit
|
||||
mindert.</p>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-lock"></i>
|
||||
<h3>Sicherheitsrisiken</h3>
|
||||
<p>Compliance- und Sicherheitsauflagen limitieren den Einsatz externer, unkontrollierter KI.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="plattform" class="container">
|
||||
<h2>Was DYNAMIXS.AI **anders** macht</h2>
|
||||
<p class="subtitle">Wir starten mit Ihrer Business-Realität. Die DYNAMIXS.AI Plattform ist Ihre **Process
|
||||
Context Engine**:</p>
|
||||
|
||||
<p>Ihre Workflows, Regeln, Dokumente und das Expertenwissen Ihrer Teams werden zusammengeführt, um der KI den
|
||||
notwendigen Kontext zu liefern. Dadurch wird KI **präzise, geschäftsreif und vertrauenswürdig**.</p>
|
||||
|
||||
<img src="placeholder-grafik-context-engine.svg" alt="Visuelle Darstellung der Process Context Engine"
|
||||
style="width: 100%; max-width: 600px; display: block; margin: 40px auto;">
|
||||
|
||||
<a href="#features" class="btn btn-primary">Mehr zu AI Modeling</a>
|
||||
</section>
|
||||
|
||||
<section id="features" class="container">
|
||||
<h2>Drei Säulen für Ihren Erfolg</h2>
|
||||
|
||||
<div class="feature-grid">
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-handshake fa-3x"></i>
|
||||
<h3>Start mit Ihrer Geschäftsrealität</h3>
|
||||
<p>Wir modellieren Prozesse, Daten und Regeln exakt so, wie sie existieren. Ihre individuelle Logik ist
|
||||
die Basis für präzise KI-Aktionen.</p>
|
||||
<a href="#">Mehr erfahren →</a>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-robot fa-3x"></i>
|
||||
<h3>AI transformiert Ihre Prozesse</h3>
|
||||
<p>Ihre Workflows bilden den Rahmen für KI-gesteuerte Entscheidungen: **Smart, Secure und Trusted.** Das
|
||||
System lernt mit jedem Workflow.</p>
|
||||
<a href="#">AI Modeling ansehen →</a>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<i class="fas fa-cogs fa-3x"></i>
|
||||
<h3>Effiziente Anpassung mit Templates</h3>
|
||||
<p>Vordefinierte Bausteine für Finance, HR und Logistik ermöglichen eine schnelle, kosteneffiziente
|
||||
Implementierung in Stunden statt Wochen.</p>
|
||||
<a href="#">Zur Template Library →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="prozess" class="container" style="background-color: var(--color-light);">
|
||||
<h2>In 4 Schritten zur Trusted AI Platform</h2>
|
||||
<p>Von der Vision zur Implementierung – schnell und strukturiert.</p>
|
||||
|
||||
<div class="process-flow">
|
||||
<div class="process-step">
|
||||
<div class="step-number">1</div>
|
||||
<div class="step-content">
|
||||
<h3>Capture your business reality</h3>
|
||||
<p>Ihre Prozesse, Daten und Regeln werden in einem Living Model abgebildet.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<div class="step-number">2</div>
|
||||
<div class="step-content">
|
||||
<h3>Build the workflow model</h3>
|
||||
<p>Eine erste lauffähige Version Ihres Systems ist innerhalb von Stunden einsatzbereit.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<div class="step-number">3</div>
|
||||
<div class="step-content">
|
||||
<h3>Customize with templates</h3>
|
||||
<p>Fertige Komponenten verkürzen die Entwicklungszeit und beschleunigen die Implementierung.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="process-step">
|
||||
<div class="step-number">4</div>
|
||||
<div class="step-content">
|
||||
<h3>Deploy, learn, improve</h3>
|
||||
<p>Nach dem Live-Gang beginnt die kontinuierliche Optimierung durch gesammelte Prozessdaten.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="architektur" class="container">
|
||||
<h2>Enterprise-Ready Architektur</h2>
|
||||
<p>Ein Technologie-Stack, geformt durch zwei Jahrzehnte Enterprise-Projekte, auf den Sie sich verlassen können:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>**Skalierbar:** Event-driven, BPMN-basiert, Cloud-native und API-first.</li>
|
||||
<li>**Geschützt:** Daten sind verschlüsselt, auditierbar und DSGVO-konform.</li>
|
||||
<li>**Bewährt:** Erfolgreich im Einsatz in Logistik, HR, Finance und Government.</li>
|
||||
</ul>
|
||||
<a href="#" class="btn btn-secondary">Architektur im Detail ansehen</a>
|
||||
</section>
|
||||
|
||||
<section id="ergebnisse" class="container" style="background-color: var(--color-light);">
|
||||
<h2>Messbare Erfolge in realen Unternehmen</h2>
|
||||
|
||||
<div class="metric-grid">
|
||||
<div class="metric">
|
||||
<strong>2</strong>
|
||||
<p>Wochen bis zur vollen Integration in vielen Kundenfällen.</p>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<strong>5,000+</strong>
|
||||
<p>Transaktionen und 95 Modelle bei einer Steuerberatung.</p>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<strong>2</strong>
|
||||
<p>Stunden bis zum ersten lauffähigen Modell.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="testimonial-card">
|
||||
<p>“Unglaublich, wie schnell wir unsere Geschäftsprozesse implementiert haben. Die Ergebnisse fließen direkt
|
||||
in unser ERP.”</p>
|
||||
<small>— Kunde, Finance</small>
|
||||
</div>
|
||||
<a href="#" class="btn btn-primary" style="margin-top: 40px;">Alle Erfolgsstories →</a>
|
||||
</section>
|
||||
|
||||
<section id="kontakt" class="container" style="text-align: center;">
|
||||
<h2>Ready to see how?</h2>
|
||||
<p class="subtitle">Nutzen Sie das ungenutzte Intelligenzpotenzial Ihrer Workflows. Wir zeigen Ihnen, wie.</p>
|
||||
|
||||
<a href="#" class="btn btn-primary btn-lg" style="font-size: 1.2em;">Jetzt Beratungstermin vereinbaren</a>
|
||||
<p style="margin-top: 20px;">Oder rufen Sie uns an: +49 (0) XXXX / XXXXXX</p>
|
||||
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="logo">DYNAMIXS.AI</div>
|
||||
<p>© 2025 DYNAMIXS.AI | Alle Rechte vorbehalten.</p>
|
||||
<p>
|
||||
<a href="#">Kontakt</a>
|
||||
<a href="#">Legal / Impressum</a>
|
||||
<a href="#">Datenschutz</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>dynamixs-ai</artifactId>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<version>1.0.1</version>
|
||||
</parent>
|
||||
<artifactId>dynamixs-ai-mcp</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Dynamixs AI MCP Server Library</name>
|
||||
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<!-- use JDK settings for compiling -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.source}</source>
|
||||
<target>${java.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Testing JUnit 5 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
|
||||
|
||||
<!-- issue #572
|
||||
hack for:
|
||||
https://stackoverflow.com/questions/75116023/unable-to-make-protected-final-java-lang-class-java-lang-classloader-defineclass
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<argLine>
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||
</argLine>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Jakarta EE -->
|
||||
<dependency>
|
||||
<groupId>jakarta.platform</groupId>
|
||||
<artifactId>jakarta.jakartaee-api</artifactId>
|
||||
<version>${jakarta.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Microprofile -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.microprofile</groupId>
|
||||
<artifactId>microprofile</artifactId>
|
||||
<version>${microprofile.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs Workflow -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-core</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-engine</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-jax-rs</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-faces</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Testing -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.parsson</groupId>
|
||||
<artifactId>jakarta.json</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,315 +0,0 @@
|
|||
package ai.dynamixs.mcp;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonObjectBuilder;
|
||||
import jakarta.json.JsonString;
|
||||
|
||||
/**
|
||||
* Represents an MCP Resource based on Imixs-Workflow BPMN models.
|
||||
*
|
||||
* MCP Resources represent entities that can be read by the MCP client. Each
|
||||
* resource corresponds to a workflow task/event combination.
|
||||
*/
|
||||
public class MCPResource implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// MCP Standard Fields
|
||||
private String uri; // Resource URI
|
||||
private String name; // Human-readable name
|
||||
private String description; // Resource description
|
||||
private String mimeType; // MIME type of the resource
|
||||
private Map<String, Object> annotations; // Additional metadata
|
||||
|
||||
// Imixs-specific fields
|
||||
private String modelVersion;
|
||||
private int taskId;
|
||||
private int eventId;
|
||||
|
||||
// Constructors
|
||||
public MCPResource() {
|
||||
this.annotations = new HashMap<>();
|
||||
}
|
||||
|
||||
public MCPResource(String modelVersion, int taskId, int eventId) {
|
||||
this();
|
||||
this.modelVersion = modelVersion;
|
||||
this.taskId = taskId;
|
||||
this.eventId = eventId;
|
||||
this.uri = createResourceUri(modelVersion, taskId, eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a resource URI from Imixs workflow components
|
||||
*/
|
||||
public static String createResourceUri(String modelVersion, int taskId, int eventId) {
|
||||
if (modelVersion == null || modelVersion.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("Model version cannot be null or empty");
|
||||
}
|
||||
return String.format("imixs://workflow/%s/%d/%d", modelVersion, taskId, eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses model version from URI
|
||||
*/
|
||||
public String getModelVersionFromUri() {
|
||||
if (uri == null || !uri.startsWith("imixs://workflow/")) {
|
||||
throw new IllegalStateException("Invalid resource URI format: " + uri);
|
||||
}
|
||||
String path = uri.substring("imixs://workflow/".length());
|
||||
String[] parts = path.split("/");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid resource URI format: " + uri);
|
||||
}
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses task ID from URI
|
||||
*/
|
||||
public int getTaskIdFromUri() {
|
||||
if (uri == null || !uri.startsWith("imixs://workflow/")) {
|
||||
throw new IllegalStateException("Invalid resource URI format: " + uri);
|
||||
}
|
||||
String path = uri.substring("imixs://workflow/".length());
|
||||
String[] parts = path.split("/");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid resource URI format: " + uri);
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(parts[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException("Invalid task ID in resource URI: " + uri, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses event ID from URI
|
||||
*/
|
||||
public int getEventIdFromUri() {
|
||||
if (uri == null || !uri.startsWith("imixs://workflow/")) {
|
||||
throw new IllegalStateException("Invalid resource URI format: " + uri);
|
||||
}
|
||||
String path = uri.substring("imixs://workflow/".length());
|
||||
String[] parts = path.split("/");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid resource URI format: " + uri);
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(parts[2]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException("Invalid event ID in resource URI: " + uri, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this resource to MCP JSON format
|
||||
*/
|
||||
public JsonObject toJsonObject() {
|
||||
JsonObjectBuilder builder = Json.createObjectBuilder()
|
||||
.add("uri", uri != null ? uri : "")
|
||||
.add("name", name != null ? name : "")
|
||||
.add("description", description != null ? description : "");
|
||||
|
||||
if (mimeType != null) {
|
||||
builder.add("mimeType", mimeType);
|
||||
}
|
||||
|
||||
// Annotations object
|
||||
if (annotations != null && !annotations.isEmpty()) {
|
||||
JsonObjectBuilder annotationsBuilder = Json.createObjectBuilder();
|
||||
annotations.forEach((key, value) -> {
|
||||
if (value instanceof String) {
|
||||
annotationsBuilder.add(key, (String) value);
|
||||
} else if (value instanceof Number) {
|
||||
annotationsBuilder.add(key, ((Number) value).doubleValue());
|
||||
} else if (value instanceof Boolean) {
|
||||
annotationsBuilder.add(key, (Boolean) value);
|
||||
} else if (value != null) {
|
||||
annotationsBuilder.add(key, value.toString());
|
||||
}
|
||||
});
|
||||
builder.add("annotations", annotationsBuilder.build());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MCPResource from a JsonObject
|
||||
*/
|
||||
public static MCPResource fromJsonObject(JsonObject jsonObject) {
|
||||
MCPResource resource = new MCPResource();
|
||||
|
||||
resource.setUri(jsonObject.getString("uri", ""));
|
||||
resource.setName(jsonObject.getString("name", ""));
|
||||
resource.setDescription(jsonObject.getString("description", ""));
|
||||
|
||||
if (jsonObject.containsKey("mimeType")) {
|
||||
resource.setMimeType(jsonObject.getString("mimeType"));
|
||||
}
|
||||
|
||||
// Annotations
|
||||
if (jsonObject.containsKey("annotations")) {
|
||||
JsonObject annotationsObject = jsonObject.getJsonObject("annotations");
|
||||
Map<String, Object> annotations = new HashMap<>();
|
||||
annotationsObject.forEach((key, value) -> {
|
||||
switch (value.getValueType()) {
|
||||
case STRING:
|
||||
annotations.put(key, ((JsonString) value).getString());
|
||||
break;
|
||||
case NUMBER:
|
||||
annotations.put(key, ((jakarta.json.JsonNumber) value).doubleValue());
|
||||
break;
|
||||
case TRUE:
|
||||
annotations.put(key, Boolean.TRUE);
|
||||
break;
|
||||
case FALSE:
|
||||
annotations.put(key, Boolean.FALSE);
|
||||
break;
|
||||
default:
|
||||
annotations.put(key, value.toString());
|
||||
}
|
||||
});
|
||||
resource.setAnnotations(annotations);
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates this resource for MCP compliance
|
||||
*/
|
||||
public boolean isValid() {
|
||||
if (uri == null || uri.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate URI format
|
||||
try {
|
||||
getModelVersionFromUri();
|
||||
getTaskIdFromUri();
|
||||
getEventIdFromUri();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
public void setMimeType(String mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
public void setAnnotations(Map<String, Object> annotations) {
|
||||
this.annotations = annotations != null ? annotations : new HashMap<>();
|
||||
}
|
||||
|
||||
public String getModelVersion() {
|
||||
return modelVersion;
|
||||
}
|
||||
|
||||
public void setModelVersion(String modelVersion) {
|
||||
this.modelVersion = modelVersion;
|
||||
}
|
||||
|
||||
public int getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(int taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public int getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public void setEventId(int eventId) {
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
// Convenience methods for annotations
|
||||
public void addAnnotation(String key, Object value) {
|
||||
if (annotations == null) {
|
||||
annotations = new HashMap<>();
|
||||
}
|
||||
annotations.put(key, value);
|
||||
}
|
||||
|
||||
public String getAnnotationString(String key) {
|
||||
Object value = annotations != null ? annotations.get(key) : null;
|
||||
return value != null ? value.toString() : null;
|
||||
}
|
||||
|
||||
public Boolean getAnnotationBoolean(String key) {
|
||||
Object value = annotations != null ? annotations.get(key) : null;
|
||||
if (value instanceof Boolean) {
|
||||
return (Boolean) value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MCPResource{uri='%s', name='%s', modelVersion='%s', taskId=%d, eventId=%d}",
|
||||
uri, name, modelVersion, taskId, eventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
MCPResource that = (MCPResource) obj;
|
||||
return uri != null ? uri.equals(that.uri) : that.uri == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return uri != null ? uri.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,434 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Imixs Workflow
|
||||
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public
|
||||
* License at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Project:
|
||||
* http://www.imixs.org
|
||||
* http://java.net/projects/imixs-workflow
|
||||
*
|
||||
* Contributors:
|
||||
* Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika - Software Developer
|
||||
*******************************************************************************/
|
||||
|
||||
package ai.dynamixs.mcp;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonArray;
|
||||
import jakarta.json.JsonArrayBuilder;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonObjectBuilder;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
|
||||
/**
|
||||
* The MCPRestService provides Model Context Protocol (MCP) endpoints for
|
||||
* accessing workflow resources and tools.
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
@Named
|
||||
@RequestScoped
|
||||
@Path("/mcp/")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public class MCPRestService implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Logger logger = Logger.getLogger(MCPRestService.class.getSimpleName());
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
|
||||
@Inject
|
||||
MCPService mcpService;
|
||||
|
||||
/**
|
||||
* MCP JSON-RPC 2.0 Endpoint All MCP protocol methods are handled here URL:
|
||||
* /mcp/v1
|
||||
*/
|
||||
@POST
|
||||
@Path("/v1")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response handleJsonRpcRequest(JsonObject request) {
|
||||
try {
|
||||
// Validate JSON-RPC 2.0 structure
|
||||
if (!isValidJsonRpcRequest(request)) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(buildJsonRpcError(-32600, "Invalid Request", null))
|
||||
.build();
|
||||
}
|
||||
|
||||
String method = request.getString("method");
|
||||
Object id = request.get("id");
|
||||
JsonObject params = request.containsKey("params") ? request.getJsonObject("params") : null;
|
||||
|
||||
// Route to appropriate MCP method
|
||||
switch (method) {
|
||||
case "initialize":
|
||||
return handleInitialize(id, params);
|
||||
case "resources/list":
|
||||
return handleResourcesList(id, params);
|
||||
case "resources/read":
|
||||
return handleResourcesRead(id, params);
|
||||
case "tools/list":
|
||||
return handleToolsList(id, params);
|
||||
case "tools/call":
|
||||
return handleToolsCall(id, params);
|
||||
default:
|
||||
return Response.status(Response.Status.NOT_FOUND)
|
||||
.entity(buildJsonRpcError(-32601, "Method not found", id))
|
||||
.build();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error processing MCP JSON-RPC request: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", null))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle MCP initialize method
|
||||
*/
|
||||
private Response handleInitialize(Object id, JsonObject params) {
|
||||
try {
|
||||
// Build server capabilities
|
||||
JsonObject capabilities = Json.createObjectBuilder()
|
||||
.add("resources", Json.createObjectBuilder()
|
||||
.add("subscribe", false)
|
||||
.add("listChanged", false)
|
||||
.build())
|
||||
.add("tools", Json.createObjectBuilder().build())
|
||||
.add("logging", Json.createObjectBuilder().build())
|
||||
.build();
|
||||
|
||||
// Build server information
|
||||
JsonObject serverInfo = Json.createObjectBuilder()
|
||||
.add("name", "Dynamixs.AI MCP Server")
|
||||
.add("version", "1.0.0")
|
||||
.build();
|
||||
|
||||
JsonObject result = Json.createObjectBuilder()
|
||||
.add("protocolVersion", "2024-11-05")
|
||||
.add("capabilities", capabilities)
|
||||
.add("serverInfo", serverInfo)
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", result)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in initialize: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle MCP resources/list method
|
||||
*/
|
||||
private Response handleResourcesList(Object id, JsonObject params) {
|
||||
try {
|
||||
List<MCPResource> resources = mcpService.parseResources();
|
||||
|
||||
List<MCPResource> validResources = resources.stream()
|
||||
.filter(MCPResource::isValid)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
JsonArray resourcesArray = validResources.stream()
|
||||
.map(MCPResource::toJsonObject)
|
||||
.collect(Json::createArrayBuilder,
|
||||
JsonArrayBuilder::add,
|
||||
JsonArrayBuilder::addAll)
|
||||
.build();
|
||||
|
||||
JsonObject result = Json.createObjectBuilder()
|
||||
.add("resources", resourcesArray)
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", result)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in resources/list: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle MCP resources/read method
|
||||
*/
|
||||
private Response handleResourcesRead(Object id, JsonObject params) {
|
||||
try {
|
||||
if (params == null || !params.containsKey("uri")) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(buildJsonRpcError(-32602, "Invalid params: missing uri", id))
|
||||
.build();
|
||||
}
|
||||
|
||||
String uri = params.getString("uri");
|
||||
String content = mcpService.readResource(uri);
|
||||
|
||||
JsonObject result = Json.createObjectBuilder()
|
||||
.add("contents", Json.createArrayBuilder()
|
||||
.add(Json.createObjectBuilder()
|
||||
.add("uri", uri)
|
||||
.add("mimeType", "text/plain")
|
||||
.add("text", content)
|
||||
.build())
|
||||
.build())
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", result)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in resources/read: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32001, "Resource not found", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle MCP tools/list method
|
||||
*/
|
||||
private Response handleToolsList(Object id, JsonObject params) {
|
||||
try {
|
||||
List<MCPTool> tools = mcpService.parseTools();
|
||||
|
||||
List<MCPTool> validTools = tools.stream()
|
||||
.filter(MCPTool::isValid)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
JsonArray toolsArray = validTools.stream()
|
||||
.map(MCPTool::toJsonObject)
|
||||
.collect(Json::createArrayBuilder,
|
||||
JsonArrayBuilder::add,
|
||||
JsonArrayBuilder::addAll)
|
||||
.build();
|
||||
|
||||
JsonObject result = Json.createObjectBuilder()
|
||||
.add("tools", toolsArray)
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", result)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in tools/list: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(buildJsonRpcError(-32603, "Internal server error", id))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle MCP tools/call method
|
||||
*/
|
||||
private Response handleToolsCall(Object id, JsonObject params) {
|
||||
try {
|
||||
if (params == null || !params.containsKey("name")) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(buildJsonRpcError(-32602, "Invalid params: missing name", id))
|
||||
.build();
|
||||
}
|
||||
|
||||
String toolName = params.getString("name");
|
||||
JsonObject arguments = params.containsKey("arguments") ? params.getJsonObject("arguments")
|
||||
: Json.createObjectBuilder().build();
|
||||
|
||||
// Convert JSON arguments to ItemCollection
|
||||
ItemCollection workitem = jsonToItemCollection(arguments);
|
||||
|
||||
// Execute the tool
|
||||
ItemCollection result = mcpService.executeTool(toolName, workitem);
|
||||
|
||||
// Convert result back to JSON
|
||||
JsonObject toolResult = itemCollectionToJson(result);
|
||||
|
||||
// Build MCP response with content array
|
||||
JsonObject mcpResult = Json.createObjectBuilder()
|
||||
.add("content", Json.createArrayBuilder()
|
||||
.add(Json.createObjectBuilder()
|
||||
.add("type", "text")
|
||||
.add("text", "Tool executed successfully. Result: " + toolResult.toString())
|
||||
.build())
|
||||
.build())
|
||||
.add("isError", false)
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", mcpResult)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error in tools/call: " + e.getMessage());
|
||||
|
||||
// Return error content in MCP format
|
||||
JsonObject errorResult = Json.createObjectBuilder()
|
||||
.add("content", Json.createArrayBuilder()
|
||||
.add(Json.createObjectBuilder()
|
||||
.add("type", "text")
|
||||
.add("text", "Tool execution failed: " + e.getMessage())
|
||||
.build())
|
||||
.build())
|
||||
.add("isError", true)
|
||||
.build();
|
||||
|
||||
JsonObject response = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("id", id.toString())
|
||||
.add("result", errorResult)
|
||||
.build();
|
||||
|
||||
return Response.ok(response).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates JSON-RPC 2.0 request structure
|
||||
*/
|
||||
private boolean isValidJsonRpcRequest(JsonObject request) {
|
||||
return request.containsKey("jsonrpc") &&
|
||||
"2.0".equals(request.getString("jsonrpc")) &&
|
||||
request.containsKey("method") &&
|
||||
request.containsKey("id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a JSON-RPC 2.0 error response
|
||||
*/
|
||||
private JsonObject buildJsonRpcError(int code, String message, Object id) {
|
||||
JsonObjectBuilder errorBuilder = Json.createObjectBuilder()
|
||||
.add("code", code)
|
||||
.add("message", message);
|
||||
|
||||
JsonObjectBuilder responseBuilder = Json.createObjectBuilder()
|
||||
.add("jsonrpc", "2.0")
|
||||
.add("error", errorBuilder.build());
|
||||
|
||||
if (id != null) {
|
||||
responseBuilder.add("id", id.toString());
|
||||
} else {
|
||||
responseBuilder.addNull("id");
|
||||
}
|
||||
|
||||
return responseBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JSON object to an ItemCollection
|
||||
*/
|
||||
private ItemCollection jsonToItemCollection(JsonObject jsonObject) {
|
||||
ItemCollection itemCol = new ItemCollection();
|
||||
|
||||
if (jsonObject.containsKey("workitem")) {
|
||||
JsonObject workitem = jsonObject.getJsonObject("workitem");
|
||||
workitem.forEach((key, value) -> {
|
||||
switch (value.getValueType()) {
|
||||
case STRING:
|
||||
itemCol.setItemValue(key, ((jakarta.json.JsonString) value).getString());
|
||||
break;
|
||||
case NUMBER:
|
||||
itemCol.setItemValue(key, ((jakarta.json.JsonNumber) value).intValue());
|
||||
break;
|
||||
case TRUE:
|
||||
itemCol.setItemValue(key, Boolean.TRUE);
|
||||
break;
|
||||
case FALSE:
|
||||
itemCol.setItemValue(key, Boolean.FALSE);
|
||||
break;
|
||||
default:
|
||||
itemCol.setItemValue(key, value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return itemCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an ItemCollection to a JSON object
|
||||
*/
|
||||
private JsonObject itemCollectionToJson(ItemCollection itemCol) {
|
||||
JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||
|
||||
for (String itemName : itemCol.getItemNames()) {
|
||||
Object value = itemCol.getItemValue(itemName);
|
||||
if (value instanceof String) {
|
||||
builder.add(itemName, (String) value);
|
||||
} else if (value instanceof Integer) {
|
||||
builder.add(itemName, (Integer) value);
|
||||
} else if (value instanceof Double) {
|
||||
builder.add(itemName, (Double) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
builder.add(itemName, (Boolean) value);
|
||||
} else if (value != null) {
|
||||
builder.add(itemName, value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
package ai.dynamixs.mcp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.ModelManager;
|
||||
import org.imixs.workflow.engine.ModelService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.ModelException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.openbpmn.bpmn.BPMNModel;
|
||||
|
||||
import jakarta.annotation.security.DeclareRoles;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.ejb.LocalBean;
|
||||
import jakarta.ejb.Stateless;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* The MCPService parses the model information to provide MCP Resources and
|
||||
* Tools
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
@DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS",
|
||||
"org.imixs.ACCESSLEVEL.READERACCESS",
|
||||
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.EDITORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@RolesAllowed({ "org.imixs.ACCESSLEVEL.NOACCESS",
|
||||
"org.imixs.ACCESSLEVEL.READERACCESS",
|
||||
"org.imixs.ACCESSLEVEL.AUTHORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.EDITORACCESS",
|
||||
"org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@Stateless
|
||||
@LocalBean
|
||||
public class MCPService {
|
||||
|
||||
@Inject
|
||||
ModelService modelService;
|
||||
|
||||
@Inject
|
||||
WorkflowService workflowService;
|
||||
|
||||
private static Logger logger = Logger.getLogger(MCPService.class.getName());
|
||||
|
||||
/**
|
||||
* This method iterates over all models and returns a list of MCP resources
|
||||
*
|
||||
* The method looks for events with <imixs-ai name="RESOURCE"> tag.
|
||||
*/
|
||||
public List<MCPResource> parseResources() {
|
||||
logger.log(Level.INFO, "├── 🔃 parsing MCP Resources....");
|
||||
List<MCPResource> result = new ArrayList<>();
|
||||
ModelManager modelManager = new ModelManager(workflowService);
|
||||
List<String> versions = modelService.getVersions();
|
||||
|
||||
try {
|
||||
for (String version : versions) {
|
||||
logger.log(Level.INFO, "│ ├── {0}", version);
|
||||
BPMNModel model = modelManager.getModel(version);
|
||||
|
||||
Set<String> groups = modelManager.findAllGroupsByModel(model);
|
||||
for (String group : groups) {
|
||||
List<ItemCollection> tasks = modelManager.findTasks(model, group);
|
||||
for (ItemCollection task : tasks) {
|
||||
int taskID = task.getItemValueInteger("taskid");
|
||||
List<ItemCollection> events = modelManager.findEventsByTask(model, taskID);
|
||||
|
||||
for (ItemCollection event : events) {
|
||||
int eventID = event.getItemValueInteger("eventid");
|
||||
// test if we have a <imixs-ai name="RESOURCE">
|
||||
try {
|
||||
List<ItemCollection> resourceDefinitions = workflowService.evalWorkflowResultXML(
|
||||
event, "imixs-ai", "RESOURCE", null, false);
|
||||
|
||||
// did we found a resource?
|
||||
for (ItemCollection resourceItemCol : resourceDefinitions) {
|
||||
MCPResource resource = new MCPResource(version, taskID, eventID);
|
||||
|
||||
resource.setName(event.getItemValueString("name"));
|
||||
resource.setDescription(resourceItemCol.getItemValueString("description"));
|
||||
|
||||
resource.setMimeType("text/plain");
|
||||
|
||||
// Add annotations
|
||||
String tags = resourceItemCol.getItemValueString("tags");
|
||||
if (tags != null && !tags.isBlank()) {
|
||||
resource.addAnnotation("tags", tags);
|
||||
}
|
||||
|
||||
String category = resourceItemCol.getItemValueString("category");
|
||||
if (category != null && !category.isBlank()) {
|
||||
resource.addAnnotation("category", category);
|
||||
}
|
||||
|
||||
if (resource.isValid()) {
|
||||
result.add(resource);
|
||||
logger.log(Level.INFO, "│ │ ├── Resource: {0}", resource.getUri());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (PluginException e) {
|
||||
// no match
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ModelException e) {
|
||||
logger.log(Level.SEVERE, "Error parsing models for resources", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method iterates over all models and returns a list of MCP tools
|
||||
*
|
||||
* The method looks for events with <imixs-ai name="TOOL"> tag.
|
||||
*/
|
||||
public List<MCPTool> parseTools() {
|
||||
logger.log(Level.INFO, "├── 🔃 parsing MCP Tools....");
|
||||
List<MCPTool> result = new ArrayList<>();
|
||||
ModelManager modelManager = new ModelManager(workflowService);
|
||||
List<String> versions = modelService.getVersions();
|
||||
|
||||
try {
|
||||
for (String version : versions) {
|
||||
logger.log(Level.INFO, "│ ├── {0}", version);
|
||||
BPMNModel model = modelManager.getModel(version);
|
||||
|
||||
Set<String> groups = modelManager.findAllGroupsByModel(model);
|
||||
for (String group : groups) {
|
||||
List<ItemCollection> tasks = modelManager.findTasks(model, group);
|
||||
for (ItemCollection task : tasks) {
|
||||
int taskID = task.getItemValueInteger("taskid");
|
||||
List<ItemCollection> events = modelManager.findEventsByTask(model, taskID);
|
||||
|
||||
for (ItemCollection event : events) {
|
||||
int eventID = event.getItemValueInteger("eventid");
|
||||
// test if we have a <imixs-ai name="TOOL">
|
||||
try {
|
||||
List<ItemCollection> toolDefinitions = workflowService.evalWorkflowResultXML(
|
||||
event, "imixs-ai", "TOOL", null, false);
|
||||
|
||||
// did we found a tool?
|
||||
for (ItemCollection toolItemCol : toolDefinitions) {
|
||||
MCPTool tool = new MCPTool(version, taskID, eventID);
|
||||
|
||||
String toolName = version + "_" + taskID + "_" + eventID;// toolItemCol.getItemValueString("name");
|
||||
if (toolName != null && !toolName.isBlank()) {
|
||||
tool.setName(toolName);
|
||||
}
|
||||
|
||||
tool.setDescription(toolItemCol.getItemValueString("description"));
|
||||
|
||||
String tags = toolItemCol.getItemValueString("tags");
|
||||
if (tags != null && !tags.isBlank()) {
|
||||
String[] parts = tags.split(",\\s*");
|
||||
tool.setTags(Arrays.asList(parts));
|
||||
}
|
||||
|
||||
tool.setExamples(toolItemCol.getItemValueList("example", String.class));
|
||||
|
||||
if (tool.isValid()) {
|
||||
result.add(tool);
|
||||
logger.log(Level.INFO, "│ │ ├── Tool: {0}", tool.getName());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (PluginException e) {
|
||||
// no match
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ModelException e) {
|
||||
logger.log(Level.SEVERE, "Error parsing models for tools", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a workflow tool with the given arguments
|
||||
*/
|
||||
public ItemCollection executeTool(String toolName, ItemCollection workitem) throws Exception {
|
||||
logger.log(Level.INFO, "├── 🔧 executing MCP Tool: {0}", toolName);
|
||||
|
||||
// Parse tool name to extract workflow parameters
|
||||
MCPTool tool = new MCPTool();
|
||||
tool.setName(toolName);
|
||||
|
||||
String modelVersion = tool.getModelVersionFromName();
|
||||
int taskId = tool.getTaskIdFromName();
|
||||
int eventId = tool.getEventIdFromName();
|
||||
|
||||
// Set workflow parameters
|
||||
workitem.setItemValue("$modelversion", modelVersion);
|
||||
workitem.setItemValue("$taskid", taskId);
|
||||
workitem.setItemValue("$eventid", eventId);
|
||||
|
||||
// Process the workitem
|
||||
ItemCollection result = workflowService.processWorkItem(workitem);
|
||||
|
||||
logger.log(Level.INFO, "│ └── Tool execution completed");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the content of a resource
|
||||
*/
|
||||
public String readResource(String uri) throws Exception {
|
||||
logger.log(Level.INFO, "├── 📖 reading MCP Resource: {0}", uri);
|
||||
|
||||
// Parse URI to extract workflow parameters
|
||||
MCPResource resource = new MCPResource();
|
||||
resource.setUri(uri);
|
||||
|
||||
String modelVersion = resource.getModelVersionFromUri();
|
||||
int taskId = resource.getTaskIdFromUri();
|
||||
int eventId = resource.getEventIdFromUri();
|
||||
|
||||
// Create a workitem to read the resource
|
||||
ItemCollection workitem = new ItemCollection();
|
||||
workitem.setItemValue("$modelversion", modelVersion);
|
||||
workitem.setItemValue("$taskid", taskId);
|
||||
workitem.setItemValue("$eventid", eventId);
|
||||
|
||||
// Get the event definition to extract resource content
|
||||
ModelManager modelManager = new ModelManager(workflowService);
|
||||
BPMNModel model = modelManager.getModel(modelVersion);
|
||||
ItemCollection event = modelManager.findEventByID(model, taskId, eventId);
|
||||
|
||||
if (event == null) {
|
||||
throw new Exception("Event not found: " + uri);
|
||||
}
|
||||
|
||||
// Look for resource content in the event
|
||||
try {
|
||||
List<ItemCollection> resourceDefinitions = workflowService.evalWorkflowResultXML(
|
||||
event, "imixs-ai", "RESOURCE", null, false);
|
||||
|
||||
if (!resourceDefinitions.isEmpty()) {
|
||||
ItemCollection resourceDef = resourceDefinitions.get(0);
|
||||
String content = resourceDef.getItemValueString("content");
|
||||
if (content != null && !content.isBlank()) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
} catch (PluginException e) {
|
||||
// no resource definition found
|
||||
}
|
||||
|
||||
// Fallback: return event documentation
|
||||
String documentation = event.getItemValueString("documentation");
|
||||
if (documentation != null && !documentation.isBlank()) {
|
||||
return documentation;
|
||||
}
|
||||
|
||||
// Last fallback: return event name and description
|
||||
return String.format("Event: %s\nDescription: %s",
|
||||
event.getItemValueString("name"),
|
||||
event.getItemValueString("description"));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,254 +0,0 @@
|
|||
package ai.dynamixs.mcp;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonArrayBuilder;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
|
||||
/**
|
||||
* Test endpoint for MCP server discovery and debugging Similar to A2A Agent
|
||||
* Card but for MCP protocol
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
@Named
|
||||
@RequestScoped
|
||||
@Path("/mcp/debug/")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public class MCPTestEndpoint implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Logger logger = Logger.getLogger(MCPTestEndpoint.class.getSimpleName());
|
||||
|
||||
@Context
|
||||
UriInfo uriInfo;
|
||||
|
||||
@Inject
|
||||
MCPService mcpService;
|
||||
|
||||
/**
|
||||
* MCP Server Information Endpoint (similar to A2A Agent Card) URL:
|
||||
* /mcp/server-info
|
||||
*/
|
||||
@GET
|
||||
@Path("/server-info")
|
||||
public Response getServerInfo() {
|
||||
try {
|
||||
JsonObject serverInfo = buildServerInfo();
|
||||
return Response.ok(serverInfo).build();
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error creating MCP server info: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(Json.createObjectBuilder()
|
||||
.add("error", "Internal server error")
|
||||
.add("message", e.getMessage())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick test endpoint to list all available resources URL: /mcp/test/resources
|
||||
*/
|
||||
@GET
|
||||
@Path("/test/resources")
|
||||
public Response testResources() {
|
||||
try {
|
||||
List<MCPResource> resources = mcpService.parseResources();
|
||||
|
||||
JsonArrayBuilder resourcesBuilder = Json.createArrayBuilder();
|
||||
for (MCPResource resource : resources) {
|
||||
if (resource.isValid()) {
|
||||
resourcesBuilder.add(resource.toJsonObject());
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject result = Json.createObjectBuilder()
|
||||
.add("status", "success")
|
||||
.add("count", resources.size())
|
||||
.add("resources", resourcesBuilder.build())
|
||||
.build();
|
||||
|
||||
return Response.ok(result).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error testing resources: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(Json.createObjectBuilder()
|
||||
.add("error", "Failed to parse resources")
|
||||
.add("message", e.getMessage())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick test endpoint to list all available tools URL: /mcp/test/tools
|
||||
*/
|
||||
@GET
|
||||
@Path("/test/tools")
|
||||
public Response testTools() {
|
||||
try {
|
||||
List<MCPTool> tools = mcpService.parseTools();
|
||||
|
||||
JsonArrayBuilder toolsBuilder = Json.createArrayBuilder();
|
||||
for (MCPTool tool : tools) {
|
||||
if (tool.isValid()) {
|
||||
toolsBuilder.add(tool.toJsonObject());
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject result = Json.createObjectBuilder()
|
||||
.add("status", "success")
|
||||
.add("count", tools.size())
|
||||
.add("tools", toolsBuilder.build())
|
||||
.build();
|
||||
|
||||
return Response.ok(result).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Error testing tools: " + e.getMessage());
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
|
||||
.entity(Json.createObjectBuilder()
|
||||
.add("error", "Failed to parse tools")
|
||||
.add("message", e.getMessage())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Health check endpoint URL: /mcp/health
|
||||
*/
|
||||
@GET
|
||||
@Path("/health")
|
||||
public Response healthCheck() {
|
||||
try {
|
||||
List<MCPResource> resources = mcpService.parseResources();
|
||||
List<MCPTool> tools = mcpService.parseTools();
|
||||
|
||||
JsonObject health = Json.createObjectBuilder()
|
||||
.add("status", "healthy")
|
||||
.add("timestamp", java.time.Instant.now().toString())
|
||||
.add("server", "Dynamixs.AI MCP Server")
|
||||
.add("version", "1.0.0")
|
||||
.add("protocol", "MCP 2024-11-05")
|
||||
.add("endpoint", getBaseUrl() + "mcp/v1")
|
||||
.add("resources_count", resources.size())
|
||||
.add("tools_count", tools.size())
|
||||
.build();
|
||||
|
||||
return Response.ok(health).build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.severe("Health check failed: " + e.getMessage());
|
||||
return Response.status(Response.Status.SERVICE_UNAVAILABLE)
|
||||
.entity(Json.createObjectBuilder()
|
||||
.add("status", "unhealthy")
|
||||
.add("error", e.getMessage())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds comprehensive server information (MCP equivalent of A2A Agent Card)
|
||||
*/
|
||||
private JsonObject buildServerInfo() {
|
||||
List<MCPResource> resources = mcpService.parseResources();
|
||||
List<MCPTool> tools = mcpService.parseTools();
|
||||
|
||||
// Server capabilities
|
||||
JsonObject capabilities = Json.createObjectBuilder()
|
||||
.add("resources", Json.createObjectBuilder()
|
||||
.add("subscribe", false)
|
||||
.add("listChanged", false)
|
||||
.build())
|
||||
.add("tools", Json.createObjectBuilder().build())
|
||||
.add("logging", Json.createObjectBuilder().build())
|
||||
.build();
|
||||
|
||||
// Protocol information
|
||||
JsonObject protocol = Json.createObjectBuilder()
|
||||
.add("name", "Model Context Protocol")
|
||||
.add("version", "2024-11-05")
|
||||
.add("transport", "HTTP/JSON-RPC 2.0")
|
||||
.build();
|
||||
|
||||
// Server metadata
|
||||
JsonObject server = Json.createObjectBuilder()
|
||||
.add("name", "Dynamixs.AI MCP Server")
|
||||
.add("version", "1.0.0")
|
||||
.add("description", "MCP server for Imixs-Workflow BPM platform")
|
||||
.add("vendor", "Dynamixs.AI")
|
||||
.add("platform", "Jakarta EE 10 / Imixs-Workflow")
|
||||
.build();
|
||||
|
||||
// Endpoints
|
||||
JsonObject endpoints = Json.createObjectBuilder()
|
||||
.add("jsonrpc", getBaseUrl() + "mcp/v1")
|
||||
.add("health", getBaseUrl() + "mcp/health")
|
||||
.add("server_info", getBaseUrl() + "mcp/server-info")
|
||||
.add("test_resources", getBaseUrl() + "mcp/test/resources")
|
||||
.add("test_tools", getBaseUrl() + "mcp/test/tools")
|
||||
.build();
|
||||
|
||||
// Statistics
|
||||
JsonObject statistics = Json.createObjectBuilder()
|
||||
.add("resources_available", resources.size())
|
||||
.add("tools_available", tools.size())
|
||||
.add("last_updated", java.time.Instant.now().toString())
|
||||
.build();
|
||||
|
||||
// Resource summary
|
||||
JsonArrayBuilder resourceSummary = Json.createArrayBuilder();
|
||||
for (MCPResource resource : resources) {
|
||||
if (resource.isValid()) {
|
||||
resourceSummary.add(Json.createObjectBuilder()
|
||||
.add("uri", resource.getUri())
|
||||
.add("name", resource.getName())
|
||||
.add("mimeType", resource.getMimeType() != null ? resource.getMimeType() : "text/plain")
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
// Tool summary
|
||||
JsonArrayBuilder toolSummary = Json.createArrayBuilder();
|
||||
for (MCPTool tool : tools) {
|
||||
if (tool.isValid()) {
|
||||
toolSummary.add(Json.createObjectBuilder()
|
||||
.add("name", tool.getName())
|
||||
.add("description", tool.getDescription())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
// Build complete server info
|
||||
return Json.createObjectBuilder()
|
||||
.add("protocol", protocol)
|
||||
.add("server", server)
|
||||
.add("capabilities", capabilities)
|
||||
.add("endpoints", endpoints)
|
||||
.add("statistics", statistics)
|
||||
.add("resource_summary", resourceSummary.build())
|
||||
.add("tool_summary", toolSummary.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private String getBaseUrl() {
|
||||
return uriInfo.getBaseUri().toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,283 +0,0 @@
|
|||
package ai.dynamixs.mcp;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonObjectBuilder;
|
||||
|
||||
/**
|
||||
* Represents an MCP Tool based on Imixs-Workflow BPMN models.
|
||||
*
|
||||
* MCP Tools represent functions that can be called by the MCP client. Each tool
|
||||
* corresponds to a workflow task/event combination.
|
||||
*/
|
||||
public class MCPTool implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// MCP Standard Fields
|
||||
private String name; // Tool name/identifier
|
||||
private String description; // Tool description
|
||||
private JsonObject inputSchema; // JSON Schema for input parameters
|
||||
|
||||
// Imixs-specific fields
|
||||
private String modelVersion;
|
||||
private int taskId;
|
||||
private int eventId;
|
||||
private List<String> tags;
|
||||
private List<String> examples;
|
||||
|
||||
// Constructors
|
||||
public MCPTool() {
|
||||
this.tags = new ArrayList<>();
|
||||
this.examples = new ArrayList<>();
|
||||
}
|
||||
|
||||
public MCPTool(String modelVersion, int taskId, int eventId) {
|
||||
this();
|
||||
this.modelVersion = modelVersion;
|
||||
this.taskId = taskId;
|
||||
this.eventId = eventId;
|
||||
this.name = createToolName(modelVersion, taskId, eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tool name from Imixs workflow components
|
||||
*/
|
||||
public static String createToolName(String modelVersion, int taskId, int eventId) {
|
||||
if (modelVersion == null || modelVersion.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("Model version cannot be null or empty");
|
||||
}
|
||||
return String.format("%s_%d_%d", modelVersion.replace("-", "_"), taskId, eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses model version from tool name
|
||||
*/
|
||||
public String getModelVersionFromName() {
|
||||
if (name == null || !name.contains("_")) {
|
||||
throw new IllegalStateException("Invalid tool name format: " + name);
|
||||
}
|
||||
return name.substring(0, name.lastIndexOf('_', name.lastIndexOf('_') - 1)).replace("_", "-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses task ID from tool name
|
||||
*/
|
||||
public int getTaskIdFromName() {
|
||||
if (name == null || !name.contains("_")) {
|
||||
throw new IllegalStateException("Invalid tool name format: " + name);
|
||||
}
|
||||
String[] parts = name.split("_");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid tool name format: " + name);
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(parts[parts.length - 2]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException("Invalid task ID in tool name: " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses event ID from tool name
|
||||
*/
|
||||
public int getEventIdFromName() {
|
||||
if (name == null || !name.contains("_")) {
|
||||
throw new IllegalStateException("Invalid tool name format: " + name);
|
||||
}
|
||||
String[] parts = name.split("_");
|
||||
if (parts.length < 3) {
|
||||
throw new IllegalStateException("Invalid tool name format: " + name);
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(parts[parts.length - 1]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalStateException("Invalid event ID in tool name: " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default input schema for workflow tools
|
||||
*/
|
||||
public JsonObject createDefaultInputSchema() {
|
||||
return Json.createObjectBuilder()
|
||||
.add("type", "object")
|
||||
.add("properties", Json.createObjectBuilder()
|
||||
.add("workitem", Json.createObjectBuilder()
|
||||
.add("type", "object")
|
||||
.add("description", "Workflow item data")
|
||||
.add("properties", Json.createObjectBuilder()
|
||||
.add("$modelversion", Json.createObjectBuilder()
|
||||
.add("type", "string")
|
||||
.add("description", "Workflow model version")
|
||||
.build())
|
||||
.add("$taskid", Json.createObjectBuilder()
|
||||
.add("type", "integer")
|
||||
.add("description", "Task ID")
|
||||
.build())
|
||||
.add("$eventid", Json.createObjectBuilder()
|
||||
.add("type", "integer")
|
||||
.add("description", "Event ID")
|
||||
.build())
|
||||
.build())
|
||||
.add("required", Json.createArrayBuilder()
|
||||
.add("$modelversion")
|
||||
.add("$taskid")
|
||||
.add("$eventid")
|
||||
.build())
|
||||
.build())
|
||||
.build())
|
||||
.add("required", Json.createArrayBuilder()
|
||||
.add("workitem")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this tool to MCP JSON format
|
||||
*/
|
||||
public JsonObject toJsonObject() {
|
||||
JsonObjectBuilder builder = Json.createObjectBuilder()
|
||||
.add("name", name != null ? name : "")
|
||||
.add("description", description != null ? description : "");
|
||||
|
||||
// Input schema
|
||||
if (inputSchema != null) {
|
||||
builder.add("inputSchema", inputSchema);
|
||||
} else {
|
||||
builder.add("inputSchema", createDefaultInputSchema());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MCPTool from a JsonObject
|
||||
*/
|
||||
public static MCPTool fromJsonObject(JsonObject jsonObject) {
|
||||
MCPTool tool = new MCPTool();
|
||||
|
||||
tool.setName(jsonObject.getString("name", ""));
|
||||
tool.setDescription(jsonObject.getString("description", ""));
|
||||
|
||||
if (jsonObject.containsKey("inputSchema")) {
|
||||
tool.setInputSchema(jsonObject.getJsonObject("inputSchema"));
|
||||
}
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates this tool for MCP compliance
|
||||
*/
|
||||
public boolean isValid() {
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (description == null || description.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate tool name format
|
||||
try {
|
||||
getModelVersionFromName();
|
||||
getTaskIdFromName();
|
||||
getEventIdFromName();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public JsonObject getInputSchema() {
|
||||
return inputSchema;
|
||||
}
|
||||
|
||||
public void setInputSchema(JsonObject inputSchema) {
|
||||
this.inputSchema = inputSchema;
|
||||
}
|
||||
|
||||
public String getModelVersion() {
|
||||
return modelVersion;
|
||||
}
|
||||
|
||||
public void setModelVersion(String modelVersion) {
|
||||
this.modelVersion = modelVersion;
|
||||
}
|
||||
|
||||
public int getTaskId() {
|
||||
return taskId;
|
||||
}
|
||||
|
||||
public void setTaskId(int taskId) {
|
||||
this.taskId = taskId;
|
||||
}
|
||||
|
||||
public int getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public void setEventId(int eventId) {
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(List<String> tags) {
|
||||
this.tags = tags != null ? tags : new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<String> getExamples() {
|
||||
return examples;
|
||||
}
|
||||
|
||||
public void setExamples(List<String> examples) {
|
||||
this.examples = examples != null ? examples : new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("MCPTool{name='%s', description='%s', modelVersion='%s', taskId=%d, eventId=%d}",
|
||||
name, description, modelVersion, taskId, eventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
MCPTool that = (MCPTool) obj;
|
||||
return name != null ? name.equals(that.name) : that.name == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name != null ? name.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
Imixs-Office-Workflow
|
||||
Copyright (C) 2001-2018 Imixs Software Solutions GmbH,
|
||||
http://www.imixs.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Project:
|
||||
http://www.imixs.org
|
||||
|
||||
Contributors:
|
||||
Imixs Software Solutions GmbH - initial API and implementation
|
||||
Ralph Soika - Software Developer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,621 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
|
||||
bean-discovery-mode="all" version="3.0">
|
||||
</beans>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
Imixs Workflow Technology
|
||||
Copyright (C) 2010 Imixs Software Solutions GmbH,
|
||||
http://www.imixs.com
|
||||
|
||||
|
||||
|
||||
Contributors:
|
||||
Imixs Software Solutions GmbH - initial implementation
|
||||
Ralph Soika
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
??
|
||||
13
imixs-cloud.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
############################################################
|
||||
# Push build into imixs-cloud repo
|
||||
#
|
||||
############################################################
|
||||
|
||||
# build
|
||||
./build.sh
|
||||
|
||||
# push
|
||||
docker tag imixs/dynamixs-super-office:latest registry.tikal.imixs.com/imixs/dynamixs-super-office:latest
|
||||
docker push registry.tikal.imixs.com/imixs/dynamixs-super-office:latest
|
||||
598
pom.xml
|
|
@ -3,49 +3,17 @@
|
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<artifactId>dynamixs-ai</artifactId>
|
||||
<modules>
|
||||
<module>dynamixs-ai-app</module>
|
||||
<module>dynamixs-ai-a2a</module>
|
||||
<module>dynamixs-ai-mcp</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
<name>Dynamixs AI</name>
|
||||
<version>1.0.1</version>
|
||||
<description>Dynamixs AI - The Hyper AI collaboration platform for enterprise business. </description>
|
||||
<artifactId>dynamixs-super-office</artifactId>
|
||||
|
||||
<packaging>war</packaging>
|
||||
<name>Dynamixs Super Office</name>
|
||||
<version>1.0.0</version>
|
||||
<description>Dynamixs Super Office - Internal </description>
|
||||
<organization>
|
||||
<name>Imixs Software Solutions GmbH</name>
|
||||
<url>http://www.imixs.com</url>
|
||||
</organization>
|
||||
<inceptionYear>2019</inceptionYear>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rsoika</id>
|
||||
<name>Ralph Soika</name>
|
||||
<email>ralph.soika@imixs.com</email>
|
||||
<url>http://blog.imixs.org/</url>
|
||||
<organization>Imixs Software Solutions GmbH</organization>
|
||||
<organizationUrl>http://www.imixs.com</organizationUrl>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
<role>testing</role>
|
||||
</roles>
|
||||
<timezone>2</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>gaheinle</id>
|
||||
<name>Gaby Heinle</name>
|
||||
<email />
|
||||
<url />
|
||||
<organization>Imixs Software Solutions GmbH</organization>
|
||||
<organizationUrl>http://www.imixs.com</organizationUrl>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
<role>testing</role>
|
||||
</roles>
|
||||
<timezone>2</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
<inceptionYear>2025</inceptionYear>
|
||||
|
||||
|
||||
<properties>
|
||||
|
|
@ -58,48 +26,30 @@
|
|||
<custom.webResources>src/main/webapp</custom.webResources>
|
||||
<custom.unpackTypes>war</custom.unpackTypes>
|
||||
|
||||
<!-- Build Time -->
|
||||
<org.imixs.build.timestamp>${maven.build.timestamp}</org.imixs.build.timestamp>
|
||||
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
|
||||
<jakarta.faces.project_stage>Production</jakarta.faces.project_stage>
|
||||
<!-- =========================================================
|
||||
STEP 2: Set the Dynamixs.AI platform version you target.
|
||||
Ask your Dynamixs.AI partner contact for the current version.
|
||||
========================================================= -->
|
||||
<ai.dynamixs.version>1.0.4-SNAPSHOT</ai.dynamixs.version>
|
||||
<org.imixs.workflow.version>6.2.10-SNAPSHOT</org.imixs.workflow.version>
|
||||
<org.imixs.office.version>5.1.12-SNAPSHOT</org.imixs.office.version>
|
||||
<org.imixs.data.version>1.0.5-SNAPSHOT</org.imixs.data.version>
|
||||
<org.imixs.adapter.version>3.2.5</org.imixs.adapter.version>
|
||||
<org.imixs.security.version>3.0.2</org.imixs.security.version>
|
||||
|
||||
<!-- Dependency Versions -->
|
||||
<!-- Jakarta EE -->
|
||||
<jakarta.version>10.0.0</jakarta.version>
|
||||
<microprofile.version>6.0</microprofile.version>
|
||||
|
||||
<org.imixs.workflow.version>6.2.5-SNAPSHOT</org.imixs.workflow.version>
|
||||
<org.imixs.office.version>5.1.6-SNAPSHOT</org.imixs.office.version>
|
||||
<org.imixs.data.version>1.0.2-SNAPSHOT</org.imixs.data.version>
|
||||
<org.imixs.archive.version>3.1.5-SNAPSHOT</org.imixs.archive.version>
|
||||
<org.imixs.marty.version>5.1.0</org.imixs.marty.version>
|
||||
<org.imixs.adapter.version>3.2.2-SNAPSHOT</org.imixs.adapter.version>
|
||||
<org.imixs.ai.version>1.1.5-SNAPSHOT</org.imixs.ai.version>
|
||||
<org.imixs.metrics.version>1.0.0-SNAPSHOT</org.imixs.metrics.version>
|
||||
<org.imixs.signature.version>1.0.0</org.imixs.signature.version>
|
||||
<org.imixs.melman.version>2.1.1-SNAPSHOT</org.imixs.melman.version>
|
||||
<org.imixs.security.version>3.0.1-SNAPSHOT</org.imixs.security.version>
|
||||
<net.sf.saxon.version>9.9.1-4</net.sf.saxon.version>
|
||||
<apache.pdfbox.version>2.0.24</apache.pdfbox.version>
|
||||
<!-- test dependencies -->
|
||||
<junit.jupiter.version>5.9.2</junit.jupiter.version>
|
||||
<mockito.version>5.8.0</mockito.version>
|
||||
|
||||
<imixs-office.applicationname>dynamixs-ai</imixs-office.applicationname>
|
||||
<!-- Environment Settings -->
|
||||
<imixs-office.contextroot>/</imixs-office.contextroot>
|
||||
<imixs-office.realm>imixsrealm</imixs-office.realm>
|
||||
<imixs-office.jta-data-source>jdbc/office</imixs-office.jta-data-source>
|
||||
<imixs-office.IndexDir>lucene/office-workflow-index</imixs-office.IndexDir>
|
||||
<imixs-mail-res-ref-name>java:/mail/org.imixs.workflow.mail</imixs-mail-res-ref-name>
|
||||
|
||||
<!-- Wildfly unpack war -->
|
||||
<custom.unpackTypes>war</custom.unpackTypes>
|
||||
<jakarta.faces.project_stage>Production</jakarta.faces.project_stage>
|
||||
|
||||
<org.imixs.docker.registry>registry.tikal.imixs.com</org.imixs.docker.registry>
|
||||
|
||||
<!-- The final WAR name - this will be the context root on Wildfly -->
|
||||
<custom.applicationname>dynamixs-super-office</custom.applicationname>
|
||||
</properties>
|
||||
|
||||
<!-- =========================================================
|
||||
Repositories
|
||||
- Imixs SNAPSHOT artifacts are on Sonatype (public)
|
||||
- Dynamixs.AI artifacts are on GitHub Packages (partner access required)
|
||||
========================================================= -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>oss-snapshots</id>
|
||||
|
|
@ -107,99 +57,190 @@
|
|||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>github-dynamixs</id>
|
||||
<name>Dynamixs.AI GitHub Packages</name>
|
||||
<url>https://maven.pkg.github.com/dynamixs-ai/dynamixs-platform-repo</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<profiles>
|
||||
|
||||
|
||||
<profile>
|
||||
<id>debug</id>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>imixs-cloud</id>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<id>docker</id>
|
||||
<build>
|
||||
<resources>
|
||||
<!-- enable resource filtering for multi language version -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
|
||||
<!-- use JDK settings for compiling -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.source}</source>
|
||||
<target>${java.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Testing JUnit 5 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
|
||||
|
||||
<!-- issue #572
|
||||
hack for:
|
||||
https://stackoverflow.com/questions/75116023/unable-to-make-protected-final-java-lang-class-java-lang-classloader-defineclass
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<argLine>
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED
|
||||
</argLine>
|
||||
<target>
|
||||
<exec executable="docker">
|
||||
<arg value="build" />
|
||||
<arg value="-t" />
|
||||
<arg value="imixs/${custom.applicationname}" />
|
||||
<arg value="./" />
|
||||
</exec>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>debug</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
<target>
|
||||
<exec executable="docker">
|
||||
<arg value="build" />
|
||||
<arg value="-f" />
|
||||
<arg value="./Dockerfile-debug" />
|
||||
<arg value="-t" />
|
||||
<arg value="imixs/${custom.applicationname}" />
|
||||
<arg value="./." />
|
||||
</exec>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
|
||||
<profile>
|
||||
<id>imixs-cloud</id>
|
||||
|
||||
<!-- Imixs Security OIDC -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.imixs.security</groupId>
|
||||
<artifactId>imixs-oidc</artifactId>
|
||||
<version>${org.imixs.security.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.security</groupId>
|
||||
<artifactId>imixs-oidc-marty</artifactId>
|
||||
<version>${org.imixs.security.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<exec executable="docker">
|
||||
<arg value="build" />
|
||||
<arg value="-t" />
|
||||
<arg value="imixs/${custom.applicationname}" />
|
||||
<arg value="./" />
|
||||
</exec>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
</plugins>
|
||||
|
||||
<finalName>dynamixs-ai</finalName>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- Jakarta EE -->
|
||||
|
||||
<!-- =========================================================
|
||||
Dynamixs.AI Platform Core
|
||||
Contains all platform services, CDI beans, REST endpoints,
|
||||
AI integration and workflow engine extensions.
|
||||
========================================================= -->
|
||||
<dependency>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<artifactId>dynamixs-platform-core</artifactId>
|
||||
<version>${ai.dynamixs.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- =========================================================
|
||||
Dynamixs.AI Platform UI - WAR Overlay Base
|
||||
This is the base web application. Your files in
|
||||
src/main/webapp/ will override files from this WAR.
|
||||
========================================================= -->
|
||||
<dependency>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<artifactId>dynamixs-platform-ui</artifactId>
|
||||
<version>${ai.dynamixs.version}</version>
|
||||
<type>war</type>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- =========================================================
|
||||
STEP 3: Add your customer-specific dependencies here.
|
||||
Examples: ERP connectors, custom REST clients, etc.
|
||||
This code is owned by your customer - not by Dynamixs.AI.
|
||||
========================================================= -->
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>com.acme</groupId>
|
||||
<artifactId>sap-connector</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- Jakarta EE API - provided by Wildfly at runtime -->
|
||||
<dependency>
|
||||
<groupId>jakarta.platform</groupId>
|
||||
<artifactId>jakarta.jakartaee-api</artifactId>
|
||||
<version>${jakarta.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Microprofile -->
|
||||
|
||||
<!-- Microprofile - provided by Wildfly at runtime -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.microprofile</groupId>
|
||||
<artifactId>microprofile</artifactId>
|
||||
|
|
@ -208,112 +249,44 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs Workflow -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-core</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-engine</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-jax-rs</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-faces</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs-Office-Workflow Overlay -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-workflow-index-lucene</artifactId>
|
||||
<version>${org.imixs.workflow.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Marty -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-marty</artifactId>
|
||||
<type>jar</type>
|
||||
<version>${org.imixs.marty.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs-Archive -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-archive-api</artifactId>
|
||||
<version>${org.imixs.archive.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Imixs Metrics-->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-metrics-monitor</artifactId>
|
||||
<version>${org.imixs.metrics.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- -->
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>${apache.pdfbox.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs-AI -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-ai-rag</artifactId>
|
||||
<version>${org.imixs.ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-ai-workflow</artifactId>
|
||||
<version>${org.imixs.ai.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-ai-bpmn</artifactId>
|
||||
<version>${org.imixs.ai.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs-QR-Code -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-qrcode</artifactId>
|
||||
<version>${org.imixs.adapter.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs-Wopi -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-wopi</artifactId>
|
||||
<version>${org.imixs.adapter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-odf</artifactId>
|
||||
<version>${org.imixs.adapter.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-melman</artifactId>
|
||||
<version>${org.imixs.melman.version}</version>
|
||||
<scope>compile</scope>
|
||||
<artifactId>imixs-office-workflow-util</artifactId>
|
||||
<version>${org.imixs.office.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
|
@ -338,21 +311,26 @@
|
|||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-poi</artifactId>
|
||||
<version>${org.imixs.adapter.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-adapters-odf</artifactId>
|
||||
<version>${org.imixs.adapter.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Imixs Data -->
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-groups</artifactId>
|
||||
<version>${org.imixs.data.version}</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-views</artifactId>
|
||||
<version>${org.imixs.data.version}</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.imixs.workflow</groupId>
|
||||
|
|
@ -364,112 +342,92 @@
|
|||
<groupId>org.imixs.workflow</groupId>
|
||||
<artifactId>imixs-data-importer</artifactId>
|
||||
<version>${org.imixs.data.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- Jakarta EE -->
|
||||
<dependency>
|
||||
<groupId>jakarta.platform</groupId>
|
||||
<artifactId>jakarta.jakartaee-api</artifactId>
|
||||
<version>${jakarta.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Microprofile -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.microprofile</groupId>
|
||||
<artifactId>microprofile</artifactId>
|
||||
<version>${microprofile.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
|
||||
<!-- JUnit 5 Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Mockito Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.parsson</groupId>
|
||||
<artifactId>jakarta.json</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON-B Implementation for Tests -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse</groupId>
|
||||
<artifactId>yasson</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>jakarta.json</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-jaxb</artifactId>
|
||||
<version>3.1.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<artifactId>jersey-client</artifactId>
|
||||
<version>3.1.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- HTTP Client -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${custom.applicationname}</finalName>
|
||||
|
||||
<plugins>
|
||||
<!-- Use JDK settings for compiling -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.source}</source>
|
||||
<target>${java.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- WAR Overlay: dynamixs-platform-ui is the base layer.
|
||||
Files in src/main/webapp/ take precedence and override
|
||||
anything from the base WAR. -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<webResources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<!-- this is relative to the pom.xml directory -->
|
||||
<directory>${custom.webResources}</directory>
|
||||
<includes>
|
||||
<include>**/WEB-INF/*</include>
|
||||
<!-- include any other file types you want to filter -->
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
|
||||
<!-- We exclude libs form the parent WAR artifact
|
||||
<workDirectory>target/overlay-war-folder</workDirectory>
|
||||
<overlays>
|
||||
<overlay>
|
||||
<groupId>ai.dynamixs</groupId>
|
||||
<artifactId>dynamixs-platform-ui</artifactId>
|
||||
<excludes>
|
||||
<exclude>WEB-INF/lib/*.jar</exclude>
|
||||
</excludes>
|
||||
</overlay>
|
||||
</overlays>
|
||||
-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Hot deployment to local Wildfly Docker instance -->
|
||||
<plugin>
|
||||
<groupId>org.imixs.maven</groupId>
|
||||
<artifactId>manik-hotdeploy-maven-plugin</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>deploy</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<autodeployments>
|
||||
<deployment>
|
||||
<source>target/*.{war,ear,jar}</source>
|
||||
<target>docker/deployments/</target>
|
||||
<unpack>true</unpack>
|
||||
</deployment>
|
||||
</autodeployments>
|
||||
<hotdeployments>
|
||||
<deployment>
|
||||
<source>src/main/webapp</source>
|
||||
<target>docker/deployments/${custom.applicationname}.war</target>
|
||||
</deployment>
|
||||
</hotdeployments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
7
reports/requirements-accounting.imixs-report
Normal file
130
reports/requirements-accounting.xsl
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE xsl:stylesheet [
|
||||
<!ENTITY bdquo "" ><!ENTITY quot "" ><!ENTITY uuml "ü" ><!ENTITY auml "ä" ><!ENTITY ouml "ö" ><!ENTITY Uuml "Ü" ><!ENTITY Auml "Ä" ><!ENTITY Ouml "Ö" ><!ENTITY szlig "ß" ><!ENTITY nbsp " " ><!ENTITY lt "" >
|
||||
<!ENTITY gt "" >]><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
|
||||
<xsl:output method="html" media-type="text/html" indent="no"
|
||||
encoding="UTF-8" /> <xsl:decimal-format
|
||||
name="euro" decimal-separator="," grouping-separator="." /> <xsl:variable
|
||||
name="currenttime" select="current-dateTime()" /> <xsl:template
|
||||
match="/"> <html> <head> <meta name="viewport"
|
||||
content="width=device-width" /> <meta
|
||||
http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Imixs
|
||||
Software Solutions GmbH</title> <link
|
||||
href="../../layout/css/imixs-basic.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link
|
||||
href="../../layout/css/imixs-layout.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link
|
||||
href="../../layout/css/office-theme-print.css" charset="UTF-8" type="text/css" rel="stylesheet"
|
||||
/> <link
|
||||
href="../../layout/css/custom.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link
|
||||
href="../../custom-print.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <style>
|
||||
.toolbar.branding { font-size:1.75rem; } h2 { font-size:1.7em; } .small { font-size:65%; }
|
||||
#imixs-content { padding:10px; } #header { background-color: #FFF; color: #333; border-bottom:
|
||||
1px solid #333; padding:0; } .imixs-requirement { margin-top:20px; margin-bottom:40px; }
|
||||
.imixs-requirement h4 { border-bottom: 1px solid #333; } .imixs-table { width: 100%;
|
||||
margin-bottom:4em; } @media print { body {font-size:0.66em;} } </style> </head> <body> <!--
|
||||
content --> <div
|
||||
id="container"> <div id="imixs-content"> <!-- generate
|
||||
Header --> <xsl:apply-templates
|
||||
select="/data/document[normalize-space(item[@name = '$workflowgroup'
|
||||
] /value) = 'Auftrag']" /> <!-- body -->
|
||||
<xsl:apply-templates
|
||||
select="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Requirement']" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template> <!--
|
||||
Header Template -->
|
||||
<xsl:template
|
||||
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Auftrag']">
|
||||
<div id="header">
|
||||
<div id="imixs-servicenav">
|
||||
<div class="toolbar branding" style="float:left;">
|
||||
<span> Auftrag - <xsl:value-of select="item[@name='numsequencenumber']/value" />
|
||||
</span>
|
||||
</div>
|
||||
<div style="font-size:12px;float:right"> DYNAMIXS.AI GmbH - <br /> Frei-Otto-Str. 4 -
|
||||
80797 München <br /> Tel.: +49 (0)89 / 45 21 36-0 </div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2>
|
||||
<xsl:value-of select="item[@name='_subject']/value" />
|
||||
</h2>
|
||||
<h3>Requirements Completed: <xsl:value-of
|
||||
select="format-dateTime($currenttime, '[D01].[M01].[Y0001]')"></xsl:value-of></h3>
|
||||
</div>
|
||||
</xsl:template> <!--
|
||||
Body Template -->
|
||||
<xsl:template
|
||||
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Requirement']">
|
||||
<xsl:variable name="eventDate" select="item[@name='$lasteventdate']/value" />
|
||||
<xsl:variable name="effortPlaned" select="item[@name='_effort_planed']/value" />
|
||||
<xsl:variable name="capacity" select="item[@name='_capacity']/value" />
|
||||
<div class="imixs-requirement">
|
||||
<h4>
|
||||
<xsl:value-of select="item[@name='_subject']/value" />
|
||||
<span class="small" style="float:right;"> Stand: <xsl:value-of
|
||||
select="format-dateTime($eventDate, '[D01].[M01].[Y0001]')"></xsl:value-of>
|
||||
</span>
|
||||
</h4>
|
||||
<p>
|
||||
<xsl:value-of select="item[@name='_description']/value" disable-output-escaping="yes" />
|
||||
</p>
|
||||
</div> <!--
|
||||
efforts -->
|
||||
<table class="imixs-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:10px;">Datum</th>
|
||||
<th>Leistungsbezeichnung</th>
|
||||
<th style="width:80px;">Stunden</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<xsl:for-each select="item[@name='_childitems']/value">
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<xsl:value-of
|
||||
select="format-dateTime(item[@name='datdate']/value, '[D01].[M01].[Y0001]')" />
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="item[@name='name']/value" />
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='amount']/value" />
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each> <!--
|
||||
Summe -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="text-align: right;">
|
||||
<strong>Summe:</strong>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='_capacity']/value" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="text-align: right;">
|
||||
<strong>Plan:</strong>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='_effort_planed']/value" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="text-align: right;">
|
||||
<strong>Prozent:</strong>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='_effort_div']/value" /> % </td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
7
reports/requirements-implementation.imixs-report
Normal file
133
reports/requirements-implementation.xsl
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE xsl:stylesheet [
|
||||
<!ENTITY bdquo "" ><!ENTITY quot "" ><!ENTITY uuml "ü" ><!ENTITY auml "ä" ><!ENTITY ouml "ö" ><!ENTITY Uuml "Ü" ><!ENTITY Auml "Ä" >
|
||||
<!ENTITY Ouml "Ö" ><!ENTITY szlig "ß" ><!ENTITY nbsp " " ><!ENTITY lt "" ><!ENTITY gt "" >
|
||||
]>
|
||||
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
|
||||
<xsl:output method="html" media-type="text/html" indent="no" encoding="UTF-8" />
|
||||
<xsl:decimal-format name="euro" decimal-separator="," grouping-separator="." />
|
||||
<xsl:variable name="currenttime" select="current-dateTime()" />
|
||||
<xsl:template match="/">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Imixs Software Solutions GmbH</title>
|
||||
<link href="../../layout/css/imixs-basic.css" charset="UTF-8" type="text/css"
|
||||
rel="stylesheet" />
|
||||
<link href="../../layout/css/imixs-layout.css" charset="UTF-8" type="text/css"
|
||||
rel="stylesheet" />
|
||||
<link href="../../layout/css/office-theme-print.css" charset="UTF-8" type="text/css"
|
||||
rel="stylesheet" />
|
||||
<link href="../../layout/css/custom.css" charset="UTF-8" type="text/css"
|
||||
rel="stylesheet" />
|
||||
<link href="../../custom-print.css" charset="UTF-8" type="text/css" rel="stylesheet" />
|
||||
<style> .toolbar.branding { font-size:1.75rem; } h2 { font-size:1.7em; } .small { font-size:65%; } #imixs-content { padding:10px; } #header { background-color: #FFF; color: #333; border-bottom: 1px solid #333; padding:0; } .imixs-requirement { margin-top:20px; margin-bottom:40px; } .imixs-requirement h4 { border-bottom: 1px solid #333; } .imixs-table { width: 100%; margin-bottom:4em; } @media print { body {font-size:0.66em;} } </style>
|
||||
</head>
|
||||
<body> <!-- content -->
|
||||
<div id="container">
|
||||
<div id="imixs-content"> <!-- generate Header -->
|
||||
<xsl:apply-templates
|
||||
select="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Auftrag']" /> <!--
|
||||
body -->
|
||||
<xsl:apply-templates
|
||||
select="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Requirement']" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template> <!--
|
||||
Header Template -->
|
||||
<xsl:template
|
||||
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Auftrag']">
|
||||
<div id="header">
|
||||
<div id="imixs-servicenav">
|
||||
<div class="toolbar branding" style="float:left;">
|
||||
<span> Auftrag - <xsl:value-of select="item[@name='numsequencenumber']/value" />
|
||||
</span>
|
||||
</div>
|
||||
<div style="font-size:12px;float:right"> DYNAMIXS.AI GmbH - <br /> Frei-Otto-Str. 4
|
||||
- 80797 München <br /> Tel.: +49 (0)89 / 45 21 36-0 </div>
|
||||
</div>
|
||||
</div> <div>
|
||||
<h2>
|
||||
<xsl:value-of select="item[@name='_subject']/value" />
|
||||
</h2>
|
||||
<h3>Requirements in Umsetzung: <xsl:value-of
|
||||
select="format-dateTime($currenttime, '[D01].[M01].[Y0001]')"></xsl:value-of></h3>
|
||||
</div>
|
||||
</xsl:template> <!--
|
||||
Body Template -->
|
||||
<xsl:template
|
||||
match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Requirement']">
|
||||
<xsl:variable name="eventDate" select="item[@name='$lasteventdate']/value" /> <xsl:variable
|
||||
name="effortPlaned" select="item[@name='_effort_planed']/value" /> <xsl:variable
|
||||
name="capacity" select="item[@name='_capacity']/value" /> <div class="imixs-requirement">
|
||||
<h4>
|
||||
<xsl:value-of select="item[@name='_subject']/value" />
|
||||
<span class="small" style="float:right;"> Stand: <xsl:value-of
|
||||
select="format-dateTime($eventDate, '[D01].[M01].[Y0001]')"></xsl:value-of>
|
||||
</span>
|
||||
</h4>
|
||||
<p>
|
||||
<xsl:value-of select="item[@name='_description']/value"
|
||||
disable-output-escaping="yes" />
|
||||
</p>
|
||||
</div> <!-- efforts --> <table
|
||||
class="imixs-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:120px;">Datum</th>
|
||||
<th>Leistungsbezeichnung</th>
|
||||
<th style="width:120px;">Stunden</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<xsl:for-each select="item[@name='_childitems']/value">
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<xsl:value-of
|
||||
select="format-dateTime(item[@name='datdate']/value, '[D01].[M01].[Y0001]')" />
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="item[@name='name']/value" />
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='amount']/value" />
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each> <!--
|
||||
Summe -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="text-align: right;">
|
||||
<strong>Summe:</strong>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='_capacity']/value" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="text-align: right;">
|
||||
<strong>Plan:</strong>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='_effort_planed']/value" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td style="text-align: right;">
|
||||
<strong>Prozent:</strong>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<xsl:value-of select="item[@name='_effort_div']/value" /> % </td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
7
reports/requirements-planning.imixs-report
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><document xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><item name="attributes"><value xsi:nil="true"/></item><item name="encoding"><value xsi:type="xs:string"></value></item><item name="txtname"><value xsi:type="xs:string">requirements-planning</value></item><item name="txtquery"><value xsi:type="xs:string">($uniqueid:"{id}")
|
||||
OR
|
||||
($workflowgroup:"Requirement"
|
||||
AND ($workitemref:"{id}" OR txtworkitemref:"{id}")
|
||||
AND $taskid:2010
|
||||
)
|
||||
</value></item><item name="xsl"><value xsi:type="xs:string"><?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE xsl:stylesheet [<!ENTITY bdquo "" ><!ENTITY quot "" ><!ENTITY uuml "ü" ><!ENTITY auml "ä" ><!ENTITY ouml "ö" ><!ENTITY Uuml "Ü" ><!ENTITY Auml "Ä" ><!ENTITY Ouml "Ö" ><!ENTITY szlig "ß" ><!ENTITY nbsp " " ><!ENTITY lt "" ><!ENTITY gt "" >]><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> <xsl:output method="html" media-type="text/html" indent="no" encoding="UTF-8" /> <xsl:decimal-format name="euro" decimal-separator="," grouping-separator="." /> <xsl:variable name="currenttime" select="current-dateTime()" /> <xsl:template match="/"> <html> <head> <meta name="viewport" content="width=device-width" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Imixs Software Solutions GmbH</title> <link href="../../layout/css/imixs-basic.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link href="../../layout/css/imixs-layout.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link href="../../layout/css/office-theme-print.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link href="../../layout/css/custom.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <link href="../../custom-print.css" charset="UTF-8" type="text/css" rel="stylesheet" /> <style> .toolbar.branding { font-size:1.75rem; } h2 { font-size:1.7em; } .small { font-size:65%; } #imixs-content { padding:10px; } #header { background-color: #FFF; color: #333; border-bottom: 1px solid #333; padding:0; } .imixs-requirement { margin-top:20px; margin-bottom:40px; } .imixs-requirement h4 { border-bottom: 1px solid #333; } .imixs-table { width: 100%; margin-bottom:4em; } @media print { body {font-size:0.66em;} } </style> </head> <body> <!-- content --> <div id="container"> <div id="imixs-content"> <!-- generate Header --> <xsl:apply-templates select="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Auftrag']" /> <!-- body --> <xsl:apply-templates select="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Requirement']" /> </div> </div> </body> </html> </xsl:template> <!-- Header Template --> <xsl:template match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Auftrag']"> <div id="header"> <div id="imixs-servicenav"> <div class="toolbar branding" style="float:left;"> <span> Auftrag - <xsl:value-of select="item[@name='numsequencenumber']/value" /> </span> </div> <div style="font-size:12px;float:right"> Imixs Software Solutions GmbH - <br /> Agnes-Pockels-Bogen 1 - 80992 München <br /> Tel.: +49 (0)89 / 45 21 36-0 </div> </div> </div> <div> <h2> <xsl:value-of select="item[@name='_subject']/value" /> </h2> <h3>Requirements in Planung: <xsl:value-of select="format-dateTime($currenttime, '[D01].[M01].[Y0001]')"></xsl:value-of></h3> </div> </xsl:template> <!-- Body Template --> <xsl:template match="/data/document[normalize-space(item[@name = '$workflowgroup']/value) = 'Requirement']"> <xsl:variable name="eventDate" select="item[@name='$lasteventdate']/value" /> <div class="imixs-requirement"> <h4> <xsl:value-of select="item[@name='_subject']/value" /> <span class="small" style="float:right;"> Stand: <xsl:value-of select="format-dateTime($eventDate, '[D01].[M01].[Y0001]')"></xsl:value-of> </span> </h4> <p> <xsl:value-of select="item[@name='_description']/value" disable-output-escaping="yes" /> </p> <p> <strong>Aufwand geplant: </strong><xsl:value-of select="item[@name='_effort_planed']/value" /> Stunden </p> </div> </xsl:template></xsl:stylesheet></value></item><item name="xslresource"><value xsi:type="xs:string">/imixs-super-office/src/reports/requirements-planning.xsl</value></item></document>
|
||||
85
src/main/java/ai/dynamixs/InvoicePOIAdapter.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package ai.dynamixs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.imixs.archive.core.SnapshotService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.DocumentService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.imixs.workflow.poi.POIFindReplaceAdapter;
|
||||
import org.imixs.workflow.poi.XSSFUtil;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* Dieser Adapter erweitert den POIFindReplaceAdapter und fügt in das
|
||||
* Rechnungsformular zusätzliche Zeilen ein
|
||||
*/
|
||||
public class InvoicePOIAdapter extends POIFindReplaceAdapter {
|
||||
|
||||
private static Logger logger = Logger.getLogger(InvoicePOIAdapter.class.getName());
|
||||
|
||||
@Inject
|
||||
WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
DocumentService documentService;
|
||||
|
||||
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
||||
final String TYPE_TEXTBLOCK = "textblock";
|
||||
|
||||
@Inject
|
||||
SnapshotService snapshotService;
|
||||
|
||||
@Override
|
||||
public void updateXSSFWorkbook(XSSFWorkbook workbook, ItemCollection workitem, List<String> replaceDevList,
|
||||
String eval) throws PluginException {
|
||||
XSSFSheet sheet = workbook.getSheetAt(0);
|
||||
// Steuer?
|
||||
int steuer = workitem.getItemValueInteger("invoice.tax.rate");
|
||||
if (steuer > 0) {
|
||||
XSSFUtil.replaceXSSFSheetItemValue(workbook, sheet, "TAX_INFO", "Umsatzsteuer: ");
|
||||
}
|
||||
Double steuerD = (double) steuer / 100;
|
||||
XSSFUtil.replaceXSSFSheetItemValue(workbook, sheet, "TAX_RATE", steuerD);
|
||||
|
||||
// insert invoice pos...
|
||||
|
||||
ItemCollection auftrag = documentService.load(workitem.getItemValueString("$workitemref"));
|
||||
List<ItemCollection> requirements = new ArrayList<ItemCollection>();
|
||||
List<String> refs = workitem.getItemValueList("_requirements", String.class);
|
||||
for (String _id : refs) {
|
||||
requirements.add(documentService.load(_id));
|
||||
}
|
||||
|
||||
int pos = 1;
|
||||
for (ItemCollection _requirement : requirements) {
|
||||
|
||||
int line = pos + 23;
|
||||
|
||||
XSSFUtil.replaceXSSFSheetItemValue(workbook, sheet, "A" + line, pos);
|
||||
XSSFUtil.replaceXSSFSheetItemValue(workbook, sheet, "B" + line,
|
||||
_requirement.getItemValueString("_subject"));
|
||||
|
||||
double rate = auftrag.getItemValueDouble("_rate");
|
||||
double capacity = _requirement.getItemValueDouble("_capacity");
|
||||
|
||||
XSSFUtil.replaceXSSFSheetItemValue(workbook, sheet, "E" + line, rate);
|
||||
XSSFUtil.replaceXSSFSheetItemValue(workbook, sheet, "F" + line, capacity);
|
||||
|
||||
XSSFUtil.evalXSSFSheet(workbook, sheet, "G" + line);
|
||||
|
||||
pos++;
|
||||
|
||||
}
|
||||
|
||||
super.updateXSSFWorkbook(workbook, workitem, replaceDevList, eval);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
74
src/main/java/com/imixs/intern/AuftragController.java
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.exceptions.AccessDeniedException;
|
||||
import org.imixs.workflow.faces.data.ViewController;
|
||||
import org.imixs.workflow.faces.data.WorkflowController;
|
||||
import org.imixs.workflow.faces.data.WorkflowEvent;
|
||||
import org.imixs.workflow.faces.util.LoginController;
|
||||
import org.imixs.workflow.office.forms.WorkitemLinkController;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
|
||||
/**
|
||||
* Dieser AuftragController hat nur den Zweck eine MIgration des neuen feldes
|
||||
* contact.ref durchzuführen
|
||||
*
|
||||
*/
|
||||
@Named
|
||||
@RequestScoped
|
||||
public class AuftragController extends ViewController {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static Logger logger = Logger.getLogger(AuftragController.class.getName());
|
||||
|
||||
@Inject
|
||||
LoginController loginController;
|
||||
|
||||
@Inject
|
||||
WorkflowController workflowController;
|
||||
|
||||
@Inject
|
||||
WorkitemLinkController workitemLinkController;
|
||||
|
||||
/**
|
||||
* Diese Hilfsmethode sortiert die Requirements nach Datum.
|
||||
*
|
||||
* @param workflowEvent
|
||||
* @throws AccessDeniedException
|
||||
*/
|
||||
public void onWorkflowEvent(@Observes @Priority(value = 1) WorkflowEvent workflowEvent)
|
||||
throws AccessDeniedException {
|
||||
|
||||
ItemCollection workitem = workflowEvent.getWorkitem();
|
||||
if (workitem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workflowEvent.getEventType() == WorkflowEvent.WORKITEM_CHANGED) {
|
||||
// skip if already defined
|
||||
if (!workitem.getItemValueString("contact.ref").isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check all refs...
|
||||
List<ItemCollection> references = workitemLinkController.getReferences();
|
||||
for (ItemCollection reference : references) {
|
||||
if ("Kontakt".equals(reference.getWorkflowGroup())) {
|
||||
workitem.setItemValue("contact.ref", reference.getUniqueID());
|
||||
// Erledigt! :-)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
src/main/java/com/imixs/intern/RechnungsAdapterFinish.java
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.SignalAdapter;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.AccessDeniedException;
|
||||
import org.imixs.workflow.exceptions.AdapterException;
|
||||
import org.imixs.workflow.exceptions.ModelException;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.imixs.workflow.exceptions.ProcessingErrorException;
|
||||
import org.imixs.workflow.odf.ODFDOMFindReplaceAdapter;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* Der RechnungsAdapterComplete wird eingesetzt wenn eine Rechnung geprüft
|
||||
* wurde. Dann werden alle Requirement Positionen auf 'Invoiced' gesetzt.
|
||||
*
|
||||
* Zusätzlich erzeugt der Adapter die Child Item Buchungszeile
|
||||
*
|
||||
*/
|
||||
public class RechnungsAdapterFinish implements SignalAdapter {
|
||||
|
||||
private static Logger logger = Logger.getLogger(RechnungsAdapterFinish.class.getName());
|
||||
|
||||
@Inject
|
||||
WorkflowService workflowService;
|
||||
|
||||
/**
|
||||
* Executes all
|
||||
* requriements with 2300.20**@throws PluginException
|
||||
*/
|
||||
|
||||
@Override
|
||||
public ItemCollection execute(ItemCollection workitem, ItemCollection event)
|
||||
throws AdapterException, PluginException {
|
||||
|
||||
logger.info("Finish Imixs Rechnung....");
|
||||
List<String> refs = workitem.getItemValueList("_requirements", String.class);
|
||||
for (String _id : refs) {
|
||||
try {
|
||||
ItemCollection _requirement = workflowService.getDocumentService().load(_id);
|
||||
if (_requirement.getTaskID() == 2300) {
|
||||
workflowService.processWorkItem(_requirement, 20);
|
||||
}
|
||||
} catch (AccessDeniedException | ProcessingErrorException | ModelException e) {
|
||||
throw new PluginException(ODFDOMFindReplaceAdapter.class.getSimpleName(), "UPDATE_ERROR",
|
||||
"Failed to update Requirements : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// copyRechnungssumme();
|
||||
return workitem;
|
||||
}
|
||||
|
||||
private void copyRechnungssumme() {
|
||||
|
||||
}
|
||||
}
|
||||
129
src/main/java/com/imixs/intern/RechnungsAdapterODF.java
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.DocumentService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
import org.imixs.workflow.odf.ODFDOMFindReplaceAdapter;
|
||||
import org.odftoolkit.odfdom.doc.OdfDocument;
|
||||
import org.odftoolkit.odfdom.doc.table.OdfTable;
|
||||
import org.odftoolkit.odfdom.doc.table.OdfTableRow;
|
||||
import org.odftoolkit.odfdom.incubator.search.InvalidNavigationException;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* Dieser Adapter erweitert den ODFDOMFindReplaceAdapter und fügt in das
|
||||
* Rechnungsformular zusätzliche Zeilen ein
|
||||
*/
|
||||
public class RechnungsAdapterODF extends ODFDOMFindReplaceAdapter {
|
||||
|
||||
private static Logger logger = Logger.getLogger(ODFDOMFindReplaceAdapter.class.getName());
|
||||
|
||||
@Inject
|
||||
WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
DocumentService documentService;
|
||||
|
||||
/**
|
||||
* Updates a SpreadSheet Document
|
||||
*
|
||||
* Load all needed workitems....
|
||||
*
|
||||
* @param odfDoc
|
||||
* @param workitem
|
||||
* @param replaceDevList
|
||||
* @throws PluginException
|
||||
* @throws InvalidNavigationException
|
||||
*/
|
||||
@Override
|
||||
public void updateODFDocument(OdfDocument odfDoc, ItemCollection workitem, List<String> replaceDevList)
|
||||
throws PluginException, InvalidNavigationException {
|
||||
String subject;
|
||||
|
||||
super.updateODFDocument(odfDoc, workitem, replaceDevList);
|
||||
logger.info("Update Imixs Rechnung....");
|
||||
|
||||
// Load all needed workitems....
|
||||
ItemCollection auftrag = documentService.load(workitem.getItemValueString("$workitemref"));
|
||||
subject = auftrag.getItemValueString("_subject");
|
||||
List<ItemCollection> requirements = new ArrayList<ItemCollection>();
|
||||
List<String> refs = workitem.getItemValueList("_requirements", String.class);
|
||||
for (String _id : refs) {
|
||||
requirements.add(documentService.load(_id));
|
||||
}
|
||||
// find Kontakt
|
||||
ItemCollection kontakt = null;
|
||||
refs = auftrag.getItemValueList("$workitemref", String.class);
|
||||
for (String _id : refs) {
|
||||
ItemCollection _workitem = documentService.load(_id);
|
||||
if (_workitem != null && "Kontakt".equals(_workitem.getItemValueString("$workflowgroup"))) {
|
||||
kontakt = _workitem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// find row..
|
||||
OdfTable tbl = odfDoc.getTableList().get(0);
|
||||
|
||||
// Update Address
|
||||
if (kontakt != null) {
|
||||
tbl.getCellByPosition("A7").setStringValue(kontakt.getItemValueString("_subject"));
|
||||
tbl.getCellByPosition("A8").setStringValue(kontakt.getItemValueString("_address"));
|
||||
|
||||
tbl.getCellByPosition("A10")
|
||||
.setStringValue(kontakt.getItemValueString("_zip") + " " + kontakt.getItemValueString("_city"));
|
||||
tbl.getCellByPosition("A11").setStringValue(kontakt.getItemValueString("_country"));
|
||||
}
|
||||
// Update Auftrag
|
||||
if (auftrag != null) {
|
||||
tbl.getCellByPosition("G21").setStringValue(auftrag.getItemValueString("numsequencenumber"));
|
||||
tbl.getCellByPosition("C21").setStringValue(auftrag.getItemValueString("_ordernumber"));
|
||||
|
||||
// update email if not defined
|
||||
if (workitem.getItemValueString("invoice.email").isEmpty()) {
|
||||
workitem.cloneItem("invoice.email", auftrag);
|
||||
}
|
||||
}
|
||||
|
||||
// Requirements
|
||||
List<OdfTableRow> newRows = tbl.insertRowsBefore(24, requirements.size() - 1);
|
||||
int pos = 1;
|
||||
int line = 0;
|
||||
for (ItemCollection _requirement : requirements) {
|
||||
OdfTableRow newRow = tbl.getRowByIndex(22 + pos);
|
||||
line = pos + 23;
|
||||
|
||||
newRow.getCellByIndex(0).setStringValue(pos + "");
|
||||
newRow.getCellByIndex(1).setStringValue(_requirement.getItemValueString("_subject"));
|
||||
newRow.getCellByIndex(4).setDoubleValue(auftrag.getItemValueDouble("_rate"));
|
||||
newRow.getCellByIndex(5).setDoubleValue(_requirement.getItemValueDouble("_capacity"));
|
||||
// set formular
|
||||
newRow.getCellByIndex(6).setFormula("=E" + (line) + "*F" + (line));
|
||||
pos++;
|
||||
|
||||
}
|
||||
|
||||
// Update Summary Formulars....
|
||||
// line = 24;
|
||||
// String formel = "=";
|
||||
// for (ItemCollection _requirement : requirements) {
|
||||
// formel = formel + "G" + line + "+";
|
||||
// line++;
|
||||
// }
|
||||
// formel = formel.substring(0, formel.length() - 1);
|
||||
// line = 25 + requirements.size();
|
||||
// tbl.getCellByPosition("G" + (line)).setFormula(formel);
|
||||
// line++;
|
||||
|
||||
// line++;
|
||||
// tbl.getCellByPosition("G" + (line)).setFormula("=G" + (line - 2) + "+G" +
|
||||
// (line - 1));
|
||||
|
||||
}
|
||||
}
|
||||
119
src/main/java/com/imixs/intern/RequirementsViewController.java
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.ItemCollectionComparator;
|
||||
import org.imixs.workflow.exceptions.AccessDeniedException;
|
||||
import org.imixs.workflow.exceptions.QueryException;
|
||||
import org.imixs.workflow.faces.data.ViewController;
|
||||
import org.imixs.workflow.faces.data.WorkflowController;
|
||||
import org.imixs.workflow.faces.data.WorkflowEvent;
|
||||
import org.imixs.workflow.faces.util.LoginController;
|
||||
import org.imixs.workflow.office.forms.ChildItemController;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
|
||||
@Named
|
||||
@ViewScoped
|
||||
public class RequirementsViewController extends ViewController {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static Logger logger = Logger.getLogger(RequirementsViewController.class.getName());
|
||||
|
||||
@Inject
|
||||
LoginController loginController;
|
||||
|
||||
@Inject
|
||||
WorkflowController workflowController;
|
||||
|
||||
@Inject
|
||||
ChildItemController childItemController;
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
super.init();
|
||||
String id = "-1";
|
||||
if (workflowController.getWorkitem() != null) {
|
||||
id = workflowController.getWorkitem().getUniqueID();
|
||||
}
|
||||
this.setQuery(
|
||||
"($workflowgroup:\"Requirement\") AND (type:\"workitem\" OR type:\"workitemarchive\") AND ($workitemref:\""
|
||||
+ id + "\" OR txtworkitemref:\"" + id + "\")");
|
||||
this.setSortBy("$taskid");
|
||||
this.setSortReverse(false);
|
||||
this.setPageSize(999);
|
||||
this.setLoadStubs(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute summary....
|
||||
*/
|
||||
@Override
|
||||
public List<ItemCollection> loadData() throws QueryException {
|
||||
List<ItemCollection> result = super.loadData();
|
||||
|
||||
float capa = 0;
|
||||
float plan = 0;
|
||||
for (ItemCollection orderitem : result) {
|
||||
|
||||
// skip canceled entries
|
||||
if (2900 == orderitem.getTaskID()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
capa = capa + orderitem.getItemValueFloat("_capacity");
|
||||
plan = plan + orderitem.getItemValueFloat("_effort_planed");
|
||||
}
|
||||
|
||||
workflowController.getWorkitem().replaceItemValue("_capacity", capa);
|
||||
workflowController.getWorkitem().replaceItemValue("_effort_planed", plan);
|
||||
workflowController.getWorkitem().replaceItemValue("_effort_div", Float.valueOf((capa / plan) * 100));
|
||||
// sort result by task and creation date
|
||||
result.sort(Comparator
|
||||
.comparingInt((ItemCollection item) -> item.getItemValueInteger("$taskid"))
|
||||
.thenComparing(item -> item.getItemValueDate("$created"), Comparator.reverseOrder()));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Diese Hilfsmethode sortiert die Requirements nach Datum.
|
||||
*
|
||||
* @param workflowEvent
|
||||
* @throws AccessDeniedException
|
||||
*/
|
||||
public void onWorkflowEvent(@Observes @Priority(value = 1) WorkflowEvent workflowEvent)
|
||||
throws AccessDeniedException {
|
||||
|
||||
int eventType = workflowEvent.getEventType();
|
||||
ItemCollection workitem = workflowEvent.getWorkitem();
|
||||
if (workitem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// nur reagieren wenn wir in einem Requirement oder bei Werksstudenten sind!
|
||||
if ("Requirement".equals(workitem.getWorkflowGroup()) || "Werksstudent".equals(workitem.getWorkflowGroup())) {
|
||||
|
||||
// before the workitem is saved we sort the list by date
|
||||
if (WorkflowEvent.WORKITEM_BEFORE_PROCESS == eventType
|
||||
&& childItemController.getChildItems() != null) {
|
||||
logger.info("...sorting requirement/effort list...");
|
||||
Collections.sort(childItemController.getChildItems(), new ItemCollectionComparator("datdate", false));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
175
src/main/java/com/imixs/intern/StatistikPlugin.java
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.plugins.AbstractPlugin;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
/**
|
||||
* Dieses Plugin berechnet die gebuchten Stunden pro tag und woche
|
||||
*
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
public class StatistikPlugin extends AbstractPlugin {
|
||||
|
||||
private String[] ignoreList = { "administration-np" };
|
||||
private static Logger logger = Logger.getLogger(StatistikPlugin.class
|
||||
.getName());
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Skip if not a workitem and only run once a day!
|
||||
*
|
||||
* @throws PluginException
|
||||
*
|
||||
**/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public ItemCollection run(ItemCollection workitem, ItemCollection documentActivity) throws PluginException {
|
||||
|
||||
List<String> ignoreArrayList = Arrays.asList(ignoreList);
|
||||
|
||||
// skip if the workitem is from a different type (for example Teams
|
||||
// may not be processed by this plugin)
|
||||
String type = workitem.getItemValueString("type");
|
||||
|
||||
if (!type.equals("workitem"))
|
||||
return workitem;
|
||||
|
||||
// lauf nur in workflow modell imixs-de
|
||||
// und nur 9000.100
|
||||
int processID = workitem.getItemValueInteger("$Processid");
|
||||
int activityID = documentActivity.getItemValueInteger("numActivityID");
|
||||
String model = workitem.getItemValueString("$ModelVersion");
|
||||
|
||||
if (!(processID == 9000 && activityID == 100 && model.startsWith("imixs-de")))
|
||||
return workitem;
|
||||
|
||||
// sind wir heute schon gelaufen?
|
||||
Calendar calToday = Calendar.getInstance();
|
||||
calToday.setTime(new Date());
|
||||
|
||||
Calendar calLast = Calendar.getInstance();
|
||||
Date datLast = workitem.getItemValueDate("datLetzteStatistik");
|
||||
if (datLast != null)
|
||||
calLast.setTime(datLast);
|
||||
|
||||
int dayOfYear = calLast.get(Calendar.DAY_OF_YEAR);
|
||||
|
||||
if (datLast != null
|
||||
&& calLast.get(Calendar.DAY_OF_YEAR) == calToday
|
||||
.get(Calendar.DAY_OF_YEAR)) {
|
||||
logger.info("[Imixs StatistikPlugin] skipped");
|
||||
// ganzen vorgang abbrechen, da sonst wieder eine Email gesendet wird
|
||||
throw new PluginException("StatistikPlugin", "wrong date", "wrong date");
|
||||
// return Plugin.PLUGIN_ERROR;
|
||||
|
||||
}
|
||||
|
||||
// ok wir starten die Auswertung!
|
||||
logger.info("[Imixs StatistikPlugin] Starte Auswertung....");
|
||||
|
||||
workitem.replaceItemValue("datLetzteStatistik", calToday.getTime());
|
||||
|
||||
// jetzt brauchen wir die Werte von gestern!
|
||||
calToday.add(Calendar.DATE, -1);
|
||||
List<ItemCollection> aktuell = getStunden(calToday, calToday);
|
||||
int stundenHeute = 0;
|
||||
for (ItemCollection abr : aktuell) {
|
||||
// prüfe ob categorie in ignore liste ist
|
||||
String sKategorie = abr.getItemValueString("_category")
|
||||
.toLowerCase();
|
||||
if (Arrays.asList(ignoreList).contains(sKategorie))
|
||||
continue;
|
||||
|
||||
stundenHeute += abr.getItemValueInteger("_duration");
|
||||
}
|
||||
|
||||
logger.info("[Imixs StatistikPlugin] Stunden heute=" + stundenHeute);
|
||||
workitem.replaceItemValue("numStundenHeute", stundenHeute);
|
||||
|
||||
// vorherige Woche berechnen
|
||||
Date date = new Date();
|
||||
|
||||
int i = calToday.get(Calendar.DAY_OF_WEEK)
|
||||
- calToday.getFirstDayOfWeek();
|
||||
calToday.add(Calendar.DATE, -i - 7);
|
||||
Date start = calToday.getTime();
|
||||
calToday.add(Calendar.DATE, 6);
|
||||
Date end = calToday.getTime();
|
||||
logger.info("[Imixs StatistikPlugin] Vorwoche=" + start + " - " + end);
|
||||
|
||||
Calendar calStart = Calendar.getInstance();
|
||||
calStart.setTime(start);
|
||||
Calendar calEnd = Calendar.getInstance();
|
||||
calEnd.setTime(end);
|
||||
|
||||
List<ItemCollection> vorwoche = getStunden(calStart, calEnd);
|
||||
int stundenLetzeWoche = 0;
|
||||
for (ItemCollection abr : vorwoche) {
|
||||
|
||||
// prüfe ob categorie in ignore liste ist
|
||||
String sKategorie = abr.getItemValueString("_category")
|
||||
.toLowerCase();
|
||||
if (Arrays.asList(ignoreList).contains(sKategorie))
|
||||
continue;
|
||||
|
||||
stundenLetzeWoche += abr.getItemValueInteger("_duration");
|
||||
}
|
||||
workitem.replaceItemValue("numStundenLetzeWoche", stundenLetzeWoche);
|
||||
|
||||
logger.info("[Imixs StatistikPlugin] Stunden Letze Woche="
|
||||
+ stundenLetzeWoche);
|
||||
|
||||
return workitem;
|
||||
}
|
||||
|
||||
public void close(int arg0) {
|
||||
// no op
|
||||
|
||||
}
|
||||
|
||||
public String[] getIgnoreList() {
|
||||
return ignoreList;
|
||||
}
|
||||
|
||||
public void setIgnoreList(String[] ignoreList) {
|
||||
this.ignoreList = ignoreList;
|
||||
}
|
||||
|
||||
private List<ItemCollection> getStunden(Calendar dayFrom, Calendar dayTo) {
|
||||
|
||||
// dayformat 2014-12-31
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||
String sDateFrom = df.format(dayFrom.getTime());
|
||||
String sDateTo = df.format(dayTo.getTime());
|
||||
|
||||
String sQuery = " SELECT workitem FROM Entity AS workitem"
|
||||
+ " JOIN workitem.textItems AS type2"
|
||||
+ " JOIN workitem.calendarItems AS type3"
|
||||
+ " WHERE workitem.type IN ('childworkitem')"
|
||||
+ " AND type3.itemName = 'datdate' "
|
||||
+ " AND type3.itemValue BETWEEN '" + sDateFrom + " 00:00:00' AND '"
|
||||
+ sDateTo + " 23:59:59'"
|
||||
+ " AND type2.itemName = 'txtworkflowgroup' "
|
||||
+ " AND type2.itemValue = 'Zeiterfassung'"
|
||||
+ " ORDER BY type3.itemValue DESC ";
|
||||
|
||||
logger.fine("[Imixs StatistikPlugin] " + sQuery);
|
||||
|
||||
logger.warning("Imixs Statistik Collector is not implemented");
|
||||
// return documentService.findAllEntities(sQuery, 0, -1);
|
||||
return new ArrayList<ItemCollection>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,491 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.marty.team.TeamService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.DocumentService;
|
||||
import org.imixs.workflow.exceptions.QueryException;
|
||||
import org.imixs.workflow.office.forms.AnalyticController;
|
||||
import org.imixs.workflow.office.forms.AnalyticEvent;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonArrayBuilder;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonObjectBuilder;
|
||||
|
||||
/**
|
||||
* Der SuperOfficeAnalyticController berechnet verschiedene Analyse Daten
|
||||
*
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
@Named
|
||||
@RequestScoped
|
||||
public class SuperOfficeAnalyticController implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Logger logger = Logger.getLogger(AnalyticController.class.getName());
|
||||
public static final String CHILD_ITEM_PROPERTY = "_ChildItems";
|
||||
|
||||
@Inject
|
||||
protected DocumentService documentService;
|
||||
|
||||
@Inject
|
||||
TeamService teamService;
|
||||
|
||||
List<ItemCollection> auftraege = null;
|
||||
List<ItemCollection> rechnungen = null;
|
||||
Map<String, List<ItemCollection>> requirementsCache = null;
|
||||
Map<Integer, RequirementData> hoursByWeek = null;
|
||||
int earliestWeek = Integer.MAX_VALUE;
|
||||
int latestWeek = Integer.MIN_VALUE;
|
||||
|
||||
public void onEvent(@Observes AnalyticEvent event) {
|
||||
|
||||
if (!event.getKey().startsWith("superoffice.stats.")) {
|
||||
return;
|
||||
}
|
||||
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(Locale.GERMANY);
|
||||
|
||||
ItemCollection processRequirements = teamService.getProcessByName("Sales");
|
||||
if (processRequirements == null) {
|
||||
logger.severe("Process 'Sales' not found!");
|
||||
return;
|
||||
}
|
||||
ItemCollection processBuchhaltung = teamService.getProcessByName("Finance");
|
||||
if (processBuchhaltung == null) {
|
||||
logger.severe("Process 'Finance' not found!");
|
||||
return;
|
||||
}
|
||||
String linkRequirements = "/pages/workitems/worklist.xhtml?processref=" + processRequirements.getUniqueID()
|
||||
+ "&workflowgroup=Requirement";
|
||||
String linkInvoices = "/pages/workitems/worklist.xhtml?processref=" + processBuchhaltung.getUniqueID()
|
||||
+ "&workflowgroup=Rechnungsausgang";
|
||||
|
||||
if ("superoffice.stats.hours.total".equals(event.getKey())) {
|
||||
event.setData(new ItemCollection());
|
||||
event.getData().setItemValue("value", computeHoursTotal());
|
||||
event.getData().setItemValue("label", "Stunden");
|
||||
event.getData().setItemValue("description", "Noch nicht abgerechnete Stunden");
|
||||
event.getData().setItemValue("link", linkRequirements);
|
||||
}
|
||||
|
||||
if ("superoffice.stats.invoices.total".equals(event.getKey())) {
|
||||
event.setData(new ItemCollection());
|
||||
event.getData().setItemValue("Value", currencyFormat.format(computeOffeneRechnungen()));
|
||||
event.getData().setItemValue("Label", "EUR");
|
||||
event.getData().setItemValue("Description", "Offene Rechnungen");
|
||||
event.getData().setItemValue("Link", linkInvoices);
|
||||
}
|
||||
|
||||
// Charts
|
||||
if ("superoffice.stats.hours.currentWeek".equals(event.getKey())) {
|
||||
accumulateHoursByWeek();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date());
|
||||
int weekNumber = calendar.get(Calendar.WEEK_OF_YEAR);
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
int yearWeek = year * 100 + weekNumber; // Unique key for each year + week combination
|
||||
RequirementData weekData = hoursByWeek.getOrDefault(yearWeek, new RequirementData());
|
||||
event.setData(new ItemCollection());
|
||||
event.getData().setItemValue("Value", weekData.total);
|
||||
event.getData().setItemValue("Label", "Stunden");
|
||||
event.getData().setItemValue("Description", "Stunden gesamt in dieser Woche - KW " + weekNumber);
|
||||
event.getData().setItemValue("Link", linkRequirements);
|
||||
}
|
||||
|
||||
if ("superoffice.stats.hours.trend".equals(event.getKey())) {
|
||||
accumulateHoursByWeek();
|
||||
event.setData(new ItemCollection());
|
||||
event.getData().setItemValue("Value", buildHoursChart());
|
||||
event.getData().setItemValue("Label", "Stunden");
|
||||
event.getData().setItemValue("Description", "Stunden nach KW");
|
||||
}
|
||||
|
||||
// computeKIPrompt(event.getWorkitem());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet die Summe aller offenen stunden
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private double computeHoursTotal() {
|
||||
logger.fine("compute hours...");
|
||||
List<ItemCollection> list = getAufträge();
|
||||
double result = 0;
|
||||
|
||||
for (ItemCollection steuerItemCol : list) {
|
||||
result = result + getStundenByAuftrag(steuerItemCol);
|
||||
|
||||
}
|
||||
return round(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet die Summe aller offenen Rechnungen
|
||||
*
|
||||
* _amount
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private double computeOffeneRechnungen() {
|
||||
logger.fine("compute offene Rechnungen...");
|
||||
List<ItemCollection> list = getOffeneRechnungen();
|
||||
double result = 0;
|
||||
|
||||
for (ItemCollection workitem : list) {
|
||||
result = result + workitem.getItemValueDouble("_amount");
|
||||
|
||||
}
|
||||
return round(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet die stunden pro auftrag (_capacity) Achtung: ist ein string der in
|
||||
* double convertiert werden muss
|
||||
*
|
||||
* @param auftrag
|
||||
* @return
|
||||
*/
|
||||
private double getStundenByAuftrag(ItemCollection auftrag) {
|
||||
double result = 0;
|
||||
|
||||
List<ItemCollection> requirements = getRequirementsByAuftrag(auftrag);
|
||||
for (ItemCollection requirement : requirements) {
|
||||
result = result + requirement.getItemValueDouble("_capacity");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void computeKIPrompt(ItemCollection workitem) {
|
||||
|
||||
String prompt = "Erstelle eine sehr kurze Geschäftsprognose über die Auftragslage auf Basis folgender Daten: \n";
|
||||
prompt += "Wir haben aktuell offene Rechnungen in Höhe von " + workitem.getItemValueDouble("invoices.total")
|
||||
+ " EUR .";
|
||||
prompt += "Unser Stundensatz beträgt 150,- EUR .";
|
||||
|
||||
prompt += "In der aktuellen Woche haben wir bereits " + workitem.getItemValueInteger("stunden.total.week")
|
||||
+ " Stunden gearbeitet. ";
|
||||
|
||||
prompt += "Insgesamt haben wir " + workitem.getItemValueInteger("stunden.total")
|
||||
+ " Stunden gearbeitet die noch nicht in Rechnung gestellt sind. \n";
|
||||
|
||||
prompt += "Hier kommt eine übersicht der geleisteten Stunden die noch nicht abgerechnet wurden nach Kalenderwoche: \n";
|
||||
|
||||
Set<Integer> weekNumbers = hoursByWeek.keySet();
|
||||
for (int kw : weekNumbers) {
|
||||
String year = ("" + kw).substring(0, 4);
|
||||
String weekNumber = ("" + kw).substring(4);
|
||||
// Add the saldo for the week or 0.0 if no data
|
||||
RequirementData requirementData = hoursByWeek.getOrDefault(kw, new RequirementData());
|
||||
|
||||
prompt += " - " + weekNumber + "/" + year + " = " + requirementData.total + "\n";
|
||||
|
||||
}
|
||||
|
||||
logger.info(prompt);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Aufträge
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<ItemCollection> getAufträge() {
|
||||
if (auftraege != null) {
|
||||
return auftraege;
|
||||
}
|
||||
logger.info("Load Aufträge for analytics....");
|
||||
String query = "(type:workitem ) AND ($workflowgroup:\"Auftrag\")";
|
||||
try {
|
||||
auftraege = documentService.find(query, 999, 0, "$created", false);
|
||||
return auftraege;
|
||||
} catch (QueryException e) {
|
||||
logger.severe("Failed to get invoices: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle offenen Rechnungen
|
||||
*
|
||||
* _amount
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<ItemCollection> getOffeneRechnungen() {
|
||||
if (rechnungen != null) {
|
||||
return rechnungen;
|
||||
}
|
||||
logger.info("Load Rechnung for analytics....");
|
||||
String query = "(type:workitem ) AND ($workflowgroup:\"Rechnungsausgang\")";
|
||||
try {
|
||||
rechnungen = documentService.find(query, 999, 0, "$created", false);
|
||||
return rechnungen;
|
||||
} catch (QueryException e) {
|
||||
logger.severe("Failed to get invoices: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Requirements zu einem Auftrag
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<ItemCollection> getRequirementsByAuftrag(ItemCollection auftrag) {
|
||||
if (requirementsCache == null) {
|
||||
requirementsCache = new HashMap<>();
|
||||
}
|
||||
|
||||
List<ItemCollection> result = requirementsCache.get(auftrag.getUniqueID());
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
// compute requirements....
|
||||
logger.info("Load Requirements by Auftrag for analytics (" + auftrag.getUniqueID() + ")...");
|
||||
String query = "($workflowgroup:\"Requirement\") AND (type:\"workitem\") AND ($taskid:[2100 TO 2300]) AND ($workitemref:\""
|
||||
+ auftrag.getUniqueID() + "\")";
|
||||
try {
|
||||
result = documentService.find(query, 999, 0, "$created", false);
|
||||
requirementsCache.put(auftrag.getUniqueID(), result);
|
||||
return result;
|
||||
} catch (QueryException e) {
|
||||
logger.severe("Failed to get invoices: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Akkumuliert alle Stunden nach KW. Die Methode nutzt einen Cache
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private void accumulateHoursByWeek() {
|
||||
if (hoursByWeek != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("accumulate hours by week...");
|
||||
hoursByWeek = new HashMap<>();
|
||||
List<ItemCollection> list = getAufträge();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
// Step 1: Group saldo by week
|
||||
for (ItemCollection auftrag : list) {
|
||||
|
||||
List<ItemCollection> requirements = getRequirementsByAuftrag(auftrag);
|
||||
for (ItemCollection requirement : requirements) {
|
||||
|
||||
// dive into the stunden....
|
||||
List<ItemCollection> stundenListe = explodeChildList(requirement);
|
||||
|
||||
for (ItemCollection stunden : stundenListe) {
|
||||
|
||||
double total = stunden.getItemValueDouble("amount");
|
||||
Date date = stunden.getItemValueDate("datdate");
|
||||
if (date == null) {
|
||||
continue;
|
||||
}
|
||||
// Get the week number and year from the date
|
||||
calendar.setTime(date);
|
||||
int weekNumber = calendar.get(Calendar.WEEK_OF_YEAR);
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
int yearWeek = year * 100 + weekNumber; // Unique key for each year + week combination
|
||||
|
||||
if (year < 2024) {
|
||||
logger.warning("Old Requirement in Auftrag " + auftrag.getUniqueID());
|
||||
}
|
||||
|
||||
// Accumulate the hours per week
|
||||
RequirementData steuerDataByWeek = hoursByWeek.getOrDefault(yearWeek, new RequirementData());
|
||||
steuerDataByWeek.add(total, "");
|
||||
hoursByWeek.put(yearWeek, steuerDataByWeek);
|
||||
|
||||
// Track the earliest and latest weeks
|
||||
earliestWeek = Math.min(earliestWeek, yearWeek);
|
||||
latestWeek = Math.max(latestWeek, yearWeek);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Berechnet das Chart zu den aktuell ermittelten Stunden
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
chartCfg = {
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [20, 10],
|
||||
}],
|
||||
labels: ['1', '2']
|
||||
}
|
||||
}
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String buildHoursChart() {
|
||||
|
||||
accumulateHoursByWeek();
|
||||
|
||||
// Step 2: Prepare the JSON structure and ensure we have all weeks from earliest
|
||||
// to latest
|
||||
JsonArrayBuilder dataBuilderTotal = Json.createArrayBuilder();
|
||||
JsonArrayBuilder labelsBuilder = Json.createArrayBuilder();
|
||||
|
||||
Calendar startCal = Calendar.getInstance();
|
||||
startCal.set(Calendar.YEAR, earliestWeek / 100);
|
||||
startCal.set(Calendar.WEEK_OF_YEAR, earliestWeek % 100);
|
||||
|
||||
Calendar endCal = Calendar.getInstance();
|
||||
endCal.set(Calendar.YEAR, latestWeek / 100);
|
||||
endCal.set(Calendar.WEEK_OF_YEAR, latestWeek % 100);
|
||||
|
||||
while (!startCal.after(endCal)) {
|
||||
int weekNumber = startCal.get(Calendar.WEEK_OF_YEAR);
|
||||
int year = startCal.get(Calendar.YEAR);
|
||||
int yearWeek = year * 100 + weekNumber;
|
||||
|
||||
// Add the saldo for the week or 0.0 if no data
|
||||
RequirementData requirementData = hoursByWeek.getOrDefault(yearWeek, new RequirementData());
|
||||
dataBuilderTotal.add(requirementData.total);
|
||||
|
||||
labelsBuilder.add(weekNumber + "/" + year); // Label as 'week/year'
|
||||
|
||||
// Move to the next week
|
||||
startCal.add(Calendar.WEEK_OF_YEAR, 1);
|
||||
}
|
||||
|
||||
// Step 3: Prepare the JSON structure
|
||||
JsonObjectBuilder jsonBuilder = Json.createObjectBuilder()
|
||||
.add("type", "bar")
|
||||
.add("data", Json.createObjectBuilder()
|
||||
.add("datasets", Json.createArrayBuilder()
|
||||
|
||||
.add(Json.createObjectBuilder() // Third dataset for 'total'
|
||||
.add("label", "Total")
|
||||
.add("backgroundColor", "#4bc0c0")
|
||||
.add("borderWidth", 1)
|
||||
.add("data", dataBuilderTotal)))
|
||||
|
||||
.add("labels", labelsBuilder));
|
||||
|
||||
// Step 4: Return the JSON structure as a string
|
||||
JsonObject chartCfg = jsonBuilder.build();
|
||||
return chartCfg.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to hold zoll and eust totals in an object. Needed to build
|
||||
* totals per week.
|
||||
*/
|
||||
class RequirementData {
|
||||
double total = 0.0;
|
||||
String status = "";
|
||||
|
||||
public RequirementData() {
|
||||
// default constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new stunden
|
||||
*
|
||||
* @param totalNew
|
||||
* @param statusNew
|
||||
*/
|
||||
public void add(double totalNew, String statusNew) {
|
||||
|
||||
total = total + totalNew;
|
||||
status = statusNew;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static double round(double value) {
|
||||
BigDecimal bd = BigDecimal.valueOf(value);
|
||||
bd = bd.setScale(2, RoundingMode.HALF_UP);
|
||||
return bd.doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* converts the Map List of a workitem into a List of ItemCollectons
|
||||
*/
|
||||
public static List<ItemCollection> explodeChildList(ItemCollection workitem) {
|
||||
return explodeChildList(workitem, CHILD_ITEM_PROPERTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* converts the Map List of a workitem into a List of ItemCollectons
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static List<ItemCollection> explodeChildList(ItemCollection workitem, String childItemName) {
|
||||
// convert current list of childItems into ItemCollection elements
|
||||
ArrayList<ItemCollection> childItems = new ArrayList<ItemCollection>();
|
||||
|
||||
List<Object> mapOrderItems = workitem.getItemValue(childItemName);
|
||||
for (Object mapOderItem : mapOrderItems) {
|
||||
if (mapOderItem instanceof Map) {
|
||||
ItemCollection itemCol = new ItemCollection((Map) mapOderItem);
|
||||
childItems.add(itemCol);
|
||||
}
|
||||
}
|
||||
return childItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the List of ItemCollections back into a List of Map elements
|
||||
*
|
||||
* @param workitem
|
||||
*/
|
||||
public static void implodeChildList(ItemCollection workitem, List<ItemCollection> childItems) {
|
||||
implodeChildList(workitem, childItems, CHILD_ITEM_PROPERTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the List of ItemCollections back into a List of Map elements
|
||||
*
|
||||
* @param workitem
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public static void implodeChildList(ItemCollection workitem, List<ItemCollection> childItems,
|
||||
String childItemName) {
|
||||
List<Map> mapOrderItems = new ArrayList<Map>();
|
||||
// convert the child ItemCollection elements into a List of Map
|
||||
if (childItems != null) {
|
||||
// iterate over all order items..
|
||||
for (ItemCollection orderItem : childItems) {
|
||||
mapOrderItems.add(orderItem.getAllItems());
|
||||
}
|
||||
workitem.replaceItemValue(childItemName, mapOrderItems);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
112
src/main/java/com/imixs/intern/SuperOfficeDatevService.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*******************************************************************************
|
||||
* Imixs Workflow
|
||||
* Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public
|
||||
* License at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Project:
|
||||
* http://www.imixs.org
|
||||
* http://java.net/projects/imixs-workflow
|
||||
*
|
||||
* Contributors:
|
||||
* Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika - Software Developer
|
||||
*******************************************************************************/
|
||||
|
||||
package com.imixs.intern;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.FileData;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.datev.export.DatevEvent;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.annotation.security.DeclareRoles;
|
||||
import jakarta.annotation.security.RunAs;
|
||||
import jakarta.ejb.LocalBean;
|
||||
import jakarta.ejb.Stateless;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.interceptor.Interceptor;
|
||||
|
||||
/**
|
||||
* Der DatevService entscheidet welches File Exportiert werden soll.
|
||||
*
|
||||
* @author rsoika
|
||||
*/
|
||||
|
||||
@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" })
|
||||
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
|
||||
@Stateless
|
||||
@LocalBean
|
||||
public class SuperOfficeDatevService {
|
||||
|
||||
private static Logger logger = Logger.getLogger(SuperOfficeDatevService.class.getName());
|
||||
|
||||
/**
|
||||
* This method reacts on CDI events of the type DatevEvent und gibt das richtige
|
||||
* PDF zurück.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public void onDatevEvent(@Observes @Priority(Interceptor.Priority.APPLICATION + 600) DatevEvent event) {
|
||||
ItemCollection invoice = event.getWorkitem();
|
||||
|
||||
if (event.getEventType() == DatevEvent.ON_EXPORT_FILE) {
|
||||
|
||||
// nur für Ausgangsrechnungen interessant - ansonsten default verhalten nutzen
|
||||
if (invoice.getModelVersion().startsWith("rechnungsausgang")) {
|
||||
// wir nehmen das erste PDF das mir "R" beginnt.
|
||||
|
||||
FileData lastFileData = null;
|
||||
List<FileData> fileDataList = invoice.getFileData();
|
||||
for (FileData fileData : fileDataList) {
|
||||
// we are only interested in files with sufix .pdf
|
||||
// and start with "R"
|
||||
if (!fileData.getName().toLowerCase().endsWith(".pdf")) {
|
||||
// not a PDF file...
|
||||
continue;
|
||||
}
|
||||
if (!fileData.getName().toLowerCase().startsWith("r")) {
|
||||
// ist keine Rechnung
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastFileData == null) {
|
||||
lastFileData = fileData;
|
||||
} else {
|
||||
// compare the $creation date....
|
||||
ItemCollection attributes = new ItemCollection(fileData.getAttributes());
|
||||
ItemCollection lastAttributes = new ItemCollection(lastFileData.getAttributes());
|
||||
|
||||
Date date = attributes.getItemValueDate("$created");
|
||||
Date lastDate = lastAttributes.getItemValueDate("$created");
|
||||
if (date != null && lastDate != null && (date.compareTo(lastDate) > 0)) {
|
||||
// this is a newer fileData!
|
||||
lastFileData = fileData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastFileData != null) {
|
||||
event.setFileData(lastFileData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
98
src/main/java/com/imixs/intern/SuperOfficePlugin.java
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package com.imixs.intern;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.DocumentService;
|
||||
import org.imixs.workflow.engine.plugins.AbstractPlugin;
|
||||
import org.imixs.workflow.exceptions.PluginException;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* Dieses Plugin berechnet die bezeihung Kunde->Auftrag->Requreimeent, usw....
|
||||
*
|
||||
* @author rsoika
|
||||
*
|
||||
*/
|
||||
public class SuperOfficePlugin extends AbstractPlugin {
|
||||
|
||||
@Inject
|
||||
DocumentService documentService;
|
||||
|
||||
private static Logger logger = Logger.getLogger(StatistikPlugin.class
|
||||
.getName());
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Skip if not a workitem and only run once a day!
|
||||
*
|
||||
* @throws PluginException
|
||||
*
|
||||
**/
|
||||
@Override
|
||||
public ItemCollection run(ItemCollection workitem, ItemCollection documentActivity) throws PluginException {
|
||||
|
||||
ItemCollection kontakt = null;
|
||||
ItemCollection auftrag = null;
|
||||
List<String> refs = workitem.getItemValueList("$workitemref", String.class);
|
||||
|
||||
if ("Auftrag".equals(workitem.getWorkflowGroup())) {
|
||||
// find Kontakt
|
||||
kontakt = findKontakt(workitem);
|
||||
if (kontakt != null) {
|
||||
// update kontakt info.....
|
||||
workitem.setItemValue("contact.name", kontakt.getItemValueString("_subject"));
|
||||
}
|
||||
}
|
||||
|
||||
if ("Requirement".equals(workitem.getWorkflowGroup())) {
|
||||
// find Auftrag
|
||||
auftrag = findAuftrag(workitem);
|
||||
|
||||
if (auftrag != null) {
|
||||
// kontakt = findKontakt(auftrag);
|
||||
// update kontakt info.....
|
||||
workitem.setItemValue("order.name", auftrag.getItemValueString("_subject"));
|
||||
workitem.setItemValue("contact.name", auftrag.getItemValueString("contact.name"));
|
||||
}
|
||||
|
||||
// convert efforts into a number
|
||||
String ef = workitem.getItemValueString("_effort_planed");
|
||||
ef = ef.replace(",", ".");
|
||||
workitem.setItemValue("_effort_planed", Double.parseDouble(ef));
|
||||
|
||||
}
|
||||
|
||||
return workitem;
|
||||
}
|
||||
|
||||
private ItemCollection findKontakt(ItemCollection workitem) {
|
||||
ItemCollection result = null;
|
||||
List<String> refs = workitem.getItemValueList("$workitemref", String.class);
|
||||
for (String _id : refs) {
|
||||
ItemCollection _workitem = documentService.load(_id);
|
||||
if (_workitem != null && "Kontakt".equals(_workitem.getItemValueString("$workflowgroup"))) {
|
||||
result = _workitem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ItemCollection findAuftrag(ItemCollection workitem) {
|
||||
ItemCollection result = null;
|
||||
List<String> refs = workitem.getItemValueList("$workitemref", String.class);
|
||||
for (String _id : refs) {
|
||||
ItemCollection _workitem = documentService.load(_id);
|
||||
if (_workitem != null && "Auftrag".equals(_workitem.getItemValueString("$workflowgroup"))) {
|
||||
result = _workitem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
791
src/main/webapp/layout/js/imixs-script-1.0.1.js
Normal file
|
|
@ -0,0 +1,791 @@
|
|||
/*******************************************************************************
|
||||
* Imixs Workflow - jQUery API Copyright (C) 2012 Imixs Software Solutions GmbH,
|
||||
* http://www.imixs.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You can receive a copy of the GNU General Public License at
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Project: http://www.imixs.org
|
||||
*
|
||||
* Contributors: Imixs Software Solutions GmbH - initial API and implementation
|
||||
* Ralph Soika - Software Developer
|
||||
******************************************************************************/
|
||||
|
||||
var imixsServiceLocationURI = null;
|
||||
var defaultModelVersion = null;
|
||||
var defaultProcessID = null;
|
||||
var requestLocale = null;
|
||||
var defaultActionClass = null;
|
||||
var cancelActionLabel = "Cancel";
|
||||
var defaultImage = "images/default.gif";
|
||||
|
||||
/**
|
||||
* Helper method to test for HTML 5 localStorage...
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
function hasLocalStorage() {
|
||||
try {
|
||||
return 'localStorage' in window && window['localStorage'] !== null;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to setup the workflow service
|
||||
*
|
||||
* @param aLocation -
|
||||
* prafix for RESTService URI
|
||||
* @param aDefaultModel -
|
||||
* default model version
|
||||
* @param aDefaultProcess -
|
||||
* default ProcessID
|
||||
*/
|
||||
function setupWorkflowService(aLocation, aDefaultModel, aDefaultProcessID) {
|
||||
imixsServiceLocationURI = aLocation;
|
||||
defaultModelVersion = aDefaultModel;
|
||||
defaultProcessID = aDefaultProcessID;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method set the default action class for workflow action buttons. If no
|
||||
* class is specified all action buttons will be styled as jQuery-UI button
|
||||
* classes.
|
||||
*
|
||||
* @param aClass
|
||||
*/
|
||||
function setDefaultActionClass(aClass) {
|
||||
defaultActionClass = aClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default cancel button label.
|
||||
*
|
||||
* @param aLabel
|
||||
*/
|
||||
function setCancelActionLabel(aLabel) {
|
||||
cancelActionLabel = aLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method clears the stored elements from the local cache
|
||||
*
|
||||
* @param identifier
|
||||
*/
|
||||
function clearWorkflowElement(identifier) {
|
||||
// return if not html5 (IE7/8)
|
||||
if (!hasLocalStorage())
|
||||
return;
|
||||
// alert('clearView....');
|
||||
localStorage.removeItem("org.imixs.workflow." + identifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method load a collection of workItems defined by a REST service URI.
|
||||
* After the Ajax request is finished successful the method calls
|
||||
* refreshWorklistView() to print the result into a page element.
|
||||
*
|
||||
* The result is stored into the clients localStorage.
|
||||
*
|
||||
*
|
||||
* @param service -
|
||||
* rest uri to be called ( workflow/worklistbyowner/null.json)
|
||||
* @param selector -
|
||||
* jquery selector for result list output
|
||||
*/
|
||||
function loadWorkitems(service, selector) {
|
||||
|
||||
// we first test if we still have the workflow groups in the local storage
|
||||
var data = null;
|
||||
if (hasLocalStorage())
|
||||
data = localStorage.getItem("org.imixs.workflow." + service);
|
||||
if (data == null) {
|
||||
// create the list of workitems using the RESTful service interface
|
||||
var serviceURL = imixsServiceLocationURI + service;
|
||||
if (serviceURL.indexOf('?') > -1)
|
||||
serviceURL = serviceURL + "&";
|
||||
else
|
||||
serviceURL = serviceURL + "?";
|
||||
$
|
||||
.getJSON(
|
||||
serviceURL,
|
||||
{
|
||||
count : "30",
|
||||
start : "0",
|
||||
items : "$uniqueid,txtworkflowgroup,txtworkflowstatus,txtworkflowsummary,txtworkflowimageurl,namcurrenteditor,$modified"
|
||||
}, function(data) {
|
||||
// json request finished store the worklist.....
|
||||
if (hasLocalStorage())
|
||||
localStorage.setItem("org.imixs.workflow."
|
||||
+ service, JSON.stringify(data));
|
||||
refreshWorklistView(service, selector);
|
||||
});
|
||||
|
||||
} else {
|
||||
// use workflow groups from cache
|
||||
refreshWorklistView(service, selector);
|
||||
}
|
||||
}
|
||||
|
||||
jQuery.events = function(expr) {
|
||||
|
||||
var rez = [], evo;
|
||||
jQuery(expr).each(function() {
|
||||
if (evo = jQuery._data(this, "events"))
|
||||
rez.push({
|
||||
element : this,
|
||||
events : evo
|
||||
});
|
||||
});
|
||||
return rez.length > 0 ? rez : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* This method fills the page element ID=worklist_view with the selected
|
||||
* workitems in a default layout.
|
||||
*
|
||||
* The method can be overwritten by binding a event listener
|
||||
*
|
||||
* <code>
|
||||
* $(document).on( "refreshWorklist", function(e, data,service) {
|
||||
....
|
||||
});
|
||||
* </code>
|
||||
*
|
||||
* If no refreshWorklist event is bound the method prints the worklist in a
|
||||
* default layout. A refreshWorlist handler can be bound to the global document
|
||||
* or to a specific selector
|
||||
*
|
||||
* <code>
|
||||
* $(document).on( "refreshWorklist", "#worklist", function(e, data,service) {
|
||||
....
|
||||
});
|
||||
* </code>
|
||||
*/
|
||||
function refreshWorklistView(service, selector) {
|
||||
|
||||
var dataString = null;
|
||||
var data = null;
|
||||
if (hasLocalStorage()) {
|
||||
dataString = localStorage.getItem("org.imixs.workflow." + service);
|
||||
data = JSON.parse(dataString);
|
||||
}
|
||||
|
||||
|
||||
if (data != null) {
|
||||
// test if data.entity is an array....
|
||||
if (!$.isArray(data.entity)) {
|
||||
data.entity = jQuery.makeArray(data.entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// checking if an external general refreshWorklist method was bound
|
||||
// there for we check the _data object for bound events....
|
||||
var handlerFound = false;
|
||||
var $ve = $._data(document, 'events');
|
||||
if ($ve != null && typeof ($ve.refreshWorklist) != 'undefined') {
|
||||
// the refreshWorklist method was bound! so now
|
||||
// test if a binding for the current selector exists...
|
||||
var handlerList = $ve.refreshWorklist;
|
||||
$(handlerList).each(function(index) {
|
||||
if (selector != null && selector == $(this).selector) {
|
||||
// yes! we have a specific handler!
|
||||
handlerFound = true;
|
||||
// trigger handler
|
||||
$(selector).trigger('refreshWorklist', [ data, service ]);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (handlerFound) {
|
||||
// return from method
|
||||
return;
|
||||
}
|
||||
|
||||
// no specific handler was found so we trigger the general handler
|
||||
// trigger external refreshWorklist method
|
||||
$(document).trigger('refreshWorklist', [ data, service ]);
|
||||
return;
|
||||
}
|
||||
|
||||
// we did not found any handler - so do default output
|
||||
|
||||
// clear list
|
||||
$("#worklist_view").empty();
|
||||
|
||||
if (data == null) {
|
||||
$("#worklist_view").append(
|
||||
"<li class=\"workitem\">Keine Daten vorhanden</li>");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// iterate over all workitems
|
||||
$
|
||||
.each(
|
||||
data.entity,
|
||||
function(i, workitem) {
|
||||
|
||||
var imgurl = workitem.item[4].value.$;
|
||||
// take defualt image if no image url is provided
|
||||
if (imgurl == null)
|
||||
imgurl = defaultImage;
|
||||
|
||||
var img = "<div class=\"workitem-thumb\"><img class=\"\" src=\""
|
||||
+ imgurl + "\" /></div>";
|
||||
var p_status = "<span class=\"workitem-summary\"><b>"
|
||||
+ workitem.item[1].value.$ + "</b>: "
|
||||
+ workitem.item[2].value.$ + "</span>";
|
||||
|
||||
$("#worklist_view")
|
||||
.append(
|
||||
"<li class=\"workitem\" onclick=\"loadWorkitem('"
|
||||
+ workitem.item[0].value.$
|
||||
+ "');\">"
|
||||
+ img
|
||||
+ "<div class=\"workitem-info\"><h3><a href=\"#\">"
|
||||
+ ""
|
||||
+ workitem.item[3].value.$
|
||||
+ "</a></h3>"
|
||||
+ p_status
|
||||
+ "</div><div style=\"clear:left;\" /></li>");
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// ############## Workitem ####################
|
||||
|
||||
/**
|
||||
* this method loads a single workItem from the REST service and calls the
|
||||
* method updateForm to print the content into a page. The optional selectorID
|
||||
* specifies the area where the form data is placed. If no seletorId is given
|
||||
* Imixs-Script searches for a section with the id #workitem_view.
|
||||
*
|
||||
*
|
||||
* @param uid -
|
||||
* $uniqueid of the workitem to be loaded
|
||||
* @param selectorId -
|
||||
* optinal param to define the section where the form data is filled
|
||||
* in
|
||||
*/
|
||||
function loadWorkitem(uid, selectorId) {
|
||||
|
||||
if (selectorId == null || selectorId == "")
|
||||
selectorId = '#workitem_view';
|
||||
|
||||
// allways reload the workitem!
|
||||
var data = null;
|
||||
// load the workitem by it's $uniqueid
|
||||
$.getJSON(imixsServiceLocationURI + "workflow/workitem/" + uid + ".json?",
|
||||
{
|
||||
// items :
|
||||
// "$uniqueid,$modelversion,$processid,txtworkflowgroup,txtworkflowstatus,txtworkflowsummary,txtworkflowimageurl,namcurrenteditor,$modified,txtworkflowabstract,_subject"
|
||||
}, function(data) {
|
||||
updateForm(data, selectorId);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates a page section with the current workitem data. The method
|
||||
* also rebuilds the activity section
|
||||
*
|
||||
* @param aWorkitem -
|
||||
* the data object
|
||||
* @param aSelector -
|
||||
* optinal param to define the section where the form data is filled
|
||||
* in
|
||||
*/
|
||||
function updateForm(aWorkitem, aSelector) {
|
||||
disableActivities(aSelector);
|
||||
loadProcessEntity(aWorkitem);
|
||||
loadActivityList(aWorkitem, aSelector);
|
||||
updateInputFields(aWorkitem, aSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates the input field values for all properties provided by the
|
||||
* current workItem. The method only updates fields in specified selector. If no
|
||||
* selectorId is provided the selectorId defaults to 'workitem_view'.
|
||||
*
|
||||
* Each value of an input element with a name corresponding to a item contained
|
||||
* in the current Workitem will be updated.
|
||||
*
|
||||
* The method also clears all available Input fields (this is because of the
|
||||
* case that a workItem did not provide a item for a specific input field. So in
|
||||
* this case we need to clear the input in any case)
|
||||
*
|
||||
* @param aworkitem
|
||||
* the workitem with the properties
|
||||
* @param sectionid
|
||||
* an optional selector
|
||||
*/
|
||||
function updateInputFields(aWorkitem, selectorId) {
|
||||
|
||||
if (selectorId == null || selectorId == "")
|
||||
selectorId = '#workitem_view';
|
||||
|
||||
$(selectorId).trigger('beforeRefresh');
|
||||
|
||||
/* clear input fields... */
|
||||
clear_form_elements(selectorId);
|
||||
|
||||
/*
|
||||
* next we test if an element with the current item name exists. Then the
|
||||
* .text() method will replace the content
|
||||
*/
|
||||
$.each(aWorkitem.item, function(i, item) {
|
||||
var tagName = selectorId + " [name=" + item.name + "]";
|
||||
var tagValue = "";
|
||||
|
||||
if (item.value != null && item.value.$ != null)
|
||||
tagValue = item.value.$;
|
||||
|
||||
// $ is not allowed in a id because of jquery internals...
|
||||
tagName = tagName.replace('$', '\\$');
|
||||
if ($(tagName).length > 0) {
|
||||
$(tagName).val(tagValue);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// see http://stackoverflow.com/questions/399867/custom-events-in-jquery
|
||||
$(selectorId).trigger('afterRefresh', aWorkitem);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method ad action buttons for the current workitem into the selectorID.
|
||||
* Each activity for the current processID will result in a button. The method
|
||||
* did not add activity buttons with the activityEntity property
|
||||
* keypublicresult!=0.
|
||||
*
|
||||
* The method also adds all necessary hidden fields for processing a workitem.
|
||||
*
|
||||
* @param workitem -
|
||||
* the current workitem
|
||||
*
|
||||
*/
|
||||
function updateActivities(workitem, selectorId) {
|
||||
|
||||
if (selectorId == null || selectorId == "")
|
||||
selectorId = '#workitem_view';
|
||||
|
||||
var modelversion = getEntityItemValue(workitem, "$modelversion");
|
||||
var processid = getEntityItemValue(workitem, "$processid");
|
||||
var unqiueid = getEntityItemValue(workitem, "$uniqueid");
|
||||
var isauthor = getEntityItemValue(workitem, "$isauthor");
|
||||
|
||||
// iterate over all activity entities
|
||||
var dataString = null;
|
||||
var currentActivityList = null;
|
||||
if (hasLocalStorage()) {
|
||||
dataString = localStorage.getItem("org.imixs.workflow.activities."
|
||||
+ modelversion + "." + processid);
|
||||
currentActivityList = JSON.parse(dataString);
|
||||
}
|
||||
|
||||
// clear list
|
||||
$(selectorId + " #workitem_activities").empty();
|
||||
|
||||
// iterarte over all activities if available...
|
||||
// activities will be only shown is workitem isNew or user isAuthor
|
||||
if (currentActivityList != null && (unqiueid == "" || isauthor == "true")) {
|
||||
// test if currentActivityList.entity is an array....
|
||||
if (!$.isArray(currentActivityList.entity))
|
||||
currentActivityList.entity = jQuery
|
||||
.makeArray(currentActivityList.entity);
|
||||
// iterate over all activities to build buttons...
|
||||
$
|
||||
.each(currentActivityList.entity,
|
||||
function(i, activity) {
|
||||
// only add button if keypublicresult!=0
|
||||
var testPublicResult = getEntityItemValue(activity,
|
||||
"keypublicresult");
|
||||
if ("0" != testPublicResult) {
|
||||
var actionName = getEntityItemValue(activity,
|
||||
"txtname");
|
||||
var actionID = getEntityItemValue(activity,
|
||||
"numactivityid");
|
||||
var tooltipText = getEntityItemValue(activity,
|
||||
"rtfdescription");
|
||||
addActionButton(selectorId, actionName,
|
||||
actionID, false, tooltipText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// append the cancel button
|
||||
$(selectorId + " #workitem_activities").append(
|
||||
"<input id=\"workflow_activity_cancel\" type=\"button\" value=\""
|
||||
+ cancelActionLabel + "\"></input>");
|
||||
// bind clearWorkitem method
|
||||
// we need to bind the click method using jquery because otherwise external
|
||||
// code can not unbind this call
|
||||
$(selectorId + " #workitem_activities #workflow_activity_cancel").click(
|
||||
function(event) {
|
||||
clearWorkitem(selectorId);
|
||||
});
|
||||
|
||||
// add $unqiueid, $modelversion, $activitid and $processid input fields if
|
||||
// yet not part of the form
|
||||
// $ is not allowed in a id because of jquery internals...
|
||||
if ($(selectorId + " [name=\\$activityid]").length <= 0)
|
||||
$(selectorId + " #workitem_activities").append(
|
||||
"<input type=\"hidden\" name=\"$activityid\"></input>");
|
||||
if ($(selectorId + " [name=\\$processid]").length <= 0)
|
||||
$(selectorId + " #workitem_activities").append(
|
||||
"<input type=\"hidden\" name=\"$processid\" value=\""
|
||||
+ processid + "\"></input>");
|
||||
if ($(selectorId + " [name=\\$uniqueid]").length <= 0)
|
||||
$(selectorId + " #workitem_activities").append(
|
||||
"<input type=\"hidden\" name=\"$uniqueid\" value=\"" + unqiueid
|
||||
+ "\"></input>");
|
||||
if ($(selectorId + " [name=\\$modelversion]").length <= 0)
|
||||
$(selectorId + " #workitem_activities").append(
|
||||
"<input type=\"hidden\" name=\"$modelversion\" value=\""
|
||||
+ modelversion + "\"></input>");
|
||||
if ($(selectorId + " [name=type]").length <= 0)
|
||||
$(selectorId + " #workitem_activities")
|
||||
.append(
|
||||
"<input type=\"hidden\" name=\"type\" value=\"workitem\"></input>");
|
||||
|
||||
// finally style all buttons...
|
||||
var sActionSelector = selectorId + " #workitem_activities input:button, "
|
||||
+ selectorId + " #workitem_activities input:submit";
|
||||
if (defaultActionClass == null)
|
||||
$(sActionSelector).button();
|
||||
else
|
||||
$(sActionSelector).addClass(defaultActionClass);
|
||||
|
||||
/* Imixs Tooltip support */
|
||||
// test if juery ui is availalbe....
|
||||
if ($.fn.tooltip) {
|
||||
|
||||
$("span.imixs-tooltip").prev().tooltip({
|
||||
position : {
|
||||
my : "left top+5",
|
||||
at : "left+10 bottom",
|
||||
collision : "flipfit"
|
||||
},
|
||||
show : {
|
||||
duration : 800
|
||||
},
|
||||
content : function() {
|
||||
var tooltip = $(this).next();
|
||||
tooltip.hide();
|
||||
return tooltip.text();
|
||||
}
|
||||
});
|
||||
// hide all imixs tooltips
|
||||
$("span.imixs-tooltip").hide();
|
||||
} // end of tooltip support
|
||||
|
||||
// trigger afterRefresh event
|
||||
$(selectorId + ' #workitem_activities').trigger('afterRefresh', workitem);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* clears all input fiels inside the given formpart
|
||||
*/
|
||||
function clear_form_elements(formpart) {
|
||||
|
||||
$(formpart).find(':input').each(function() {
|
||||
switch (this.type) {
|
||||
case 'text':
|
||||
case 'hidden':
|
||||
case 'password':
|
||||
case 'select-multiple':
|
||||
case 'select-one':
|
||||
case 'textarea':
|
||||
$(this).val('');
|
||||
break;
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
this.checked = false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method create a new empty workitem and clears also the workitem_view
|
||||
*/
|
||||
function clearWorkitem(selectorId) {
|
||||
if (selectorId == null || selectorId == "")
|
||||
selectorId = '#workitem_view';
|
||||
|
||||
newWorkitem = {
|
||||
"item" : [ {
|
||||
"name" : "$processid",
|
||||
"value" : {
|
||||
"@type" : "xs:int",
|
||||
"$" : defaultProcessID
|
||||
}
|
||||
}, {
|
||||
"name" : "$modelversion",
|
||||
"value" : {
|
||||
"@type" : "xs:string",
|
||||
"$" : defaultModelVersion
|
||||
}
|
||||
}, {
|
||||
"name" : "_subject",
|
||||
"value" : {
|
||||
"@type" : "xs:string",
|
||||
"$" : ""
|
||||
}
|
||||
} ]
|
||||
};
|
||||
|
||||
updateForm(newWorkitem, selectorId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method loads the specifiy processEntity. The method uses the
|
||||
* localStorage to cache processEntities already loaded
|
||||
*
|
||||
* @param workitem -
|
||||
* the current workitem
|
||||
*/
|
||||
function loadProcessEntity(workitem, selectorId) {
|
||||
|
||||
var processid = null;
|
||||
var modelversion = null;
|
||||
|
||||
// read processID and model version.....
|
||||
$.each(workitem.item, function(i, item) {
|
||||
|
||||
if (item.name == "$modelversion")
|
||||
modelversion = item.value.$;
|
||||
if (item.name == "$processid")
|
||||
processid = item.value.$;
|
||||
|
||||
if (modelversion != null && processid != null)
|
||||
return;
|
||||
|
||||
});
|
||||
|
||||
// we first test if we still have the Entity in the local storage
|
||||
var currentProcessEntity = null;
|
||||
if (hasLocalStorage())
|
||||
currentProcessEntity = localStorage
|
||||
.getItem("org.imixs.workflow.process." + modelversion + "."
|
||||
+ processid);
|
||||
if (currentProcessEntity == null) {
|
||||
// now we need to load the model information from the rest service...
|
||||
$
|
||||
.getJSON(imixsServiceLocationURI + "model/" + modelversion
|
||||
+ "/process/" + processid + ".json",
|
||||
function(data) {
|
||||
// cache the result
|
||||
if (hasLocalStorage())
|
||||
localStorage.setItem(
|
||||
"org.imixs.workflow.process."
|
||||
+ modelversion + "."
|
||||
+ processid, JSON
|
||||
.stringify(data));
|
||||
refreshWorkitemProcessView(currentProcessEntity,
|
||||
selectorId);
|
||||
});
|
||||
} else
|
||||
refreshWorkitemProcessView(currentProcessEntity, selectorId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method loads the specifiy activitylist. The method uses the localStorage
|
||||
* to cache Entities already loaded
|
||||
*
|
||||
* @param workitem -
|
||||
* the current workitem
|
||||
*
|
||||
* @param selectorId -
|
||||
* optional param to force a refresh of a specific section
|
||||
*/
|
||||
function loadActivityList(workitem, selectorId) {
|
||||
|
||||
var modelversion = getEntityItemValue(workitem, "$modelversion");
|
||||
var processid = getEntityItemValue(workitem, "$processid");
|
||||
|
||||
// we first test if we still have the Entity in the local storage
|
||||
var currentProcessEntity = null;
|
||||
if (hasLocalStorage())
|
||||
currentProcessEntity = localStorage
|
||||
.getItem("org.imixs.workflow.activities." + modelversion + "."
|
||||
+ processid);
|
||||
if (currentProcessEntity == null) {
|
||||
// now we need to load the model information from the rest service...
|
||||
$.getJSON(
|
||||
imixsServiceLocationURI + "model/" + modelversion
|
||||
+ "/activities/" + processid + ".json",
|
||||
function(data) {
|
||||
// cache the result
|
||||
if (hasLocalStorage())
|
||||
localStorage.setItem("org.imixs.workflow.activities."
|
||||
+ modelversion + "." + processid, JSON
|
||||
.stringify(data));
|
||||
updateActivities(workitem, selectorId);
|
||||
}).error(function() {
|
||||
// if an error occur we also need to update the activityview....
|
||||
updateActivities(workitem, selectorId);
|
||||
});
|
||||
} else
|
||||
updateActivities(workitem, selectorId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* this method writes the html code for the current ProcessEntity into the
|
||||
* element workitem_view
|
||||
*
|
||||
* @param aProcessEntity
|
||||
* the aProcessEntity to be loaded
|
||||
*/
|
||||
function refreshWorkitemProcessView(aprocessEntity, selectorId) {
|
||||
// ;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by the loadWorkitem() method to disable any action
|
||||
* buttons from the current form until the workitem_view is refreshed
|
||||
* completley. This is only a helper method to avoid inconsistent submits if the
|
||||
* refresh process of the workitem_view will break for any reason.
|
||||
*/
|
||||
function disableActivities(selectorId) {
|
||||
$(':input:button, :input:submit', selectorId + ' #workitem_activities')
|
||||
.each(function() {
|
||||
// disable the button...
|
||||
$(this).attr('disabled', 'disabled');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a workflow action buttion int a defined section
|
||||
*
|
||||
* @param selectorId -
|
||||
* the name of the section the buttion should be placed in
|
||||
* @param actionName -
|
||||
* the name of the button
|
||||
* @param activityID -
|
||||
* the activity entity ID to be processed
|
||||
* @param tooltipText -
|
||||
* optional tooltip for the button
|
||||
* @param bInsert -
|
||||
* optional, if true the button will be inserted at the first child
|
||||
* element of the selectior
|
||||
*/
|
||||
function addActionButton(selectorId, actionName, activityID, bInsert,
|
||||
tooltipText) {
|
||||
if (selectorId == null || selectorId == "")
|
||||
selectorId = '#workitem_view';
|
||||
|
||||
// test if selector was found
|
||||
if ($(selectorId + " #workitem_activities").length) {
|
||||
|
||||
// build conclick event....
|
||||
var activityScript = "onclick=\"processWorkitem('" + activityID + "');";
|
||||
|
||||
// build tooltip span tag
|
||||
var tooltip = "";
|
||||
if (tooltipText != "")
|
||||
tooltip = "<span class=\"imixs-tooltip\">" + tooltipText
|
||||
+ "</span>";
|
||||
|
||||
// insert at the bginning of the tag?
|
||||
if (bInsert)
|
||||
$(selectorId + " #workitem_activities").prepend(
|
||||
"<input type=\"submit\" id=\"workflow_activity_"
|
||||
+ activityID + "\" value=\"" + actionName + "\" "
|
||||
+ activityScript + "\"title=\"\"></input>");
|
||||
else
|
||||
$(selectorId + " #workitem_activities").append(
|
||||
"<input type=\"submit\" id=\"workflow_activity_"
|
||||
+ activityID + "\" value=\"" + actionName + "\" "
|
||||
+ activityScript + "\"title=\"\"></input>"
|
||||
+ tooltip);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates the $activityid input field .
|
||||
*
|
||||
* @param activityid
|
||||
*/
|
||||
function processWorkitem(activityid) {
|
||||
$('#workitem_view').trigger('beforeProcess');
|
||||
|
||||
var tagName = "#workitem_activities [name=\\$activityid]";
|
||||
if ($(tagName).length > 0) {
|
||||
$(tagName).val(activityid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the value of a specified item inside an entity. Maybe we
|
||||
* can optimize the method???
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
function getEntityItemValue(entity, itemname) {
|
||||
var value = "";
|
||||
$.each(entity.item, function(i, item) {
|
||||
if (item.name == itemname) {
|
||||
if (item.value != null) {
|
||||
|
||||
if ($.isArray(item.value))
|
||||
value = item.value[0].$;
|
||||
else
|
||||
value = item.value.$;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the value of a specified item inside an entity. Maybe we
|
||||
* can optimize the method???
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
function getEntityItemValueArray(entity, itemname) {
|
||||
var value = "";
|
||||
$.each(entity.item, function(i, item) {
|
||||
if (item.name == itemname) {
|
||||
if (item.value != null) {
|
||||
|
||||
if ($.isArray(item.value))
|
||||
value = item.value;
|
||||
else
|
||||
value = jQuery.makeArray(item.value);
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
return value;
|
||||
|
||||
}
|
||||
320
src/main/webapp/pages/admin/datev_config.xhtml
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:i="http://java.sun.com/jsf/composite/imixs"
|
||||
xmlns:c="http://java.sun.com/jsp/jstl/core"
|
||||
xmlns:marty="http://java.sun.com/jsf/composite/marty"
|
||||
template="/layout/template.xhtml">
|
||||
|
||||
<ui:define name="content">
|
||||
<f:view>
|
||||
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
function updateStatustPanel(data) {
|
||||
//initUserInput($('#userselector_id'));
|
||||
if (data.status === 'success') {
|
||||
// select with wildcard operator
|
||||
$('[id$=status_panel]').imixsLayout();
|
||||
}
|
||||
}
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
<h:form id="import_form_id" enctype="multipart/form-data">
|
||||
|
||||
<div class="imixs-form">
|
||||
<div class="imixs-header">
|
||||
<h1>DATEV</h1>
|
||||
</div>
|
||||
|
||||
<div class="imixs-body">
|
||||
<div class="imixs-tabs">
|
||||
<ul>
|
||||
<li><a href="#tab-1">Einstellungen</a></li>
|
||||
<li><a href="#tab-2">Import</a></li>
|
||||
<li><a href="#tab-3">Export</a></li>
|
||||
</ul>
|
||||
|
||||
<div id="tab-1">
|
||||
<!-- **** Einstellungen ***** -->
|
||||
<div class="imixs-form-section">
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<h3>DATEV Einstellungen</h3>
|
||||
<p>Definieren Sie hier die DATEV Parameter die Ihnen von Ihrem Steuerberater mitgeteilt wurden.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="imixs-form-section-2">
|
||||
|
||||
<dl>
|
||||
<dt>DATEV Mandant Name</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{datevController.configuration.item['datev.client.name']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>DATEV Mandantennummer </dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{datevController.configuration.item['datev.client.id']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
DATEV Beraternummer <span class="imixs-required">*</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<h:inputText required="true"
|
||||
value="#{datevController.configuration.item['datev.consultant.id']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>BU Schlüssel:</dt>
|
||||
<dd>
|
||||
|
||||
<h:inputTextarea required="false"
|
||||
converter="org.imixs.VectorConverter"
|
||||
style="height: 8em; width: 100%;"
|
||||
value="#{datevController.configuration.itemList['datev.buschluessel']}">
|
||||
</h:inputTextarea>
|
||||
<span style="font-size:0.7rem;">Format: BEZEICHNUNG | DATEV_BU_SCHLUESSEL | PROZENTSATZ</span>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
DATEV WJ-Beginn (MMTT) <span class="imixs-required">* <h:message
|
||||
for="fiscalstart" /></span>
|
||||
</dt>
|
||||
<dd>
|
||||
<h:inputText value="#{datevController.configuration.item['datev.fiscal_start']}"
|
||||
id="fiscalstart" required="false"/>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>DATEV Sachkontennummernlänge</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{datevController.configuration.item['datev.sachkontennummernlaenge']}" />
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Kostenstelle I. (Nummer|Bezeichnung)</dt>
|
||||
<dd>
|
||||
<h:inputTextarea required="false"
|
||||
converter="org.imixs.VectorConverter"
|
||||
style="height: 8em; width: 100%;"
|
||||
value="#{datevController.configuration.itemList['datev.kostenstelle1']}">
|
||||
</h:inputTextarea>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Kostenstellen II. (Nummer|Bezeichnung)</dt>
|
||||
<dd>
|
||||
<h:inputTextarea required="false"
|
||||
converter="org.imixs.VectorConverter"
|
||||
style="height: 8em; width: 100%;"
|
||||
value="#{datevController.configuration.itemList['datev.kostenstelle2']}">
|
||||
</h:inputTextarea>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-2">
|
||||
<!-- **** DATEV import ***** -->
|
||||
<div class="imixs-form-section">
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<h3>Import DATEV Stammdaten</h3>
|
||||
<ul>
|
||||
<li>Fügen Sie hier die zu importierende DATEV Datei an.</li>
|
||||
<li>Die Datei muss im CSV Format vorliegen.</li>
|
||||
|
||||
<li>Die Datei muss zwei Header Zeilen enthalten:
|
||||
<ol>
|
||||
<li>Zeile: Datenart - z.B. "Kontobeschriftungen"</li>
|
||||
<li>Zeile: Feldbezeichnungen - z.B. "Konto,
|
||||
Kontobezeichnung"</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Fügen Sie immer nur eine Datei für den Import an!</li>
|
||||
<li>Der Import kann einige Minuten in Anspruch nehmen.</li>
|
||||
<li>Brechen Sie den Vorgang nicht ab und warten Sie bis
|
||||
der Import vollständig abgeschlossen ist.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Importdatei wählen:</dt>
|
||||
<dd>
|
||||
<i:imixsFileUpload id="file_upload_id"
|
||||
workitem="#{datevController.importData}"
|
||||
context_url="#{facesContext.externalContext.requestContextPath}/rest-service/workflow/workitem/#{workflowController.workitem.item['$uniqueid']}"
|
||||
hideatachments="true" />
|
||||
<h:panelGroup layout="block"
|
||||
styleClass="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;"
|
||||
rendered="#{! empty datevController.importData.item['log']}">
|
||||
<pre>#{datevController.importData.item['log']}</pre>
|
||||
|
||||
</h:panelGroup>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Encoding </dt>
|
||||
<dd>
|
||||
<h:inputText required="false" style="width: 220px;"
|
||||
value="#{datevController.configuration.item['datev.encoding']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
<h:commandButton
|
||||
actionListener="#{datevController.startImport}"
|
||||
value="Start Import">
|
||||
</h:commandButton>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="tab-3">
|
||||
|
||||
<!-- **** Export Buchunsstapel ***** -->
|
||||
<div class="imixs-form-section">
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<h3>Export DATEV Buchungsstapel</h3>
|
||||
<p>Definieren Sie hier den Export Workflow sowie die Reportdefinition.</p>
|
||||
</div>
|
||||
|
||||
<h:panelGroup layout="block" id="report_selection"
|
||||
styleClass="imixs-form-section-2">
|
||||
<dl>
|
||||
<dt>
|
||||
DATEV Schnittstellen-Typ <span class="imixs-required">*</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<h:selectOneRadio
|
||||
value="#{datevController.configuration.item['export.type']}"
|
||||
required="true">
|
||||
<f:selectItem itemValue="xml"
|
||||
itemLabel="DATEV Belegsatzschnittstelle im XML-Format"></f:selectItem>
|
||||
<f:selectItem itemValue="csv"
|
||||
itemLabel="DATEV-Format (csv)"></f:selectItem>
|
||||
<f:ajax render="report_selection"/>
|
||||
</h:selectOneRadio>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
DATEV Report Definitionen <span class="imixs-required">*</span>
|
||||
</dt>
|
||||
<dd>
|
||||
Belegexport:
|
||||
<h:inputText required="true"
|
||||
value="#{datevController.configuration.item['report.invoices']}">
|
||||
</h:inputText>
|
||||
|
||||
<h:panelGroup
|
||||
rendered="#{'xml' eq datevController.configuration.item['export.type']}">
|
||||
<br />
|
||||
Dokumente: <h:inputText required="false"
|
||||
value="#{datevController.configuration.item['report.documents']}">
|
||||
</h:inputText>
|
||||
</h:panelGroup>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</h:panelGroup>
|
||||
<div class="imixs-form-section-2">
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
DATEV Model Version <span class="imixs-required">*</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<h:inputText required="true"
|
||||
value="#{datevController.configuration.item['model.version']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
DATEV Initial Task <span class="imixs-required">*</span>
|
||||
</dt>
|
||||
<dd>
|
||||
<h:inputText required="true"
|
||||
value="#{datevController.configuration.item['initial.task']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="imixs-form-section">
|
||||
<p>
|
||||
<span class="typcn typcn-lightbulb"></span> Der Initaltask
|
||||
muss einen Report definieren, der die Abfrage und das Stylesheet enthält.
|
||||
Die Rechnungen werden automatisch nach dem
|
||||
Attribut "datev.client.id" sowie der Buchungsperiode gruppiert.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="imixs-footer">
|
||||
<h:outputLabel value="#{message.modified}: " />
|
||||
<h:outputText
|
||||
value="#{datevController.configuration.item['$modified']}">
|
||||
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
|
||||
pattern="#{message.dateTimePattern}" />
|
||||
</h:outputText>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<h:commandButton
|
||||
actionListener="#{datevController.saveConfiguration()}"
|
||||
value="#{message.save}">
|
||||
</h:commandButton>
|
||||
|
||||
<h:commandButton value="#{message.close}" action="notes" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</h:form>
|
||||
</f:view>
|
||||
</ui:define>
|
||||
|
||||
|
||||
|
||||
</ui:composition>
|
||||
337
src/main/webapp/pages/admin/document_import.xhtml
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:i="http://java.sun.com/jsf/composite/imixs"
|
||||
xmlns:c="http://java.sun.com/jsp/jstl/core"
|
||||
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
|
||||
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
|
||||
xmlns:marty="http://java.sun.com/jsf/composite/marty"
|
||||
template="/layout/template.xhtml">
|
||||
|
||||
<ui:define name="content">
|
||||
<f:view>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function() {
|
||||
//$('.imixsdatatable').layoutImixsTable();
|
||||
});
|
||||
|
||||
|
||||
// This method refreshs the layout
|
||||
function updateOptions(data) {
|
||||
if (data.status === 'success') {
|
||||
$('[id$=Optionlist]').imixsLayout();
|
||||
|
||||
/* var id='#'+data.source.id;
|
||||
if (id.indexOf("input")>-1) {
|
||||
$(id).focus();
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
|
||||
<h:form id="import_form_id">
|
||||
|
||||
<div class="imixs-form">
|
||||
<div class="imixs-header">
|
||||
<h1>Dokument Import</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="imixs-body">
|
||||
|
||||
|
||||
<div class="imixs-tabs">
|
||||
<ul>
|
||||
<li><a href="#tab-1">Timer Setting</a></li>
|
||||
<li><a href="#tab-2">Data Sources</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- ### Timer ### -->
|
||||
<div id="tab-1">
|
||||
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<p><span class="typcn typcn-lightbulb"></span> Define a crontab to schedule the import processor.</p>
|
||||
</div>
|
||||
<ui:include src="sub_scheduler_control.xhtml">
|
||||
<ui:param name="schedulerController"
|
||||
value="#{documentImportController}" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<!-- ### SMTP ### -->
|
||||
<div id="tab-2">
|
||||
|
||||
<div class="ui-state-highlight ui-corner-all"
|
||||
style="margin-bottom: 10px; padding: .5em;">
|
||||
<p><span class="typcn typcn-lightbulb"></span> Define a destination IMAP server and assign mail addresses to specific workflow groups.</p>
|
||||
</div>
|
||||
<div class="imixs-form-panel">
|
||||
|
||||
<!-- ### Sources ### -->
|
||||
<h:panelGroup layout="block"
|
||||
id="imapOptionlist" binding="#{imapOptionlistContainer}">
|
||||
<f:ajax onevent="updateOptions">
|
||||
<table class="imixsdatatable"
|
||||
style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10px;text-align: center;">Pos</th>
|
||||
<th style="width: 100px;text-align: center;">Type</th>
|
||||
<th style="">Workflowgroup</th>
|
||||
<th style="">Modelversion</th>
|
||||
<th style="">Task</th>
|
||||
<th style="">Event</th>
|
||||
<th style="width: 110px;">
|
||||
<!-- delete -->
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<ui:repeat var="source" value="#{documentImportController.sources}">
|
||||
|
||||
<tr>
|
||||
<!-- pos -->
|
||||
<td style=" text-align: center;">
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.selectSource(source.item['index'])}">#<h:outputText
|
||||
value="#{source.item['index']}" />
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
</td>
|
||||
|
||||
<!-- type -->
|
||||
<td style="text-align: center;">
|
||||
<h:outputText value="#{source.item['type']}" />
|
||||
</td>
|
||||
<!-- Workflowgroup -->
|
||||
<td><h:outputText
|
||||
value="#{source.item['workflowgroup']}" />
|
||||
</td>
|
||||
|
||||
<td><h:outputText
|
||||
value="#{source.item['modelversion']}" />
|
||||
</td>
|
||||
<td><h:outputText
|
||||
value="#{source.item['task']}" />
|
||||
</td>
|
||||
<td><h:outputText
|
||||
value="#{source.item['event']}" />
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.moveSourceDown(source.item['index'])}">
|
||||
<span class="typcn typcn-arrow-down-thick imixs-state-info"></span>
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.moveSourceUp(source.item['index'])}">
|
||||
<span class="typcn typcn-arrow-up-thick imixs-state-info"></span>
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink>
|
||||
|
||||
<h:commandLink
|
||||
actionListener="#{documentImportController.removeSource(source.item['index'])}">
|
||||
<span class="typcn typcn-trash imixs-state-info"></span>
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandLink></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</ui:repeat>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<!-- add button -->
|
||||
<h:commandButton
|
||||
value="#{message.add}"
|
||||
actionListener="#{documentImportController.addSource()}">
|
||||
<f:ajax render="#{imapOptionlistContainer.clientId}"
|
||||
onevent="updateOptions" />
|
||||
</h:commandButton>
|
||||
|
||||
|
||||
|
||||
<!-- ### Subform for selected source ### -->
|
||||
|
||||
<h:panelGroup layout="block" rendered="#{! empty documentImportController.source}" styleClass="imixs-form-panel">
|
||||
<h3>Order ID #<h:outputText value="#{documentImportController.source.item['index']}"/></h3>
|
||||
<div class="imixs-form-section-3">
|
||||
<dl>
|
||||
<dt>Type</dt>
|
||||
<dd>
|
||||
<h:selectOneRadio value="#{documentImportController.source.item['type']}">
|
||||
<f:selectItem itemLabel="IMAP" itemValue="IMAP"/>
|
||||
<f:selectItem itemLabel="FTP" itemValue="FTP"/>
|
||||
</h:selectOneRadio>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Workflowgroup</dt>
|
||||
<dd>
|
||||
<h:selectOneMenu
|
||||
value="#{documentImportController.source.item['workflowgroup']}">
|
||||
<c:forEach items="#{modelController.workflowGroups}" var="group">
|
||||
<f:selectItem itemLabel="#{group}" itemValue="#{group}" />
|
||||
</c:forEach>
|
||||
</h:selectOneMenu>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="imixs-form-section-3">
|
||||
|
||||
<dl>
|
||||
<dt>Workflowmodel</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{documentImportController.source.item['workflowmodel']}"/>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Task ID</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{documentImportController.source.item['task']}"/>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Event ID</dt>
|
||||
<dd>
|
||||
<h:inputText
|
||||
value="#{documentImportController.source.item['event']}"/>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<!-- IMAP -->
|
||||
<div class="imixs-form-section-3">
|
||||
<dl>
|
||||
<dt>Server : Port</dt>
|
||||
<dd>
|
||||
<h:inputText style="width:80%;"
|
||||
value="#{documentImportController.source.item['server']}">
|
||||
</h:inputText> : <h:inputText style="width:15%;"
|
||||
value="#{documentImportController.source.item['port']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>User</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{documentImportController.source.item['user']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Password</dt>
|
||||
<dd>
|
||||
<h:inputSecret required="false" redisplay="true"
|
||||
value="#{documentImportController.source.item['password']}">
|
||||
</h:inputSecret>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="imixs-form-section">
|
||||
<dl>
|
||||
<dt>Selector</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{documentImportController.source.item['selector']}">
|
||||
</h:inputText>
|
||||
<p class="small">A selector can be an optional regular expression to be used to select a subset of data</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Options</dt>
|
||||
<dd>
|
||||
<h:inputTextarea required="false"
|
||||
style="height: 5em; width: 100%;"
|
||||
value="#{documentImportController.source.item['options']}">
|
||||
</h:inputTextarea>
|
||||
<p class="small">You can apply custom properties here.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</h:panelGroup> <!-- end of source subform -->
|
||||
|
||||
|
||||
|
||||
|
||||
</f:ajax>
|
||||
|
||||
|
||||
</h:panelGroup>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="imixs-footer">
|
||||
<h:outputLabel value="#{message.modified}: " />
|
||||
<h:outputText
|
||||
value="#{documentImportController.configuration.item['$modified']}">
|
||||
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
|
||||
pattern="#{message.dateTimePattern}" />
|
||||
</h:outputText>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<h:commandButton
|
||||
actionListener="#{documentImportController.saveConfiguration()}"
|
||||
action="/pages/admin/document_import"
|
||||
value="#{message.save}">
|
||||
</h:commandButton>
|
||||
|
||||
|
||||
<h:commandButton value="#{message.close}" action="notes" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</h:form>
|
||||
</f:view>
|
||||
</ui:define>
|
||||
|
||||
|
||||
|
||||
</ui:composition>
|
||||
268
src/main/webapp/pages/admin/sepa_config.xhtml
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:i="http://java.sun.com/jsf/composite/imixs"
|
||||
xmlns:c="http://java.sun.com/jsp/jstl/core"
|
||||
xmlns:marty="http://java.sun.com/jsf/composite/marty"
|
||||
xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
|
||||
template="/layout/template.xhtml">
|
||||
|
||||
<ui:define name="content">
|
||||
<f:view>
|
||||
|
||||
<script type="text/javascript">
|
||||
/*<![CDATA[*/
|
||||
|
||||
function updateStatustPanel(data) {
|
||||
//initUserInput($('#userselector_id'));
|
||||
if (data.status === 'success') {
|
||||
// select with wildcard operator
|
||||
$('[id$=status_panel]').imixsLayout();
|
||||
}
|
||||
}
|
||||
|
||||
// display summary
|
||||
$(document).ready(function() {
|
||||
// erste Zeile hinzufügen, falls tabelle noch leer ist
|
||||
var posTableEmpty=#{empty sepaController.dbtrList};
|
||||
if (posTableEmpty) {
|
||||
// click on add button
|
||||
posButton=$("[data-id='addposbutton_id']");
|
||||
if (posButton) {
|
||||
$(posButton).click();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This method refreshs the layout
|
||||
function updateSepaList(data) {
|
||||
if (data.status === 'success') {
|
||||
$('[id$=dbtrlist]').imixsLayout();
|
||||
$('[id$=cdtrlist]').imixsLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/*]]>*/
|
||||
</script>
|
||||
|
||||
|
||||
<h:form id="import_form_id">
|
||||
<div class="imixs-form">
|
||||
<div class="imixs-header">
|
||||
<h1>SEPA</h1>
|
||||
</div>
|
||||
|
||||
<div class="imixs-body">
|
||||
<!-- **** General info ***** -->
|
||||
<div class="imixs-form-panel">
|
||||
<h:panelGroup layout="block" styleClass="imixs-form-section"
|
||||
id="dbtrlist" binding="#{dbtrlistContainer}">
|
||||
<h1>Debitor IBAN/BIC</h1>
|
||||
<p>
|
||||
<span class="typcn typcn-lightbulb"></span> The Debitor IBAN/BIC configuration list
|
||||
can be used for SEPA payments.
|
||||
</p>
|
||||
<f:ajax render="dbtrlist" onevent="updateSepaList">
|
||||
<table class="imixsdatatable imixs-orderitems">
|
||||
<tr>
|
||||
<th style="width: 140px">ID</th>
|
||||
<th style="">Bank<span class="imixs-required">
|
||||
*</span></th>
|
||||
<th style="width: 250px;">IBAN</th>
|
||||
<th style="width: 150px;">BIC</th>
|
||||
<th style="width: 150px;">Report (optional)</th>
|
||||
<th style="width: 50px">
|
||||
<!-- delete -->
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<ui:repeat var="dbtr"
|
||||
value="#{sepaController.dbtrList}">
|
||||
<tr>
|
||||
<!-- ID -->
|
||||
<td><h:inputText value="#{dbtr.item['name']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- dbtr.name -->
|
||||
<td><h:inputText value="#{dbtr.item['dbtr.name']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- dbtr.iban -->
|
||||
<td><h:inputText value="#{dbtr.item['dbtr.iban']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- dbtr.bic -->
|
||||
<td><h:inputText value="#{dbtr.item['dbtr.bic']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- dbtr.bic -->
|
||||
<td><h:inputText value="#{dbtr.item['report']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
|
||||
<td><h:commandLink
|
||||
actionListener="#{sepaController.removeDbtr(dbtr.item['name'])}">
|
||||
<span class="typcn typcn-trash imixs-state-info"></span>
|
||||
<f:ajax render="#{dbtrlistContainer.clientId}"
|
||||
onevent="updateSepaList" />
|
||||
</h:commandLink></td>
|
||||
</tr>
|
||||
</ui:repeat>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<!-- add button -->
|
||||
<h:commandButton value="#{message.add}"
|
||||
a:data-id="addposbutton_id"
|
||||
actionListener="#{sepaController.addDbtr}">
|
||||
</h:commandButton>
|
||||
</f:ajax>
|
||||
</h:panelGroup>
|
||||
|
||||
|
||||
<h:panelGroup layout="block" styleClass="imixs-form-section"
|
||||
id="cdtrlist" binding="#{cdtrlistContainer}">
|
||||
<h1>Creditor IBAN/BIC</h1>
|
||||
<p>
|
||||
<span class="typcn typcn-lightbulb"></span> The Creditor IBAN/BIC configuration list
|
||||
can be used for SEPA Direct Debit.
|
||||
</p>
|
||||
<f:ajax render="cdtrlist" onevent="updateSepaList">
|
||||
<table class="imixsdatatable imixs-orderitems">
|
||||
<tr>
|
||||
<th style="width: 140px">ID</th>
|
||||
<th style="">Bank<span class="imixs-required">
|
||||
*</span></th>
|
||||
<th style="width: 250px;">IBAN</th>
|
||||
<th style="width: 150px;">BIC</th>
|
||||
<th style="width: 150px;">Report (optional)</th>
|
||||
<th style="width: 50px">
|
||||
<!-- delete -->
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<ui:repeat var="cdtr"
|
||||
value="#{sepaController.cdtrList}">
|
||||
<tr>
|
||||
<!-- ID -->
|
||||
<td><h:inputText value="#{cdtr.item['name']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- cdtr.name -->
|
||||
<td><h:inputText value="#{cdtr.item['cdtr.name']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- cdtr.iban -->
|
||||
<td><h:inputText value="#{cdtr.item['cdtr.iban']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- cdtr.bic -->
|
||||
<td><h:inputText value="#{cdtr.item['cdtr.bic']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
<!-- cdtr.report -->
|
||||
<td><h:inputText value="#{cdtr.item['report']}"
|
||||
style="width:100%;" /></td>
|
||||
|
||||
|
||||
<td><h:commandLink
|
||||
actionListener="#{sepaController.removeCdtr(cdtr.item['name'])}">
|
||||
<span class="typcn typcn-trash imixs-state-info"></span>
|
||||
<f:ajax render="#{cdtrlistContainer.clientId}"
|
||||
onevent="updateSepaList" />
|
||||
</h:commandLink></td>
|
||||
</tr>
|
||||
</ui:repeat>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<!-- add button -->
|
||||
<h:commandButton value="#{message.add}"
|
||||
a:data-id="addposbutton_id"
|
||||
actionListener="#{sepaController.addCdtr}">
|
||||
</h:commandButton>
|
||||
</f:ajax>
|
||||
</h:panelGroup>
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
<h1>Model Configuration</h1>
|
||||
<div class="imixs-form-section">
|
||||
<p>
|
||||
<span class="typcn typcn-lightbulb"></span> The initial task
|
||||
must define a report containing the query and style sheet
|
||||
information. Invoices will be automatically grouped by the
|
||||
attribute "_sepa_iban". If this attribute is not set, the
|
||||
default sepa_iban will be assigned to the invoice before
|
||||
processed. The SEPA workflow may optional include a
|
||||
"invoice_update" item definition.
|
||||
</p>
|
||||
</div>
|
||||
<div class="imixs-form-section-2">
|
||||
<dl>
|
||||
<dt>SEPA Model Version</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{sepaController.configuration.item['_model_version']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>SEPA Initial Task</dt>
|
||||
<dd>
|
||||
<h:inputText required="false"
|
||||
value="#{sepaController.configuration.item['_initial_task']}">
|
||||
</h:inputText>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="imixs-footer">
|
||||
<h:outputLabel value="#{message.modified}: " />
|
||||
<h:outputText
|
||||
value="#{sepaController.configuration.item['$modified']}">
|
||||
<f:convertDateTime timeZone="#{message.timeZone}" type="both"
|
||||
pattern="#{message.dateTimePattern}" />
|
||||
</h:outputText>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
<h:commandButton
|
||||
actionListener="#{sepaController.saveConfiguration()}"
|
||||
value="#{message.save}">
|
||||
</h:commandButton>
|
||||
|
||||
<h:commandButton value="#{message.close}" action="notes" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</h:form>
|
||||
|
||||
|
||||
</f:view>
|
||||
</ui:define>
|
||||
|
||||
|
||||
|
||||
|
||||
</ui:composition>
|
||||