First commit waiting for Budget Alert

This commit is contained in:
2025-09-04 13:37:35 +01:00
commit 2d681f27f5
4563 changed files with 1061534 additions and 0 deletions

View File

@ -0,0 +1,34 @@
Overview
------
This module adds tools that helps to create or edit a axelor module directly from the Axelor Open Platform web interface.
The module components like domain, view, report,..etc could be easily created by using those tools.
It also provides a support to create and apply the workflow.
It generate a module code and store it in to the specified source directory.
All changes could be applied to the working instance with just one button click.
Dependencies
------
* axelor-tool
* axelor-exception
* axelor-message
Install
------
* Put the axelor-studio with its dependencies in to the app module's module path.
* Set the following properties in the app module.
- `studio.source.dir:` A path to the app module's source directory.
- `studio.adk.dir:` A path to the axelor-open-platform that is required to build a module.
- `studio.restart.log:` A path to any text file. It will store the log of the backend script that restart the server.
- `studio.doc.dir:`A path to directory containing screenshots of the form views. It will be used to generate a doc from the excel sheet.
- `context.action = com.axelor.studio.utils.ActionHelper`. Put this as it is in the properties file.
* Environment variables to set.
- `JAVA_HOME:` A path to JDK used by the running app instance. It must be a JDK path and not the JRE path.
- `CATALINA_HOME:` It is a well known tomcat environment variable. A path to the tomcat server directory used by the current running instance.
- `PGDATA:` A path to the postgreql installation directory. For linux(ubuntu) its mostly a /usr/lib/postgresql/{postgres version}.

View File

@ -0,0 +1,55 @@
apply plugin: "com.axelor.app-module"
apply from: "../version.gradle"
apply {
version = openSuiteVersion
}
axelor {
title "Axelor Studio"
description "Axelor Studio Module"
}
dependencies {
compile project(":modules:axelor-admin")
compile project(":modules:axelor-message")
compile 'commons-lang:commons-lang:2.3'
// compile 'org.xhtmlrenderer:flying-saucer-pdf:9.1.4'
compile 'org.eclipse.birt.runtime.3_7_1:Tidy:1'
compile 'org.apache.commons:commons-exec:1.2'
// compile "org.bouncycastle:bcprov-jdk15on:1.62"
}
def updateJsp(jspFile, check, lines) {
def jsp = file("${rootProject.buildDir}/webapp/${jspFile}")
def text = lines.join("\n");
if (jsp.exists()) {
def jspText = jsp.getText('UTF-8')
if (jspText.indexOf(check) == -1) {
text = jspText + text
}
}
file(jsp).write(text, 'UTF-8')
}
//XXX: this task should be removed when we introduce per module webapp support in Axelor Open Platform
task copyWebapp(type: Copy) {
destinationDir = file(rootProject.buildDir)
into("webapp/studio") {
from "src/main/webapp"
}
doLast {
// update index-head.jsp
updateJsp("index-head.jsp", "diagram-js.css", [
'<link href="studio/lib/bpmn-js/assets/bpmn-font/css/bpmn-embedded.css" rel="stylesheet">',
'<link href="studio/lib/bpmn-js/assets/diagram-js.css" rel="stylesheet">',
'<link href="studio/css/bpmn.css" rel="stylesheet">'])
// update index-foot.jsp
updateJsp("index-foot.jsp", "bpmn-modeler.js", [
'<script src="studio/lib/bpmn-js/bpmn-modeler.js"></script>',
'<script src="studio/js/form/form.bpmn.js"></script>'])
}
}
rootProject.tasks.war.dependsOn copyWebapp

View File

@ -0,0 +1,51 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.meta.MetaStore;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.service.StudioMetaService;
import com.axelor.studio.service.builder.ActionBuilderService;
import com.google.inject.Inject;
public class ActionBuilderRepo extends ActionBuilderRepository {
@Inject private StudioMetaService metaService;
@Inject private ActionBuilderService builderService;
@Override
public ActionBuilder save(ActionBuilder builder) {
builder = super.save(builder);
builderService.build(builder);
return builder;
}
@Override
public void remove(ActionBuilder actionBuilder) {
metaService.removeMetaActions(actionBuilder.getName());
MetaStore.clear();
super.remove(actionBuilder);
}
}

View File

@ -0,0 +1,49 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.exception.AxelorException;
import com.axelor.studio.db.AppBuilder;
import com.axelor.studio.service.builder.AppBuilderService;
import com.google.inject.Inject;
import javax.validation.ValidationException;
public class AppBuilderRepo extends AppBuilderRepository {
@Inject private AppBuilderService appBuilderService;
@Override
public AppBuilder save(AppBuilder appBuilder) {
try {
appBuilderService.build(appBuilder);
} catch (AxelorException e) {
throw new ValidationException(e.getMessage());
}
return super.save(appBuilder);
}
@Override
public void remove(AppBuilder appBuilder) {
appBuilderService.clean(appBuilder);
super.remove(appBuilder);
}
}

View File

@ -0,0 +1,69 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.exception.AxelorException;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.db.repo.MetaViewRepository;
import com.axelor.studio.db.ChartBuilder;
import com.axelor.studio.service.builder.ChartBuilderService;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.util.List;
import javax.validation.ValidationException;
import javax.xml.bind.JAXBException;
public class ChartBuilderRepo extends ChartBuilderRepository {
@Inject private MetaViewRepository metaViewRepo;
@Inject private ChartBuilderService chartBuilderService;
@Override
public ChartBuilder save(ChartBuilder chartBuilder) throws ValidationException {
try {
chartBuilderService.build(chartBuilder);
} catch (AxelorException | JAXBException e) {
refresh(chartBuilder);
throw new ValidationException(e.getMessage());
}
return super.save(chartBuilder);
}
@Override
@Transactional
public void remove(ChartBuilder chartBuilder) {
MetaView metaView = chartBuilder.getMetaViewGenerated();
List<ChartBuilder> chartBuilders =
all()
.filter("self.metaViewGenerated = ?1 and self.id != ?2", metaView, chartBuilder.getId())
.fetch();
for (ChartBuilder builder : chartBuilders) {
builder.setMetaViewGenerated(null);
}
if (metaView != null) {
metaViewRepo.remove(metaView);
}
super.remove(chartBuilder);
}
}

View File

@ -0,0 +1,59 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.db.repo.MetaViewRepository;
import com.axelor.studio.db.DashboardBuilder;
import com.axelor.studio.service.builder.DashboardBuilderService;
import com.google.inject.Inject;
public class DashboardBuilderRepo extends DashboardBuilderRepository {
@Inject private DashboardBuilderService dashboardBuilderService;
@Inject private MetaViewRepository metaViewRepo;
@Override
public DashboardBuilder save(DashboardBuilder dashboardBuilder) {
dashboardBuilder = super.save(dashboardBuilder);
MetaView metaView = dashboardBuilderService.build(dashboardBuilder);
if (metaView != null) {
dashboardBuilder.setMetaViewGenerated(metaView);
} else {
metaView = dashboardBuilder.getMetaViewGenerated();
if (metaView != null) {
metaViewRepo.remove(metaView);
}
}
return dashboardBuilder;
}
@Override
public void remove(DashboardBuilder dashboardBuilder) {
MetaView metaView = dashboardBuilder.getMetaViewGenerated();
if (metaView != null) {
metaViewRepo.remove(metaView);
}
super.remove(dashboardBuilder);
}
}

View File

@ -0,0 +1,87 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.exception.service.TraceBackService;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaMenu;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.MenuBuilder;
import com.axelor.studio.service.StudioMetaService;
import com.axelor.studio.service.builder.MenuBuilderService;
import com.google.inject.Inject;
public class MenuBuilderRepo extends MenuBuilderRepository {
@Inject private MenuBuilderService menuBuilderService;
@Inject private ActionBuilderRepo actionBuilderRepo;
@Inject private StudioMetaService metaService;
@Override
public MenuBuilder save(MenuBuilder menuBuilder) {
if (menuBuilder.getName() == null) {
menuBuilder.setName("studio-menu-" + menuBuilder.getId());
}
if (menuBuilder.getActionBuilder() != null) {
menuBuilder.getActionBuilder().setMenuAction(true);
}
menuBuilder = super.save(menuBuilder);
menuBuilder.setMetaMenu(menuBuilderService.build(menuBuilder));
return menuBuilder;
}
@Override
public MenuBuilder copy(MenuBuilder menuBuilder, boolean deep) {
ActionBuilder actionBuilder = menuBuilder.getActionBuilder();
menuBuilder.setActionBuilder(null);
menuBuilder = super.copy(menuBuilder, deep);
if (actionBuilder != null) {
menuBuilder.setActionBuilder(actionBuilderRepo.copy(actionBuilder, deep));
}
return menuBuilder;
}
@Override
public void remove(MenuBuilder menuBuilder) {
MetaMenu metaMenu = menuBuilder.getMetaMenu();
menuBuilder.setMetaMenu(null);
metaService.removeMetaMenu(metaMenu);
ActionBuilder actionBuilder = menuBuilder.getActionBuilder();
menuBuilder.setActionBuilder(null);
if (actionBuilder != null) {
try {
actionBuilderRepo.remove(actionBuilder);
} catch (RuntimeException e) {
TraceBackService.trace(e);
throw e;
}
}
MetaStore.clear();
super.remove(menuBuilder);
}
}

View File

@ -0,0 +1,36 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.repo.MetaJsonFieldRepository;
import com.axelor.studio.db.AppBuilder;
public class MetaJsonFieldRepo extends MetaJsonFieldRepository {
@Override
public MetaJsonField save(MetaJsonField metajsonField) {
AppBuilder appBuilder = metajsonField.getAppBuilder();
if (appBuilder != null) {
metajsonField.setIncludeIf("__config__.app.isApp('" + appBuilder.getCode() + "')");
}
return super.save(metajsonField);
}
}

View File

@ -0,0 +1,42 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.meta.db.MetaJsonModel;
import com.axelor.meta.db.repo.MetaJsonModelRepository;
import com.axelor.studio.db.AppBuilder;
public class MetaJsonModelRepo extends MetaJsonModelRepository {
@Override
public MetaJsonModel save(MetaJsonModel jsonModel) {
jsonModel = super.save(jsonModel);
if (jsonModel.getMenu() != null) {
AppBuilder appBuilder = jsonModel.getAppBuilder();
if (appBuilder != null) {
jsonModel
.getMenu()
.setConditionToCheck("__config__.app.isApp('" + appBuilder.getCode() + "')");
} else {
jsonModel.getMenu().setConditionToCheck(null);
}
}
return jsonModel;
}
}

View File

@ -0,0 +1,39 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.db.repo;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.service.wkf.WkfService;
import com.google.inject.Inject;
public class StudioWkfRepository extends WkfRepository {
@Inject private WkfService wkfService;
/**
* Overridden to remove changes related with workflow. Like to remove buttons and status field
* from view and model.
*/
@Override
public void remove(Wkf wkf) {
wkfService.clearWkf(wkf);
super.remove(wkf);
}
}

View File

@ -0,0 +1,31 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.exception;
public interface IExceptionMessage {
/** Check if app builder code is not conflicting with existing app. */
static final String APP_BUILDER_1 = /*$$(*/
"Please provide unique code. The code '%s' is already used" /*)*/;
/** Check if chart name doesn't contains any space. */
static final String CHART_BUILDER_1 = /*$$(*/ "Name must not contains space" /*)*/;
/** Message to display on click of edit icon of node or transition if workflow is not saved. */
static final String WKF_1 = /*$$(*/ "Workflow is not saved" /*)*/;
}

View File

@ -0,0 +1,51 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.module;
import com.axelor.app.AxelorModule;
import com.axelor.meta.db.repo.MetaJsonFieldRepository;
import com.axelor.meta.db.repo.MetaJsonModelRepository;
import com.axelor.studio.db.repo.ActionBuilderRepo;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import com.axelor.studio.db.repo.AppBuilderRepo;
import com.axelor.studio.db.repo.AppBuilderRepository;
import com.axelor.studio.db.repo.ChartBuilderRepo;
import com.axelor.studio.db.repo.ChartBuilderRepository;
import com.axelor.studio.db.repo.DashboardBuilderRepo;
import com.axelor.studio.db.repo.DashboardBuilderRepository;
import com.axelor.studio.db.repo.MenuBuilderRepo;
import com.axelor.studio.db.repo.MenuBuilderRepository;
import com.axelor.studio.db.repo.MetaJsonFieldRepo;
import com.axelor.studio.db.repo.MetaJsonModelRepo;
import com.axelor.studio.db.repo.StudioWkfRepository;
import com.axelor.studio.db.repo.WkfRepository;
public class StudioModule extends AxelorModule {
@Override
protected void configure() {
bind(WkfRepository.class).to(StudioWkfRepository.class);
bind(ChartBuilderRepository.class).to(ChartBuilderRepo.class);
bind(ActionBuilderRepository.class).to(ActionBuilderRepo.class);
bind(MenuBuilderRepository.class).to(MenuBuilderRepo.class);
bind(DashboardBuilderRepository.class).to(DashboardBuilderRepo.class);
bind(AppBuilderRepository.class).to(AppBuilderRepo.class);
bind(MetaJsonFieldRepository.class).to(MetaJsonFieldRepo.class);
bind(MetaJsonModelRepository.class).to(MetaJsonModelRepo.class);
}
}

View File

@ -0,0 +1,157 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service;
import com.axelor.exception.service.TraceBackService;
import com.axelor.meta.MetaFiles;
import com.axelor.meta.db.MetaFile;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.ActionBuilderLine;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import com.google.common.base.Strings;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
public class ExportService {
private ExportService() {
throw new IllegalStateException("Should not be instantiated.");
}
public static String getImage(MetaFile metaFile) {
if (metaFile != null) {
File file = MetaFiles.getPath(metaFile).toFile();
if (file != null) {
try {
byte[] img = IOUtils.toByteArray(new FileInputStream(file));
return Base64.getEncoder().encodeToString(img);
} catch (IOException e) {
TraceBackService.trace(e);
}
}
}
return "";
}
public static String exportActionBuilderLines(List<ActionBuilderLine> lines, int count) {
String xml = "";
String indent = "\n" + Strings.repeat("\t", count);
for (ActionBuilderLine line : lines) {
String source = "";
String target = "";
if (line.getParent() == null) {
ActionBuilder builder = line.getActionBuilder();
if (builder != null) {
target = builder.getTargetModel();
source = builder.getModel();
if (builder.getTypeSelect() == ActionBuilderRepository.TYPE_SELECT_UPDATE) {
target = builder.getModel();
}
}
} else {
ActionBuilderLine parent = line.getParent();
if (parent.getMetaField() != null) target = parent.getMetaField().getTypeName();
if (parent.getMetaJsonField() != null && parent.getMetaJsonField().getTargetModel() != null)
target = parent.getMetaJsonField().getTargetModel();
if (parent.getMetaJsonField() != null
&& parent.getMetaJsonField().getTargetJsonModel() != null)
target = parent.getMetaJsonField().getTargetJsonModel().getName();
if (parent.getValueField() != null)
source = parent.getValueField().getMetaModel().getFullName();
if (parent.getValueJson() != null && parent.getValueJson().getTargetModel() != null)
source = parent.getValueJson().getTargetModel();
if (parent.getValueJson() != null && parent.getValueJson().getTargetJsonModel() != null)
source = parent.getValueJson().getTargetJsonModel().getName();
}
xml +=
indent
+ "<line>"
+ indent
+ "<target>"
+ target
+ "</target>"
+ indent
+ "<source>"
+ source
+ "</source>"
+ indent
+ "<metaJsonField>"
+ (line.getMetaJsonField() != null ? line.getMetaJsonField().getName() : "")
+ "</metaJsonField>"
+ indent
+ "<metaField>"
+ (line.getMetaField() != null ? line.getMetaField().getName() : "")
+ "</metaField>"
+ indent
+ "<valueJson>"
+ (line.getValueJson() != null ? line.getValueJson().getName() : "")
+ "</valueJson>"
+ indent
+ "<valueField>"
+ (line.getValueField() != null ? line.getValueField().getName() : "")
+ "</valueField>"
+ indent
+ "<value>"
+ (line.getValue() != null ? line.getValue() : "")
+ "</value>"
+ indent
+ "<conditionText>"
+ (line.getConditionText() != null ? line.getConditionText() : "")
+ "</conditionText>"
+ indent
+ "<filter>"
+ (line.getFilter() != null ? line.getFilter() : "")
+ "</filter>"
+ indent
+ "<validationTypeSelect>"
+ (line.getValidationTypeSelect() != null ? line.getValidationTypeSelect() : "")
+ "</validationTypeSelect>"
+ indent
+ "<validationMsg>"
+ (line.getValidationMsg() != null ? line.getValidationMsg() : "")
+ "</validationMsg>"
+ indent
+ "<name>"
+ (line.getName() != null ? line.getName() : "")
+ "</name>"
+ indent
+ "<dummy>"
+ (line.getDummy() != null ? line.getDummy() : "")
+ "</dummy>"
+ indent
+ "<subLines>"
+ exportActionBuilderLines(line.getSubLines(), count + 1)
+ "</subLines>"
+ "</line>";
}
return StringEscapeUtils.unescapeXml(xml);
}
}

View File

@ -0,0 +1,242 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service;
import com.axelor.db.JPA;
import com.axelor.exception.AxelorException;
import com.axelor.meta.MetaFiles;
import com.axelor.meta.db.MetaFile;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaJsonModel;
import com.axelor.meta.db.repo.MetaFileRepository;
import com.axelor.meta.db.repo.MetaJsonFieldRepository;
import com.axelor.meta.db.repo.MetaJsonModelRepository;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.AppBuilder;
import com.axelor.studio.db.ChartBuilder;
import com.axelor.studio.db.DashboardBuilder;
import com.axelor.studio.db.MenuBuilder;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import com.axelor.studio.db.repo.AppBuilderRepository;
import com.axelor.studio.db.repo.ChartBuilderRepository;
import com.axelor.studio.db.repo.DashboardBuilderRepository;
import com.axelor.studio.db.repo.MenuBuilderRepository;
import com.axelor.studio.service.wkf.WkfService;
import com.google.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Map;
import javax.xml.bind.JAXBException;
public class ImportService {
@Inject private ChartBuilderRepository chartBuilderRepo;
@Inject private MetaJsonModelRepository metaJsonModelRepo;
@Inject private MetaJsonFieldRepository metaJsonFieldRepo;
@Inject private DashboardBuilderRepository dashboardBuilderRepo;
@Inject private MenuBuilderRepository menuBuilderRepo;
@Inject private ActionBuilderRepository actionBuilderRepo;
@Inject private AppBuilderRepository appBuilderRepo;
@Inject private WkfService wkfService;
@Inject private MetaFiles metaFiles;
@Inject private MetaFileRepository metaFileRepo;
public Object importMetaJsonModel(Object bean, Map<String, Object> values) {
assert bean instanceof MetaJsonModel;
return metaJsonModelRepo.save((MetaJsonModel) bean);
}
public Object importMetaJsonField(Object bean, Map<String, Object> values) {
assert bean instanceof MetaJsonField;
return metaJsonFieldRepo.save((MetaJsonField) bean);
}
public Object importChartBuilder(Object bean, Map<String, Object> values)
throws JAXBException, AxelorException {
assert bean instanceof ChartBuilder;
return chartBuilderRepo.save((ChartBuilder) bean);
}
public Object importDashboardBuilder(Object bean, Map<String, Object> values) {
assert bean instanceof DashboardBuilder;
return dashboardBuilderRepo.save((DashboardBuilder) bean);
}
public Object importMenuBuilder(Object bean, Map<String, Object> values) {
assert bean instanceof MenuBuilder;
return menuBuilderRepo.save((MenuBuilder) bean);
}
public Object importActionBuilder(Object bean, Map<String, Object> values) {
assert bean instanceof ActionBuilder;
return actionBuilderRepo.save((ActionBuilder) bean);
}
public Object importWkf(Object bean, Map<String, Object> values) {
assert bean instanceof Wkf;
Wkf wkf = (Wkf) bean;
wkfService.process(wkf);
return wkf;
}
public Object importAppBuilderImg(Object bean, Map<String, Object> values) {
assert bean instanceof AppBuilder;
AppBuilder appBuilder = (AppBuilder) bean;
String fileName = (String) values.get("fileName");
String imageData = (String) values.get("imageData");
if (fileName != null && imageData != null) {
appBuilder.setImage(importImg(fileName, imageData));
}
appBuilder = appBuilderRepo.save(appBuilder);
return appBuilder;
}
public Object importAppBuilder(Object bean, Map<String, Object> values) {
assert bean instanceof AppBuilder;
AppBuilder appBuilder = (AppBuilder) bean;
return appBuilderRepo.save(appBuilder);
}
// Import methods specific for import from AppBuilder
private MetaFile importImg(String name, String data) {
if (data == null) {
return null;
}
byte[] img = Base64.getDecoder().decode(data);
ByteArrayInputStream inImg = new ByteArrayInputStream(img);
MetaFile metaFile = metaFileRepo.all().filter("self.fileName = ?1", name).fetchOne();
try {
if (metaFile != null) {
return metaFiles.upload(inImg, metaFile);
} else {
return metaFiles.upload(inImg, name);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public MetaJsonField importJsonModelField(Object bean, Map<String, Object> values) {
assert bean instanceof MetaJsonField;
MetaJsonField field = (MetaJsonField) bean;
if (field.getJsonModel() == null) {
return null;
}
return field;
}
public MetaJsonField importJsonField(Object bean, Map<String, Object> values) {
assert bean instanceof MetaJsonField;
MetaJsonField field = (MetaJsonField) bean;
if (field.getJsonModel() != null) {
return null;
}
return field;
}
public Object importAppMetaJsonModel(Object bean, Map<String, Object> values) {
assert bean instanceof MetaJsonModel;
MetaJsonModel model = (MetaJsonModel) bean;
JPA.flush();
JPA.refresh(model);
return metaJsonModelRepo.save(model);
}
public Object importAppDashboardBuilder(Object bean, Map<String, Object> values) {
assert bean instanceof DashboardBuilder;
DashboardBuilder dashboard = (DashboardBuilder) bean;
JPA.flush();
JPA.refresh(dashboard);
return dashboardBuilderRepo.save(dashboard);
}
public Object importAppWkf(Object bean, Map<String, Object> values) {
assert bean instanceof Wkf;
Wkf wkf = (Wkf) bean;
JPA.flush();
JPA.refresh(wkf);
wkfService.process(wkf);
return wkf;
}
}

View File

@ -0,0 +1,290 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service;
import com.axelor.auth.db.Group;
import com.axelor.auth.db.Role;
import com.axelor.db.JPA;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaMenu;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.db.repo.MetaActionRepository;
import com.axelor.meta.db.repo.MetaMenuRepository;
import com.axelor.meta.db.repo.MetaViewRepository;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.views.AbstractView;
import com.axelor.studio.db.MenuBuilder;
import com.axelor.studio.db.repo.MenuBuilderRepository;
import com.axelor.studio.service.wkf.WkfTrackingService;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.persistence.NoResultException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StudioMetaService {
public static final String XML_ID_PREFIX = "studio-build-";
private final Logger log = LoggerFactory.getLogger(StudioMetaService.class);
@Inject private MetaActionRepository metaActionRepo;
@Inject private MetaViewRepository metaViewRepo;
@Inject private MetaMenuRepository metaMenuRepo;
@Inject private MenuBuilderRepository menuBuilderRepo;
/**
* Removes MetaActions from comma separated names in string.
*
* @param actionNames Comma separated string of action names.
*/
@Transactional
public void removeMetaActions(String actionNames) {
log.debug("Removing actions: {}", actionNames);
if (actionNames == null) {
return;
}
actionNames = actionNames.replaceAll(WkfTrackingService.ACTION_OPEN_TRACK, "");
// .replaceAll(WkfTrackingService.ACTION_TRACK, "");
List<MetaAction> metaActions =
metaActionRepo
.all()
.filter("self.name in ?1", Arrays.asList(actionNames.split(",")))
.fetch();
for (MetaAction action : metaActions) {
if (action.getXmlId() == null
|| !action.getXmlId().contentEquals(XML_ID_PREFIX + action.getName())) {
continue;
}
List<MetaMenu> menus = metaMenuRepo.all().filter("self.action = ?1", action).fetch();
for (MetaMenu metaMenu : menus) {
metaMenu.setAction(null);
metaMenuRepo.save(metaMenu);
}
metaActionRepo.remove(action);
}
}
@Transactional
public MetaAction updateMetaAction(String name, String actionType, String xml, String model) {
String xmlId = XML_ID_PREFIX + name;
MetaAction action = metaActionRepo.findByID(xmlId);
if (action == null) {
action = new MetaAction(name);
action.setXmlId(xmlId);
Integer priority = getPriority(MetaAction.class.getSimpleName(), name);
action.setPriority(priority);
}
action.setType(actionType);
action.setModel(model);
action.setXml(xml);
return metaActionRepo.save(action);
}
/**
* Creates or Updates metaView from AbstractView.
*
* @param viewIterator ViewBuilder iterator
*/
@Transactional
public MetaView generateMetaView(AbstractView view) {
String name = view.getName();
String xmlId = view.getXmlId();
String model = view.getModel();
String viewType = view.getType();
log.debug("Search view name: {}, xmlId: {}", name, xmlId);
MetaView metaView;
if (xmlId != null) {
metaView =
metaViewRepo
.all()
.filter(
"self.name = ?1 and self.xmlId = ?2 and self.type = ?3", name, xmlId, viewType)
.fetchOne();
} else {
metaView =
metaViewRepo.all().filter("self.name = ?1 and self.type = ?2", name, viewType).fetchOne();
}
log.debug("Meta view found: {}", metaView);
if (metaView == null) {
metaView =
metaViewRepo
.all()
.filter("self.name = ?1 and self.type = ?2", name, viewType)
.order("-priority")
.fetchOne();
Integer priority = 20;
if (metaView != null) {
priority = metaView.getPriority() + 1;
}
metaView = new MetaView();
metaView.setName(name);
metaView.setXmlId(xmlId);
metaView.setModel(model);
metaView.setPriority(priority);
metaView.setType(viewType);
metaView.setTitle(view.getTitle());
}
String viewXml = XMLViews.toXml(view, true);
metaView.setXml(viewXml);
return metaViewRepo.save(metaView);
}
public String updateAction(String oldAction, String newAction, boolean remove) {
if (oldAction == null) {
return newAction;
}
if (newAction == null) {
return oldAction;
}
if (remove) {
oldAction = oldAction.replace(newAction, "");
} else if (!oldAction.contains(newAction)) {
oldAction = oldAction + "," + newAction;
}
oldAction = oldAction.replace(",,", ",");
if (oldAction.isEmpty()) {
return null;
}
return oldAction;
}
public MetaMenu createMenu(MenuBuilder builder) {
String xmlId = XML_ID_PREFIX + builder.getName();
MetaMenu menu = metaMenuRepo.findByID(xmlId);
if (menu == null) {
menu = new MetaMenu(builder.getName());
menu.setXmlId(xmlId);
Integer priority = getPriority(MetaMenu.class.getSimpleName(), menu.getName());
menu.setPriority(priority);
menu.setTitle(builder.getTitle());
menu = metaMenuRepo.save(menu);
}
menu.setTitle(builder.getTitle());
menu.setIcon(builder.getIcon());
menu.setIconBackground(builder.getIconBackground());
menu.setOrder(builder.getOrder());
menu.setParent(builder.getParentMenu());
if (builder.getGroups() != null) {
Set<Group> groups = new HashSet<>();
groups.addAll(builder.getGroups());
menu.setGroups(groups);
}
if (builder.getRoles() != null) {
Set<Role> roles = new HashSet<>();
roles.addAll(builder.getRoles());
menu.setRoles(roles);
}
String condition = builder.getConditionToCheck();
if (builder.getAppBuilder() != null) {
if (condition != null) {
condition =
"__config__.app.isApp('"
+ builder.getAppBuilder().getCode()
+ "') && ("
+ condition
+ ")";
} else {
condition = "__config__.app.isApp('" + builder.getAppBuilder().getCode() + "')";
}
}
menu.setConditionToCheck(condition);
menu.setModuleToCheck(builder.getModuleToCheck());
menu.setLeft(builder.getLeft());
menu.setTop(builder.getTop());
menu.setHidden(builder.getHidden());
menu.setMobile(builder.getMobile());
menu.setTag(builder.getTag());
menu.setTagCount(builder.getTagCount());
menu.setTagGet(builder.getTagGet());
menu.setTagStyle(builder.getTagStyle());
menu.setLink(builder.getLink());
if (builder.getMetaModule() != null) {
menu.setModule(builder.getMetaModule().getName());
}
return menu;
}
@Transactional
public void removeMetaMenu(MetaMenu metaMenu) {
Preconditions.checkNotNull(metaMenu, "metaMenu cannot be null.");
List<MetaMenu> subMenus = metaMenuRepo.all().filter("self.parent = ?1", metaMenu).fetch();
for (MetaMenu subMenu : subMenus) {
subMenu.setParent(null);
}
List<MenuBuilder> subBuilders =
menuBuilderRepo.all().filter("self.parentMenu = ?1", metaMenu).fetch();
for (MenuBuilder subBuilder : subBuilders) {
subBuilder.setParentMenu(null);
menuBuilderRepo.save(subBuilder);
}
metaMenuRepo.remove(metaMenu);
}
private Integer getPriority(String object, String name) {
String query =
String.format("SELECT MAX(obj.priority) FROM %s obj WHERE obj.name = :name", object);
try {
Optional<Integer> priorityOpt =
Optional.ofNullable(
JPA.em()
.createQuery(query, Integer.class)
.setParameter("name", name)
.getSingleResult());
return priorityOpt.orElse(0) + 1;
} catch (NoResultException e) {
return 0;
}
}
}

View File

@ -0,0 +1,112 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaAction;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.ActionBuilderView;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ActionBuilderService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Inject private ActionViewBuilderService actionViewBuilderService;
@Inject private ActionScriptBuilderService actionScriptBuilderService;
@Inject private ActionEmailBuilderService actionEmailBuilderService;
@Transactional
public MetaAction build(ActionBuilder builder) {
if (builder == null) {
return null;
}
log.debug("Processing action: {}, type: {}", builder.getName(), builder.getTypeSelect());
if (Arrays.asList(
ActionBuilderRepository.TYPE_SELECT_CREATE,
ActionBuilderRepository.TYPE_SELECT_UPDATE)
.contains(builder.getTypeSelect())
&& (builder.getLines() == null || builder.getLines().isEmpty())) {
return null;
}
MetaAction metaAction = null;
switch (builder.getTypeSelect()) {
case ActionBuilderRepository.TYPE_SELECT_CREATE:
metaAction = actionScriptBuilderService.build(builder);
break;
case ActionBuilderRepository.TYPE_SELECT_UPDATE:
metaAction = actionScriptBuilderService.build(builder);
break;
case ActionBuilderRepository.TYPE_SELECT_SCRIPT:
metaAction = actionScriptBuilderService.build(builder);
break;
case ActionBuilderRepository.TYPE_SELECT_VIEW:
metaAction = actionViewBuilderService.build(builder);
break;
case ActionBuilderRepository.TYPE_SELECT_EMAIL:
metaAction = actionEmailBuilderService.build(builder);
}
if (builder.getMetaModule() != null) {
metaAction.setModule(builder.getMetaModule().getName());
}
MetaStore.clear();
return metaAction;
}
public ActionBuilder setActionBuilderViews(
ActionBuilder actionBuilder, String modelName, String formViewName, String gridViewName) {
if (actionBuilder.getActionBuilderViews() == null) {
actionBuilder.setActionBuilderViews(new ArrayList<>());
}
List<ActionBuilderView> actionBuilderViews = actionBuilder.getActionBuilderViews();
if (formViewName != null) {
setActionBuilderView("form", formViewName, actionBuilderViews);
}
if (gridViewName != null) {
setActionBuilderView("grid", gridViewName, actionBuilderViews);
}
actionBuilder.setModel(modelName);
return actionBuilder;
}
private void setActionBuilderView(
String viewType, String viewName, List<ActionBuilderView> actionBuilderViews) {
ActionBuilderView actionBuilderView = new ActionBuilderView();
actionBuilderView.setViewType(viewType);
actionBuilderView.setViewName(viewName);
actionBuilderViews.add(actionBuilderView);
}
}

View File

@ -0,0 +1,114 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.apps.message.db.Message;
import com.axelor.apps.message.db.Template;
import com.axelor.apps.message.db.repo.TemplateRepository;
import com.axelor.apps.message.exception.IExceptionMessage;
import com.axelor.apps.message.service.MessageService;
import com.axelor.apps.message.service.TemplateMessageService;
import com.axelor.exception.AxelorException;
import com.axelor.i18n.I18n;
import com.axelor.meta.CallMethod;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaJsonModel;
import com.axelor.meta.db.MetaModel;
import com.axelor.meta.db.repo.MetaJsonModelRepository;
import com.axelor.meta.db.repo.MetaModelRepository;
import com.axelor.meta.schema.actions.ActionView;
import com.axelor.rpc.ActionResponse;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.service.StudioMetaService;
import com.google.inject.Inject;
import java.io.IOException;
import javax.mail.MessagingException;
public class ActionEmailBuilderService {
@Inject private MetaModelRepository metaModelRepo;
@Inject private MetaJsonModelRepository metaJsonModelRepo;
@Inject private StudioMetaService studioMetaService;
@Inject private TemplateRepository templateRepo;
@Inject private TemplateMessageService templateMessageService;
@Inject private MessageService messageService;
public MetaAction build(ActionBuilder builder) {
String name = builder.getName();
Object model =
builder.getIsJson()
? metaJsonModelRepo.all().filter("self.name = ?", builder.getModel()).fetchOne()
: metaModelRepo.all().filter("self.fullName = ?", builder.getModel()).fetchOne();
int sendOption = builder.getEmailSendOptionSelect();
Template template = builder.getEmailTemplate();
String xml =
"<action-method name=\""
+ name
+ "\" id=\"studio-"
+ name
+ "\">\n\t"
+ "<call class=\"com.axelor.studio.service.builder.ActionEmailBuilderService\" method=\"sendEmail(id, '"
+ (builder.getIsJson()
? ((MetaJsonModel) model).getName()
: ((MetaModel) model).getFullName())
+ "', '"
+ (builder.getIsJson()
? ((MetaJsonModel) model).getName()
: ((MetaModel) model).getName())
+ "', '"
+ template.getId()
+ "', '"
+ sendOption
+ "')\" "
+ "if=\"id != null\"/>\n"
+ "</action-method>";
return studioMetaService.updateMetaAction(name, "action-method", xml, null);
}
@CallMethod
public ActionResponse sendEmail(
Long objectId, String model, String tag, Long templateId, int sendOption)
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
AxelorException, IOException, MessagingException {
Template template = templateRepo.find(templateId);
Message message = templateMessageService.generateMessage(objectId, model, tag, template);
ActionResponse response = new ActionResponse();
if (sendOption == 0) {
messageService.sendByEmail(message);
} else {
response.setView(
ActionView.define(I18n.get(IExceptionMessage.MESSAGE_3))
.model(Message.class.getName())
.add("form", "message-form")
.param("forceEdit", "true")
.context("_showRecord", message.getId().toString())
.map());
}
return response;
}
}

View File

@ -0,0 +1,644 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.common.Inflector;
import com.axelor.exception.AxelorException;
import com.axelor.exception.service.TraceBackService;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.ActionBuilderLine;
import com.axelor.studio.db.repo.ActionBuilderLineRepository;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import com.axelor.studio.service.StudioMetaService;
import com.axelor.studio.service.filter.FilterSqlService;
import com.axelor.studio.service.wkf.WkfTrackingService;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ActionScriptBuilderService {
private static final String INDENT = "\t";
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final Inflector inflector = Inflector.getInstance();
private List<StringBuilder> fbuilder = null;
private int varCount = 0;
private boolean isCreate = false;
@Inject private ActionBuilderLineRepository builderLineRepo;
@Inject private StudioMetaService metaService;
@Inject private FilterSqlService filterSqlService;
public MetaAction build(ActionBuilder builder) {
String name = builder.getName();
String code = null;
String lang = "js";
String transactional = "true";
if (builder.getTypeSelect() == ActionBuilderRepository.TYPE_SELECT_SCRIPT) {
code = "\n" + builder.getScriptText();
if (builder.getScriptType() == 1) {
lang = "groovy";
}
if (builder.getTransactional()) {
transactional = "false";
}
} else {
code = generateScriptCode(builder);
}
String xml =
"<action-script name=\""
+ name
+ "\" "
+ "id=\"studio-"
+ name
+ "\" model=\""
+ MetaJsonRecord.class.getName()
+ "\">\n\t"
+ "<script language=\""
+ lang
+ "\" transactional=\""
+ transactional
+ "\">\n\t<![CDATA["
+ code
+ "\n\t]]>\n\t</script>\n</action-script>";
return metaService.updateMetaAction(builder.getName(), "action-script", xml, null);
}
private String generateScriptCode(ActionBuilder builder) {
StringBuilder stb = new StringBuilder();
fbuilder = new ArrayList<>();
varCount = 1;
int level = 1;
stb.append(format("var ctx = $request.context;", level));
String targetModel;
if (builder.getTypeSelect() == ActionBuilderRepository.TYPE_SELECT_CREATE) {
targetModel = builder.getTargetModel();
isCreate = true;
addCreateCode(builder.getIsJson(), stb, level, targetModel);
if (builder.getOpenRecord()) {
addOpenRecord(builder.getIsJson(), stb, level, targetModel);
}
if (!Strings.isNullOrEmpty(builder.getDisplayMsg())) {
stb.append("\n");
stb.append(format("$response.setFlash('" + builder.getDisplayMsg() + "')", level));
}
} else {
targetModel = builder.getModel();
isCreate = false;
addUpdateCode(builder.getIsJson(), stb, level, targetModel);
}
stb.append("\n");
addRootFunction(builder, stb, level);
stb.append(Joiner.on("").join(fbuilder));
return stb.toString();
}
private void addCreateCode(boolean isJson, StringBuilder stb, int level, String targetModel) {
if (isJson) {
stb.append(format("var target = $json.create('" + targetModel + "');", level));
stb.append(format("target = setVar0(null, ctx, {});", level));
stb.append(format("target = $json.save(target);", level));
stb.append(
format(
"Beans.get(" + WkfTrackingService.class.getName() + ".class).track(target);", level));
} else {
stb.append(format("var target = new " + targetModel + "();", level));
stb.append(format("target = setVar0(null, ctx, {});", level));
stb.append(format("$em.persist(target);", level));
}
}
private void addOpenRecord(boolean isJson, StringBuilder stb, int level, String targetModel) {
stb.append("\n");
if (isJson) {
String title = inflector.humanize(targetModel);
stb.append(
format(
"$response.setView(com.axelor.meta.schema.actions.ActionView.define('" + title + "')",
level));
stb.append(format(".model('com.axelor.meta.db.MetaJsonRecord')", level + 1));
stb.append(format(".add('grid','custom-model-" + targetModel + "-grid')", level + 1));
stb.append(format(".add('form','custom-model-" + targetModel + "-form')", level + 1));
stb.append(format(".domain('self.jsonModel = :jsonModel')", level + 1));
stb.append(format(".context('jsonModel', '" + targetModel + "')", level + 1));
stb.append(format(".context('_showRecord', target.id)", level + 1));
stb.append(format(".map())", level + 1));
} else {
String title = inflector.humanize(targetModel.substring(targetModel.lastIndexOf('.') + 1));
stb.append(
format(
"$response.setView(com.axelor.meta.schema.actions.ActionView.define('" + title + "')",
level));
stb.append(format(".model('" + targetModel + "')", level + 1));
stb.append(format(".add('grid')", level + 1));
stb.append(format(".add('form')", level + 1));
stb.append(format(".context('_showRecord', target.id)", level + 1));
stb.append(format(".map())", level + 1));
}
}
private void addUpdateCode(boolean isJson, StringBuilder stb, int level, String targetModel) {
if (isJson) {
stb.append(format("var target = {};", level));
} else {
stb.append(format("var target = ctx.asType(" + targetModel + ".class)", level));
}
stb.append(format("target = setVar0(null, ctx, {});", level));
stb.append(format("$response.setValues(target);", level));
}
private void addRootFunction(ActionBuilder builder, StringBuilder stb, int level) {
stb.append(format("function setVar0($$, $, _$){", level));
String bindings = addFieldsBinding("target", builder.getLines(), level + 1);
stb.append(bindings);
stb.append(format("return target;", level + 1));
stb.append(format("}", level));
}
private String format(String line, int level) {
return "\n" + Strings.repeat(INDENT, level) + line;
}
private String addFieldsBinding(String target, List<ActionBuilderLine> lines, int level) {
StringBuilder stb = new StringBuilder();
lines.sort(
(l1, l2) -> {
if (l1.getDummy() && !l2.getDummy()) {
return -1;
}
if (!l1.getDummy() && l2.getDummy()) {
return 1;
}
return 0;
});
for (ActionBuilderLine line : lines) {
String name = line.getName();
String value = line.getValue();
if (value != null && value.contains(".sum(")) {
value = getSum(value, line.getFilter());
}
if (line.getDummy()) {
stb.append(format("_$." + name + " = " + value + ";", level));
continue;
}
MetaJsonField jsonField = line.getMetaJsonField();
MetaField metaField = line.getMetaField();
if (jsonField != null
&& (jsonField.getTargetJsonModel() != null || jsonField.getTargetModel() != null)) {
value = addRelationalBinding(line, target, true);
} else if (metaField != null && metaField.getRelationship() != null) {
value = addRelationalBinding(line, target, false);
}
// else {
// MetaJsonField valueJson = line.getValueJson();
// if (valueJson != null && valueJson.getType().contentEquals("many-to-one")) {
// value = value.replace("$." + valueJson.getName(),"$json.create($json.find($."
// +
// valueJson.getName() + ".id))");
// }
// }
if (value != null
&& metaField != null
&& metaField.getTypeName().equals(BigDecimal.class.getSimpleName())) {
value = "new BigDecimal(" + value + ")";
}
String condition = line.getConditionText();
if (condition != null) {
stb.append(
format("if(" + condition + "){" + target + "." + name + " = " + value + ";}", level));
} else {
stb.append(format(target + "." + name + " = " + value + ";", level));
}
}
return stb.toString();
}
private String addRelationalBinding(ActionBuilderLine line, String target, boolean json) {
line = builderLineRepo.find(line.getId());
String subCode = null;
String type =
json
? line.getMetaJsonField().getType()
: inflector.dasherize(line.getMetaField().getRelationship());
switch (type) {
case "many-to-one":
subCode = addM2OBinding(line, true, true);
break;
case "many-to-many":
subCode = addM2MBinding(line);
break;
case "one-to-many":
subCode = addO2MBinding(line, target);
break;
case "one-to-one":
subCode = addM2OBinding(line, true, true);
break;
case "json-many-to-one":
subCode = addJsonM2OBinding(line, true, true);
break;
case "json-many-to-many":
subCode = addJsonM2MBinding(line);
break;
case "json-one-to-many":
subCode = addJsonO2MBinding(line);
break;
default:
throw new IllegalArgumentException("Unknown type");
}
return subCode + "($," + line.getValue() + ", _$)";
}
private String getTargetModel(ActionBuilderLine line) {
MetaJsonField jsonField = line.getMetaJsonField();
String targetModel = "";
if (jsonField != null && jsonField.getTargetModel() != null) {
targetModel = jsonField.getTargetModel();
}
MetaField field = line.getMetaField();
if (field != null && field.getTypeName() != null) {
targetModel = field.getTypeName();
}
return targetModel;
}
private String getTargetJsonModel(ActionBuilderLine line) {
MetaJsonField jsonField = line.getMetaJsonField();
if (jsonField != null) {
return jsonField.getTargetJsonModel().getName();
}
return "";
}
private String getRootSourceModel(ActionBuilderLine line) {
if (line.getActionBuilder() != null) {
return line.getActionBuilder().getModel();
}
return null;
}
private String getSourceModel(ActionBuilderLine line) {
MetaJsonField jsonField = line.getValueJson();
String sourceModel = null;
Object targetObject = null;
try {
if (jsonField != null && jsonField.getTargetModel() != null) {
if (line.getValue() != null && !line.getValue().contentEquals("$." + jsonField.getName())) {
targetObject =
filterSqlService.parseJsonField(
jsonField, line.getValue().replace("$.", ""), null, null);
} else {
sourceModel = jsonField.getTargetModel();
}
}
MetaField field = line.getValueField();
if (field != null && field.getTypeName() != null) {
if (line.getValue() != null && !line.getValue().contentEquals("$." + field.getName())) {
targetObject =
filterSqlService.parseMetaField(
field, line.getValue().replace("$.", ""), null, null, false);
} else {
sourceModel = field.getTypeName();
}
}
} catch (AxelorException e) {
TraceBackService.trace(e);
}
if (sourceModel == null && line.getValue() != null && line.getValue().equals("$")) {
sourceModel = getRootSourceModel(line);
}
if (sourceModel == null && line.getValue() != null && line.getValue().equals("$$")) {
sourceModel = getRootSourceModel(line);
}
if (targetObject != null) {
if (targetObject instanceof MetaJsonField) {
sourceModel = ((MetaJsonField) targetObject).getTargetModel();
} else if (targetObject instanceof MetaField) {
sourceModel = ((MetaField) targetObject).getTypeName();
}
}
return sourceModel;
}
private String addM2OBinding(ActionBuilderLine line, boolean search, boolean filter) {
String fname = "setVar" + varCount;
varCount += 1;
String tModel = getTargetModel(line);
String srcModel = getSourceModel(line);
StringBuilder stb = new StringBuilder();
fbuilder.add(stb);
if (tModel.contains(".")) {
tModel = tModel.substring(tModel.lastIndexOf('.') + 1);
}
stb.append(format("", 1));
stb.append(format("function " + fname + "($$, $, _$){", 1));
stb.append(format("var val = null;", 2));
if (srcModel != null) {
stb.append(format("if ($ != null && $.id != null){", 2));
srcModel = srcModel.substring(srcModel.lastIndexOf('.') + 1);
stb.append(format("$ = $em.find(" + srcModel + ".class, $.id);", 3));
log.debug("src model: {}, Target model: {}", srcModel, tModel);
if (srcModel.contentEquals(tModel)) {
stb.append(format("val = $", 3));
}
stb.append(format("}", 2));
}
if (filter && line.getFilter() != null) {
if (line.getValue() != null) {
stb.append(format("var map = com.axelor.db.mapper.Mapper.toMap($);", 2));
} else {
stb.append(format("var map = com.axelor.db.mapper.Mapper.toMap($$);", 2));
}
stb.append(format("val = " + getQuery(tModel, line.getFilter(), false, false), 2));
}
List<ActionBuilderLine> lines = line.getSubLines();
if (lines != null && !lines.isEmpty()) {
stb.append(format("if (!val) {", 2));
stb.append(format("val = new " + tModel + "();", 3));
stb.append(format("}", 2));
stb.append(addFieldsBinding("val", lines, 2));
// stb.append(format("$em.persist(val);", 2));
}
stb.append(format("return val;", 2));
stb.append(format("}", 1));
return fname;
}
private String addM2MBinding(ActionBuilderLine line) {
String fname = "setVar" + varCount;
varCount += 1;
StringBuilder stb = new StringBuilder();
fbuilder.add(stb);
stb.append(format("", 1));
stb.append(format("function " + fname + "($$, $, _$){", 1));
stb.append(format("var val = new HashSet();", 2));
if (line.getFilter() != null) {
String model = getTargetModel(line);
stb.append(format("var map = com.axelor.db.mapper.Mapper.toMap($$);", 2));
stb.append(format("val.addAll(" + getQuery(model, line.getFilter(), false, true) + ");", 2));
stb.append(format("if(!val.empty){return val;}", 2));
}
stb.append(format("if(!$){return val;}", 2));
stb.append(format("$.forEach(function(v){", 2));
stb.append(format("v = " + addM2OBinding(line, true, false) + "($$, v, _$);", 3));
stb.append(format("val.add(v);", 3));
stb.append(format("})", 2));
stb.append(format("return val;", 2));
stb.append(format("}", 1));
return fname;
}
private String addO2MBinding(ActionBuilderLine line, String target) {
String fname = "setVar" + varCount;
varCount += 1;
StringBuilder stb = new StringBuilder();
fbuilder.add(stb);
stb.append(format("", 1));
stb.append(format("function " + fname + "($$, $, _$){", 1));
stb.append(format("var val = new ArrayList();", 2));
stb.append(format("if(!$){return val;}", 2));
stb.append(format("$.forEach(function(v){", 2));
stb.append(format("var item = " + addM2OBinding(line, false, false) + "($$, v, _$);", 3));
if (isCreate && line.getMetaField() != null && line.getMetaField().getMappedBy() != null) {
stb.append(format("item." + line.getMetaField().getMappedBy() + " = " + target, 3));
}
stb.append(format("val.add(item);", 3));
stb.append(format("})", 2));
stb.append(format("return val;", 2));
stb.append(format("}", 1));
return fname;
}
private String addJsonM2OBinding(ActionBuilderLine line, boolean search, boolean filter) {
String fname = "setVar" + varCount;
varCount += 1;
StringBuilder stb = new StringBuilder();
fbuilder.add(stb);
String model = getTargetJsonModel(line);
stb.append(format("", 1));
stb.append(format("function " + fname + "($$, $, _$){", 1));
stb.append(format("var val = null;", 2));
// stb.append(format("if ($ != null && $.id != null){", 2));
// stb.append(format("$ = $json.find($.id);", 3));
if (search) {
stb.append(format("if ($ != null && $.id != null) {", 2));
stb.append(format("val = $json.find($.id);", 3));
stb.append(format("if (val.jsonModel != '" + model + "'){val = null;} ", 3));
stb.append(format("}", 2));
}
// stb.append(format("}",2));
if (filter && line.getFilter() != null) {
String query = getQuery(model, line.getFilter(), true, false);
stb.append(format("val = " + query, 2));
}
List<ActionBuilderLine> lines = line.getSubLines();
if (lines != null && !lines.isEmpty()) {
stb.append(format("if (!val) {", 2));
stb.append(format("val = $json.create('" + model + "');", 3));
stb.append(format("}", 2));
// stb.append(format("if($ instanceof MetaJsonRecord){$ =
// $json.create($json.find($.id))};",
// 2));
stb.append(addFieldsBinding("val", lines, 2));
stb.append(format("val = $json.save(val);", 2));
}
stb.append(format("return val;", 2));
stb.append(format("}", 1));
return fname;
}
private String addJsonM2MBinding(ActionBuilderLine line) {
String fname = "setVar" + varCount;
varCount += 1;
StringBuilder stb = new StringBuilder();
fbuilder.add(stb);
stb.append(format("", 1));
stb.append(format("function " + fname + "($$, $, _$){", 1));
stb.append(format("var val = new HashSet();", 2));
if (line.getFilter() != null) {
String model = getTargetJsonModel(line);
stb.append(format("val.addAll(" + getQuery(model, line.getFilter(), true, true) + ");", 2));
stb.append(format("if(!val.empty){return val;}", 2));
}
stb.append(format("if(!$){return val;}", 2));
stb.append(format("$.forEach(function(v){", 2));
stb.append(format("v = " + addJsonM2OBinding(line, true, false) + "($$, v, _$);", 3));
stb.append(format("val.add(v);", 3));
stb.append(format("})", 2));
stb.append(format("return val;", 2));
stb.append(format("}", 1));
return fname;
}
private String addJsonO2MBinding(ActionBuilderLine line) {
String fname = "setVar" + varCount;
varCount += 1;
StringBuilder stb = new StringBuilder();
fbuilder.add(stb);
stb.append(format("", 1));
stb.append(format("function " + fname + "($$, $, _$){", 1));
stb.append(format("var val = new ArrayList();", 2));
stb.append(format("if(!$){return val;}", 2));
stb.append(format("$.forEach(function(v){", 2));
stb.append(format("v = " + addJsonM2OBinding(line, false, false) + "($$, v, _$);", 3));
stb.append(format("val.add(v);", 3));
stb.append(format("})", 2));
stb.append(format("return val;", 2));
stb.append(format("}", 1));
return fname;
}
private String getQuery(String model, String filter, boolean json, boolean all) {
if (model.contains(".")) {
model = model.substring(model.lastIndexOf('.') + 1);
}
String nRecords = "fetchOne()";
if (all) {
nRecords = "fetch()";
}
String query = null;
if (json) {
query = "$json.all('" + model + "').by(" + filter + ")." + nRecords;
} else {
query =
"__repo__("
+ model
+ ".class).all().filter(\""
+ filter
+ "\").bind(map).bind(_$)."
+ nRecords;
}
return query;
}
private String getSum(String value, String filter) {
value = value.substring(0, value.length() - 1);
String[] expr = value.split("\\.sum\\(");
String fname = "setVar" + varCount;
varCount += 1;
StringBuilder stb = new StringBuilder();
stb.append(format("", 1));
stb.append(format("function " + fname + "(sumOf$, $$, filter){", 1));
stb.append(format("var val = 0", 2));
stb.append(format("if (sumOf$ == null){ return val;}", 2));
stb.append(format("sumOf$.forEach(function($){", 2));
// stb.append(format("if ($ instanceof MetaJsonRecord){ $ =
// $json.create($json.find($.id)); }",
// 3));
String val = "val += " + expr[1] + ";";
if (filter != null) {
val = "if(filter){" + val + "}";
}
stb.append(format(val, 3));
stb.append(format("})", 2));
stb.append(format("return new BigDecimal(val);", 2));
stb.append(format("}", 1));
fbuilder.add(stb);
return fname + "(" + expr[0] + ",$," + filter + ")";
}
}

View File

@ -0,0 +1,139 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.common.StringUtils;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.ActionBuilderLine;
import com.axelor.studio.db.ActionBuilderView;
import com.axelor.studio.service.StudioMetaService;
import com.google.inject.Inject;
import java.util.List;
import org.apache.commons.lang.StringEscapeUtils;
public class ActionViewBuilderService {
private static final String INDENT = "\t";
@Inject private StudioMetaService metaService;
public MetaAction build(ActionBuilder builder) {
if (builder == null) {
return null;
}
List<ActionBuilderView> views = builder.getActionBuilderViews();
if (views == null || views.isEmpty()) {
return null;
}
StringBuilder xml = new StringBuilder();
String model = appendBasic(builder, xml);
appendViews(views, xml);
appendParams(builder.getViewParams(), xml);
appendDomain(builder.getDomainCondition(), builder.getIsJson(), xml);
appendContext(builder, xml);
xml.append("\n" + "</action-view>");
return metaService.updateMetaAction(builder.getName(), "action-view", xml.toString(), model);
}
private void appendParams(List<ActionBuilderLine> params, StringBuilder xml) {
if (params == null) {
return;
}
for (ActionBuilderLine param : params) {
xml.append("\n" + INDENT + "<view-param name=\"" + param.getName() + "\" ");
xml.append("value=\"" + StringEscapeUtils.escapeXml(param.getValue()) + "\" />");
}
}
private void appendContext(ActionBuilder builder, StringBuilder xml) {
boolean addJsonCtx = true;
if (builder.getLines() != null) {
for (ActionBuilderLine context : builder.getLines()) {
if (context.getName().contentEquals("jsonModel")) {
addJsonCtx = false;
}
xml.append("\n" + INDENT + "<context name=\"" + context.getName() + "\" ");
xml.append("expr=\"eval:" + StringEscapeUtils.escapeXml(context.getValue()) + "\" />");
}
}
if (addJsonCtx && builder.getIsJson() && builder.getModel() != null) {
xml.append("\n" + INDENT + "<context name=\"jsonModel\" ");
xml.append("expr=\"" + builder.getModel() + "\" />");
}
}
private void appendDomain(String domain, Boolean isJson, StringBuilder xml) {
if (isJson) {
String jsonDomain = "self.jsonModel = :jsonModel";
if (domain == null) {
domain = jsonDomain;
} else if (!domain.contains(jsonDomain)) {
domain = jsonDomain + " AND (" + domain + ")";
}
}
if (domain != null) {
xml.append("\n" + INDENT + "<domain>" + StringEscapeUtils.escapeXml(domain) + "</domain>");
}
}
private void appendViews(List<ActionBuilderView> views, StringBuilder xml) {
views.sort((action1, action2) -> action1.getSequence().compareTo(action2.getSequence()));
for (ActionBuilderView view : views) {
xml.append("\n" + INDENT + "<view type=\"" + view.getViewType() + "\" ");
xml.append("name=\"" + view.getViewName() + "\" ");
if (StringUtils.notEmpty(view.getViewConditionToCheck())) {
xml.append("if=\"" + view.getViewConditionToCheck() + "\" />");
} else {
xml.append("/>");
}
}
}
private String appendBasic(ActionBuilder builder, StringBuilder xml) {
xml.append("<action-view name=\"" + builder.getName() + "\" ");
xml.append("title=\"" + builder.getTitle() + "\" ");
xml.append("id=\"studio-" + builder.getName() + "\" ");
String model = MetaJsonRecord.class.getName();
if (!builder.getIsJson()) {
model = builder.getModel();
}
xml.append("model=\"" + model + "\">");
return model;
}
}

View File

@ -0,0 +1,85 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.apps.base.db.App;
import com.axelor.apps.base.db.repo.AppRepository;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.repo.TraceBackRepository;
import com.axelor.i18n.I18n;
import com.axelor.studio.db.AppBuilder;
import com.axelor.studio.exception.IExceptionMessage;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.util.HashSet;
import java.util.Set;
public class AppBuilderService {
@Inject private AppRepository appRepo;
public AppBuilder build(AppBuilder appBuilder) throws AxelorException {
checkCode(appBuilder);
App app = appBuilder.getGeneratedApp();
if (app == null) {
app = new App(appBuilder.getName(), appBuilder.getCode());
} else {
app.setCode(appBuilder.getCode());
app.setName(appBuilder.getName());
}
app.setImage(appBuilder.getImage());
app.setDescription(appBuilder.getDescription());
Set<App> depends = new HashSet<App>();
if (appBuilder.getDependsOnSet() != null) {
depends.addAll(appBuilder.getDependsOnSet());
app.setDependsOnSet(depends);
}
app.setSequence(appBuilder.getSequence());
app.setInitDataLoaded(true);
app.setDemoDataLoaded(true);
appBuilder.setGeneratedApp(appRepo.save(app));
return appBuilder;
}
private void checkCode(AppBuilder appBuilder) throws AxelorException {
App app = appRepo.findByCode(appBuilder.getCode());
if (app != null && app != appBuilder.getGeneratedApp()) {
throw new AxelorException(
TraceBackRepository.CATEGORY_INCONSISTENCY,
I18n.get(IExceptionMessage.APP_BUILDER_1),
appBuilder.getCode());
}
}
@Transactional
public void clean(AppBuilder appBuilder) {
if (appBuilder.getGeneratedApp() != null) {
appRepo.remove(appBuilder.getGeneratedApp());
appBuilder.setGeneratedApp(null);
}
}
}

View File

@ -0,0 +1,553 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.common.Inflector;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.repo.TraceBackRepository;
import com.axelor.i18n.I18n;
import com.axelor.meta.CallMethod;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.meta.db.MetaModel;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.db.repo.MetaModelRepository;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.ObjectViews;
import com.axelor.studio.db.ChartBuilder;
import com.axelor.studio.db.Filter;
import com.axelor.studio.exception.IExceptionMessage;
import com.axelor.studio.service.StudioMetaService;
import com.axelor.studio.service.filter.FilterCommonService;
import com.axelor.studio.service.filter.FilterSqlService;
import com.google.common.base.Joiner;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.JAXBException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class generate charts using ViewBuilder and chart related fields. Chart xml generated by
* adding query, search fields , onInit actions..etc. All filters with parameter checked will be
* used as search fields. Tags also there to use context variable in filter value, like $User for
* current user (__user__).
*/
public class ChartBuilderService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String Tab1 = "\n \t";
private static final String Tab2 = "\n \t\t";
private static final String Tab3 = "\n \t\t\t";
private static final List<String> dateTypes =
Arrays.asList(
new String[] {"DATE", "DATETIME", "LOCALDATE", "LOCALDATETIME", "ZONNEDDATETIME"});
private List<String> searchFields;
// private List<RecordField> onNewFields;
private List<String> joins;
private String categType;
@Inject private MetaModelRepository metaModelRepo;
@Inject private FilterSqlService filterSqlService;
@Inject private FilterCommonService filterCommonService;
@Inject private StudioMetaService metaService;
/**
* Root Method to access the service it generate AbstractView from ViewBuilder.
*
* @param viewBuilder ViewBuilder object of type chart.
* @return AbstractView from meta schema.
* @throws JAXBException
* @throws AxelorException
*/
public void build(ChartBuilder chartBuilder) throws JAXBException, AxelorException {
if (chartBuilder.getName().contains(" ")) {
throw new AxelorException(
TraceBackRepository.CATEGORY_MISSING_FIELD, I18n.get(IExceptionMessage.CHART_BUILDER_1));
}
searchFields = new ArrayList<String>();
// onNewFields = new ArrayList<RecordField>();
joins = new ArrayList<String>();
categType = "text";
String[] queryString = prepareQuery(chartBuilder);
// setOnNewAction(chartBuilder);
String xml = createXml(chartBuilder, queryString);
log.debug("Chart xml: {}", xml);
ObjectViews chartView = XMLViews.fromXML(xml);
MetaView metaView = metaService.generateMetaView(chartView.getViews().get(0));
if (metaView != null) {
chartBuilder.setMetaViewGenerated(metaView);
}
}
private String createXml(ChartBuilder chartBuilder, String[] queryString) {
String xml =
"<chart name=\"" + chartBuilder.getName() + "\" title=\"" + chartBuilder.getTitle() + "\" ";
// if (onNewAction != null) {
// xml += " onInit=\"" + onNewAction.getName() + "\" ";
// }
xml += ">\n";
if (!searchFields.isEmpty()) {
xml += "\t" + getSearchFields() + "\n";
}
String groupLabel =
chartBuilder.getIsJsonGroupOn()
? chartBuilder.getGroupOnJson().getTitle()
: chartBuilder.getGroupOn().getLabel();
String displayLabel =
chartBuilder.getIsJsonDisplayField()
? chartBuilder.getDisplayFieldJson().getTitle()
: chartBuilder.getDisplayField().getLabel();
xml += "\t<dataset type=\"sql\"><![CDATA[";
xml += Tab2 + queryString[0];
xml += Tab2 + " ]]></dataset>";
xml +=
Tab1
+ "<category key=\"group_field\" type=\""
+ categType
+ "\" title=\""
+ groupLabel
+ "\" />";
xml +=
Tab1
+ "<series key=\"sum_field\" type=\""
+ chartBuilder.getChartType()
+ "\" title=\""
+ displayLabel
+ "\" ";
if (queryString[1] != null) {
xml += "groupBy=\"agg_field\" ";
}
xml += "/>\n";
xml += "</chart>";
return xml;
}
/**
* Method create query from chart filters added in chart builder.
*
* @param viewBuilder ViewBuilder of type chart
* @return StringArray with first element as query string and second as aggregate field name.
* @throws AxelorException
*/
private String[] prepareQuery(ChartBuilder chartBuilder) throws AxelorException {
String query =
createSumQuery(
chartBuilder.getIsJsonDisplayField(),
chartBuilder.getDisplayField(),
chartBuilder.getDisplayFieldJson());
String groupField =
getGroup(
chartBuilder.getIsJsonGroupOn(),
chartBuilder.getGroupOn(),
chartBuilder.getGroupOnJson(),
chartBuilder.getGroupDateType(),
chartBuilder.getGroupOnTarget());
String aggField =
getGroup(
chartBuilder.getIsJsonAggregateOn(),
chartBuilder.getAggregateOn(),
chartBuilder.getAggregateOnJson(),
chartBuilder.getAggregateDateType(),
chartBuilder.getAggregateOnTarget());
query += groupField + " AS group_field";
if (aggField != null) {
query += "," + Tab3 + aggField + " AS agg_field";
}
String filters = filterSqlService.getSqlFilters(chartBuilder.getFilterList(), joins, true);
addSearchField(chartBuilder.getFilterList());
String model = chartBuilder.getModel();
if (chartBuilder.getIsJson()) {
if (filters != null) {
filters = "self.json_model = '" + model + "' AND (" + filters + ")";
} else {
filters = "self.json_model = '" + model + "'";
}
model = MetaJsonRecord.class.getName();
}
query += Tab2 + "FROM " + Tab3 + getTable(model) + " self";
if (!joins.isEmpty()) {
query += Tab3 + Joiner.on(Tab3).join(joins);
}
if (filters != null) {
query += Tab2 + "WHERE " + Tab3 + filters;
}
query += Tab2 + "group by " + Tab3 + "group_field";
if (aggField != null && aggField != null) {
query += ",agg_field";
return new String[] {query, aggField};
}
return new String[] {query, null};
}
private String createSumQuery(boolean isJson, MetaField metaField, MetaJsonField jsonField) {
String sumField = null;
if (isJson) {
String sqlType = filterSqlService.getSqlType(jsonField.getType());
sumField =
"cast(self."
+ filterSqlService.getColumn(jsonField.getModel(), jsonField.getModelField())
+ "->>'"
+ jsonField.getName()
+ "' as "
+ sqlType
+ ")";
} else {
sumField = "self." + filterSqlService.getColumn(metaField);
}
return "SELECT" + Tab3 + "SUM(" + sumField + ") AS sum_field," + Tab3;
}
private String getGroup(
boolean isJson, MetaField metaField, MetaJsonField jsonField, String dateType, String target)
throws AxelorException {
if (!isJson && metaField == null || isJson && jsonField == null) {
return null;
}
String typeName = null;
String group = null;
Object object = null;
StringBuilder parent = new StringBuilder("self");
if (isJson) {
group = jsonField.getName();
typeName = filterSqlService.getSqlType(jsonField.getType());
if (target != null) {
object = filterSqlService.parseJsonField(jsonField, target, joins, parent);
}
} else {
group = filterSqlService.getColumn(metaField);
typeName = filterSqlService.getSqlType(metaField.getTypeName());
if (target != null) {
object = filterSqlService.parseMetaField(metaField, target, joins, parent, true);
}
}
if (object != null) {
String[] sqlField = filterSqlService.getSqlField(object, parent.toString(), joins);
typeName = sqlField[1];
group = sqlField[0];
}
log.debug("Group field type: {}, group: {}, dateType: {}", typeName, group, dateType);
if (dateType != null && typeName != null && dateTypes.contains(typeName.toUpperCase())) {
group = getDateTypeGroup(dateType, typeName, group);
}
return group;
}
private String getDateTypeGroup(String dateType, String typeName, String group) {
switch (dateType) {
case "year":
group = "to_char(cast(" + group + " as date), 'yyyy')";
break;
case "month":
group = "to_char(cast(" + group + " as date), 'yyyy-mm')";
break;
default:
categType = "date";
}
return group;
}
/**
* Method generate xml for search-fields.
*
* @return
*/
private String getSearchFields() {
String search = "<search-fields>";
for (String searchField : searchFields) {
search += Tab2 + searchField;
}
search += Tab1 + "</search-fields>";
return search;
}
/**
* Method set default value for search-fields(parameters). It will add field and expression in
* onNew for chart.
*
* @param fieldName Name of field of search-field.
* @param typeName Type of field.
* @param defaultValue Default value input in chart filter.
* @param modelField It is for relational field. String array with first element as Model name and
* second as its field.
*/
// private void setDefaultValue(String fieldName, String typeName,
// String defaultValue, String[] modelField) {
//
// if (defaultValue == null) {
// return;
// }
//
// RecordField field = new RecordField();
// field.setName(fieldName);
//
// defaultValue = filterCommonService.getTagValue(defaultValue, false);
//
// if (modelField != null) {
// if (typeName.equals("STRING")) {
// defaultValue = "__repo__(" + modelField[0]
// + ").all().filter(\"LOWER(" + modelField[1] + ") LIKE "
// + defaultValue + "\").fetchOne()";
// } else {
// defaultValue = "__repo__(" + modelField[0]
// + ").all().filter(\"" + modelField[1] + " = "
// + defaultValue + "\").fetchOne()";
// }
//
// }
//
// log.debug("Default value: {}", defaultValue);
//
// field.setExpression("eval:" + defaultValue);
//
// onNewFields.add(field);
// }
/**
* It will create onNew action from onNew fields.
*
* @param viewBuilder ViewBuilder use to get model name also used in onNew action name creation.
*/
// private void setOnNewAction(ChartBuilder chartBuilder) {
//
// if (!onNewFields.isEmpty()) {
// onNewAction = new ActionRecord();
// onNewAction.setName("action-" + chartBuilder.getName() + "-default");
// onNewAction.setModel(chartBuilder.getModel());
// onNewAction.setFields(onNewFields);
// }
//
// }
private void addSearchField(List<Filter> filters) throws AxelorException {
if (filters == null) {
return;
}
for (Filter filter : filters) {
if (!filter.getIsParameter()) {
continue;
}
String fieldStr = "param" + filter.getId();
Object object = null;
StringBuilder parent = new StringBuilder("self");
if (filter.getIsJson()) {
object =
filterSqlService.parseJsonField(
filter.getMetaJsonField(), filter.getTargetField(), null, parent);
} else {
object =
filterSqlService.parseMetaField(
filter.getMetaField(), filter.getTargetField(), null, parent, true);
}
if (object instanceof MetaField) {
fieldStr = getMetaSearchField(fieldStr, (MetaField) object);
} else {
fieldStr = getJsonSearchField(fieldStr, (MetaJsonField) object);
}
searchFields.add(fieldStr + "\" x-required=\"true\" />");
}
}
private String getMetaSearchField(String fieldStr, MetaField field) {
fieldStr = "<field name=\"" + fieldStr + "\" title=\"" + field.getLabel();
if (field.getRelationship() == null) {
String fieldType = filterCommonService.getFieldType(field);
fieldStr += "\" type=\"" + fieldType;
} else {
String[] targetRef = filterSqlService.getDefaultTarget(field.getName(), field.getTypeName());
String[] nameField = targetRef[0].split("\\.");
fieldStr +=
"\" widget=\"ref-text\" type=\""
+ filterCommonService.getFieldType(targetRef[1])
+ "\" x-target-name=\""
+ nameField[1]
+ "\" x-target=\""
+ metaModelRepo.findByName(field.getTypeName()).getFullName();
}
return fieldStr;
}
private String getJsonSearchField(String fieldStr, MetaJsonField field) {
fieldStr = "<field name=\"" + fieldStr + "\" title=\"" + field.getTitle();
if (field.getTargetJsonModel() != null) {
String[] targetRef =
filterSqlService.getDefaultTargetJson(field.getName(), field.getTargetJsonModel());
String[] nameField = targetRef[0].split("\\.");
fieldStr +=
"\" widget=\"ref-text\" type=\""
+ filterCommonService.getFieldType(targetRef[1])
+ "\" x-target-name=\""
+ nameField[1]
+ "\" x-target=\""
+ MetaJsonRecord.class.getName()
+ "\" x-domain=\"self.jsonModel = '"
+ field.getTargetJsonModel().getName()
+ "'";
} else if (field.getTargetModel() != null) {
String[] targetRef =
filterSqlService.getDefaultTarget(field.getName(), field.getTargetModel());
String[] nameField = targetRef[0].split("\\.");
fieldStr +=
"\" widget=\"ref-text\" type=\""
+ filterCommonService.getFieldType(targetRef[1])
+ "\" x-target-name=\""
+ nameField[1]
+ "\" x-target=\""
+ field.getTargetModel();
} else {
String fieldType = Inflector.getInstance().camelize(field.getType(), true);
fieldStr += "\" type=\"" + fieldType;
}
return fieldStr;
}
private String getTable(String model) {
String[] models = model.split("\\.");
MetaModel metaModel = metaModelRepo.findByName(models[models.length - 1]);
if (metaModel != null) {
return metaModel.getTableName();
}
return null;
}
@CallMethod
public String getDefaultTarget(MetaField metaField) {
if (metaField.getRelationship() == null) {
return metaField.getName();
}
return filterSqlService.getDefaultTarget(metaField.getName(), metaField.getTypeName())[0];
}
@CallMethod
public String getDefaultTarget(MetaJsonField metaJsonField) {
if (!"many-to-one,one-to-one,json-many-to-one".contains(metaJsonField.getType())) {
return metaJsonField.getName();
}
if (metaJsonField.getTargetJsonModel() != null) {
return filterSqlService
.getDefaultTargetJson(metaJsonField.getName(), metaJsonField.getTargetJsonModel())[0];
}
if (metaJsonField.getTargetModel() == null) {
return metaJsonField.getName();
}
return filterSqlService
.getDefaultTarget(metaJsonField.getName(), metaJsonField.getTargetModel())[0];
}
@CallMethod
public String getTargetType(Object object, String target) {
if (target == null) {
log.debug("No target provided for target type");
return null;
}
Object targetField = null;
try {
if (object instanceof MetaJsonField) {
targetField = filterSqlService.parseJsonField((MetaJsonField) object, target, null, null);
} else if (object instanceof MetaField) {
targetField = filterSqlService.parseMetaField((MetaField) object, target, null, null, true);
}
} catch (AxelorException e) {
}
if (targetField == null) {
log.debug("Target field not found");
return null;
}
log.debug("Target field found: {}", targetField);
return filterSqlService.getTargetType(targetField);
}
}

View File

@ -0,0 +1,171 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.schema.views.AbstractWidget;
import com.axelor.meta.schema.views.Dashboard;
import com.axelor.meta.schema.views.Dashlet;
import com.axelor.studio.db.DashboardBuilder;
import com.axelor.studio.db.DashletBuilder;
import com.axelor.studio.service.StudioMetaService;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This service class used to generate dashboard from ViewBuilder of type Dashboard. It will take
* all selected charts and generate xml from it.
*
* @author axelor
*/
public class DashboardBuilderService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Inject private StudioMetaService metaService;
/**
* Method to generate Dashboard (meta schema) from View Builder.
*
* @param viewBuilder ViewBuilder of type dashboard.
* @return Dashboard.
*/
public MetaView build(DashboardBuilder dashboardBuilder) {
log.debug("Processing dashboard: {}", dashboardBuilder.getName());
log.debug("Dashlet list: {}", dashboardBuilder.getDashletBuilderList());
if (dashboardBuilder.getDashletBuilderList() == null
|| dashboardBuilder.getDashletBuilderList().isEmpty()) {
return null;
}
Dashboard dashboard = new Dashboard();
String boardName = dashboardBuilder.getName();
dashboard.setTitle(dashboardBuilder.getTitle());
dashboard.setName(dashboardBuilder.getName());
List<AbstractWidget> dashlets = new ArrayList<AbstractWidget>();
dashboardBuilder.clearGeneratedActions();
for (DashletBuilder dashletBuilder : dashboardBuilder.getDashletBuilderList()) {
Dashlet dashlet = new Dashlet();
String name = null;
String model = null;
MetaView metaView = dashletBuilder.getMetaView();
MetaAction action = dashletBuilder.getAction();
String actionName = null;
if (metaView != null) {
name = metaView.getName();
model = metaView.getModel();
MetaAction metaAction = getAction(boardName, name, model, dashletBuilder);
actionName = metaAction.getName();
dashboardBuilder.addGeneratedAction(metaAction);
} else if (action != null) {
model = action.getModel();
actionName = action.getName();
}
dashlet.setAction(actionName);
dashlet.setHeight("350");
Integer colSpan = dashletBuilder.getColspan();
if (colSpan > 12) {
colSpan = 12;
} else if (colSpan <= 0) {
colSpan = 6;
}
dashlet.setColSpan(colSpan);
dashlets.add(dashlet);
}
if (dashlets.isEmpty()) {
return null;
}
dashboard.setItems(dashlets);
MetaStore.clear();
return metaService.generateMetaView(dashboard);
}
/**
* Method to generate action-view for a chart
*
* @param dashboard Dashboard in which chart to be used.
* @param actions
* @param chart Chart to open from action-view.
* @return Name of action-view.
*/
private MetaAction getAction(
String dashboard, String name, String model, DashletBuilder dashletBuilder) {
String actionName = "action-" + (dashboard + "-" + name).replace(".", "-");
boolean isJson = model != null && model.contentEquals(MetaJsonRecord.class.getName());
String otherView = "form";
String view = dashletBuilder.getViewType();
if (view.equals("form")) {
otherView = "grid";
}
String xmlId = StudioMetaService.XML_ID_PREFIX + actionName;
StringBuilder xml = new StringBuilder();
xml.append("<action-view name=\"" + actionName + "\" ");
xml.append("id=\"" + xmlId + "\" ");
xml.append("title=\"" + dashletBuilder.getName() + "\" ");
if (model != null) {
xml.append("model=\"" + model + "\"");
}
xml.append(">");
xml.append("\n\t<view type=\"" + view + "\" ");
xml.append("name=\"" + name + "\" />");
if (isJson) {
xml.append("\n\t<view type=\"" + otherView + "\" ");
xml.append("name=\"" + name.replace("-" + view, "-" + otherView) + "\" />");
} else {
xml.append("\n\t<view type=\"" + otherView + "\" />");
}
if (dashletBuilder.getPaginationLimit() > 0) {
xml.append(
"\n\t<view-param name=\"limit\" value=\""
+ dashletBuilder.getPaginationLimit().toString()
+ "\"/>");
}
if (isJson) {
String[] models = name.split("-");
xml.append("\n\t<domain>self.jsonModel = '" + models[models.length - 2] + "'</domain>");
}
xml.append("\n</action-view>");
return metaService.updateMetaAction(actionName, "action-view", xml.toString(), model);
}
}

View File

@ -0,0 +1,121 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.exception.service.TraceBackService;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.meta.db.MetaMenu;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.ObjectViews;
import com.axelor.meta.schema.actions.Action;
import com.axelor.meta.schema.actions.ActionView;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.ActionBuilderLine;
import com.axelor.studio.db.ActionBuilderView;
import com.axelor.studio.db.MenuBuilder;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import com.axelor.studio.service.StudioMetaService;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.util.List;
import java.util.Optional;
import javax.xml.bind.JAXBException;
public class MenuBuilderService {
@Inject private ActionBuilderService actionBuilderService;
@Inject private StudioMetaService metaService;
@Transactional
public MetaMenu build(MenuBuilder builder) {
MetaMenu menu = metaService.createMenu(builder);
ActionBuilder actionBuilder = builder.getActionBuilder();
if (actionBuilder != null) {
if (actionBuilder.getName() == null) {
actionBuilder.setName(menu.getName().replace("-", "."));
}
actionBuilder.setTitle(menu.getTitle());
actionBuilder.setAppBuilder(builder.getAppBuilder());
menu.setAction(actionBuilderService.build(actionBuilder));
}
MetaStore.clear();
return menu;
}
@SuppressWarnings("unchecked")
public Optional<ActionBuilder> createActionBuilder(MetaAction metaAction) {
try {
ObjectViews objectViews = XMLViews.fromXML(metaAction.getXml());
List<Action> actions = objectViews.getActions();
if (actions != null && !actions.isEmpty()) {
ActionView action = (ActionView) actions.get(0);
if (action.getModel() != null
&& action.getModel().contentEquals(MetaJsonRecord.class.getName())) {
return Optional.empty();
}
ActionBuilder actionBuilder = new ActionBuilder(action.getName());
actionBuilder.setTitle(action.getTitle());
actionBuilder.setModel(action.getModel());
actionBuilder.setTypeSelect(ActionBuilderRepository.TYPE_SELECT_VIEW);
String domain = action.getDomain();
actionBuilder.setDomainCondition(domain);
for (ActionView.View view : action.getViews()) {
ActionBuilderView builderView = new ActionBuilderView();
builderView.setViewType(view.getType());
builderView.setViewName(view.getName());
actionBuilder.addActionBuilderView(builderView);
}
if (action.getParams() != null) {
for (ActionView.Param param : action.getParams()) {
ActionBuilderLine paramLine = new ActionBuilderLine();
paramLine.setName(param.getName());
paramLine.setValue(param.getValue());
actionBuilder.addViewParam(paramLine);
}
}
if (action.getContext() != null) {
for (ActionView.Context ctx : (List<ActionView.Context>) action.getContext()) {
ActionBuilderLine ctxLine = new ActionBuilderLine();
ctxLine.setName(ctx.getName());
if (ctx.getName().contentEquals("jsonModel")
&& domain != null
&& domain.contains("self.jsonModel = :jsonModel")) {
actionBuilder.setIsJson(true);
actionBuilder.setModel(ctx.getExpression());
}
ctxLine.setValue(ctx.getExpression());
actionBuilder.addLine(ctxLine);
}
}
return Optional.of(actionBuilder);
}
} catch (JAXBException e) {
TraceBackService.trace(e);
}
return Optional.empty();
}
}

View File

@ -0,0 +1,516 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.builder;
import com.axelor.common.Inflector;
import com.axelor.db.mapper.Mapper;
import com.axelor.db.mapper.Property;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaModel;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.db.repo.MetaFieldRepository;
import com.axelor.meta.db.repo.MetaModelRepository;
import com.axelor.meta.db.repo.MetaViewRepository;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.ObjectViews;
import com.axelor.meta.schema.views.AbstractView;
import com.axelor.meta.schema.views.AbstractWidget;
import com.axelor.meta.schema.views.Field;
import com.axelor.meta.schema.views.FormView;
import com.axelor.meta.schema.views.GridView;
import com.axelor.meta.schema.views.Panel;
import com.axelor.meta.schema.views.PanelField;
import com.axelor.meta.schema.views.PanelRelated;
import com.axelor.meta.schema.views.PanelTabs;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.JAXBException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service class generate html template from selected metaView for ReportBuilder. It also add button
* into MetaView selected as buttonView in ReportBuilder.
*
* @author axelor
*/
public class ReportBuilderService {
private Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private List<String[]> panels;
private List<String[]> sidePanels;
private String model;
private String template;
private Inflector inflector;
@Inject private MetaFieldRepository metaFieldRepo;
@Inject private MetaViewRepository metaViewRepo;
@Inject private MetaModelRepository metaModelRepo;
/**
* Method create html template from MetaView. This is root method to create template. Html
* contains table with two columns. If field is o2m/m2m it will take full row span.
*
* @param metaView MetaView to process
* @return Html template generated.
*/
public String generateTemplate(MetaView metaView) {
panels = new ArrayList<String[]>();
sidePanels = new ArrayList<String[]>();
model = metaView.getModel();
template = "";
inflector = Inflector.getInstance();
try {
processView(metaView.getXml());
generateHtml(false);
generateHtml(true);
template = "<table class=\"table no-border\"><tr>" + template + "</tr></table>";
log.debug("Template generated: {}", template);
return template;
} catch (JAXBException e) {
e.printStackTrace();
}
return null;
}
/**
* Method parse given xml to create html.
*
* @param xml View xml passed.
* @throws JAXBException Xml parsing exception.
*/
private void processView(String xml) throws JAXBException {
ObjectViews objectViews = XMLViews.fromXML(xml);
AbstractView view = objectViews.getViews().get(0);
FormView formView = (FormView) view;
for (AbstractWidget widget : formView.getItems()) {
if (widget instanceof PanelTabs) {
PanelTabs panelTabs = (PanelTabs) widget;
AbstractWidget tabItem = panelTabs.getItems().get(0);
processAbstractWidget(tabItem, false);
continue;
}
processAbstractWidget(widget, false);
}
}
/**
* Check given AbstractWidget and process it according to its type.
*
* @param widget AbstractWidget to process
* @param sidePanel Boolean to check if widget is sidePanel.
*/
private void processAbstractWidget(AbstractWidget widget, Boolean sidePanel) {
if (widget instanceof Panel) {
processPanel((Panel) widget, sidePanel);
} else if (widget instanceof PanelRelated) {
PanelRelated panelRelated = (PanelRelated) widget;
sidePanel = sidePanel != null && sidePanel ? sidePanel : panelRelated.getSidebar();
processPanelRelated(panelRelated, sidePanel, "12");
} else if (widget instanceof PanelField) {
processField((PanelField) widget, sidePanel);
}
}
/**
* Process panel to create html from it and to process items of panels. It add panel title in full
* row span of html table.
*
* @param panel Panels to process.
* @param sidePanel Boolean to check if panel is sidePanel.
*/
private void processPanel(Panel panel, Boolean sidePanel) {
sidePanel = sidePanel != null && sidePanel ? sidePanel : panel.getSidebar();
String title = panel.getTitle();
if (title != null) {
title = "<td><h4><u>" + title + "</u></h4></td>";
if (sidePanel != null && sidePanel) {
sidePanels.add(new String[] {"12", title});
} else {
panels.add(new String[] {"12", title});
}
}
for (AbstractWidget widget : panel.getItems()) {
processAbstractWidget(widget, sidePanel);
}
}
/**
* Process PanelField and extend html table of html template.
*
* @param field PanelField to process.
* @param sidePanel Boolean to check if field is in sidePanel.
* @param colSpan Colspan of field.
*/
private void processField(PanelField field, Boolean sidePanel) {
String title = field.getTitle();
String name = field.getName();
MetaField metaField = getMetaField(name, model);
if (Strings.isNullOrEmpty(title)) {
title = getFieldTitle(name, metaField);
}
name = processRelational(name, metaField);
String value = "<td><b>" + title + "</b> : $" + name + "$</td>";
String colSpan = "6";
if (field.getColSpan() != null && field.getColSpan() == 12) {
colSpan = "12";
value = "<td colSpan=\"2\"><b>" + title + "</b> : $" + name + "$</td>";
} else {
value = "<td><b>" + title + "</b> : $" + name + "$</td>";
}
if (sidePanel != null && sidePanel) {
sidePanels.add(new String[] {"12", value});
} else {
panels.add(new String[] {colSpan, value});
}
}
/**
* Check given metaField and process relational field to create proper string template friendly
* string.
*
* @param name Name of field.
* @param metaField MetaField to process.
* @return Template friendly string created for relational field.
*/
private String processRelational(String name, MetaField metaField) {
if (metaField == null) {
return name;
}
String relationship = metaField.getRelationship();
if (relationship == null) {
return name;
}
String nameColumn = getNameColumn(name, metaField);
if (!relationship.equals("ManyToOne")) {
String[] names = nameColumn.split("\\.");
nameColumn = name + " : {item | $item." + names[1] + "$ }";
}
return nameColumn;
}
/**
* Get nameColumn for given relational metaField.
*
* @param name Field name
* @param metaField MetaField to check.
* @return Name column of field.
*/
private String getNameColumn(String name, MetaField metaField) {
String refModel = getRefModel(metaField.getTypeName());
try {
Mapper mapper = Mapper.of(Class.forName(refModel));
boolean nameField = false;
boolean codeField = false;
for (Property property : Arrays.asList(mapper.getProperties())) {
if (property.isNameColumn()) {
return name + "." + property.getName();
} else if (property.getName().equals("name")) {
nameField = true;
} else if (property.getName().equals("code")) {
codeField = true;
}
}
if (nameField) {
return name + ".name";
}
if (codeField) {
return name + ".code";
}
return name + "." + "id";
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return name;
}
/**
* Method generate main html table of html template, from 'panels' and 'sidePanels' list created
* during view xml processing.
*
* @param sidePanel Boolean to check which panel list to process.
*/
private void generateHtml(boolean sidePanel) {
List<String[]> panelList = sidePanel ? sidePanels : panels;
if (panelList.isEmpty()) {
return;
}
template += "<td><table>";
int totalSpan = 0;
for (String[] field : panelList) {
int colSpan = Integer.parseInt(field[0]);
if (colSpan == 12) {
if (totalSpan > 0) {
totalSpan = 0;
template += "</tr>";
}
template += "<tr>" + field[1] + "</tr>";
} else {
if (totalSpan == 0) {
template += "<tr>";
}
template += field[1];
totalSpan += colSpan;
if (totalSpan == 12) {
totalSpan = 0;
template += "</tr>";
}
}
}
if (totalSpan > 0) {
template += "</tr>";
}
template += "</table></td>";
}
/**
* It returns title of MetaField and if title is empty it create human readable title from field
* name.
*
* @param name Name of field.
* @param metaField MetaField to process.
* @return Title of field.
*/
private String getFieldTitle(String name, MetaField metaField) {
log.debug("Meta field for name : {}, metaField: {}", name, metaField);
if (metaField != null) {
String title = metaField.getLabel();
if (!Strings.isNullOrEmpty(title)) {
return metaField.getLabel();
}
}
return inflector.humanize(name);
}
/**
* Method to get MetaField record from field name and model.
*
* @param name Field name to search.
* @param modelName Model of field.
* @return Return MetaField found.
*/
private MetaField getMetaField(String name, String modelName) {
MetaField metaField =
metaFieldRepo
.all()
.filter("self.name = ? AND self.metaModel.fullName = ?", name, modelName)
.fetchOne();
return metaField;
}
/**
* Process panelRelated and update 'panels' or 'sidePanels' list with new table created for
* panelRelated.
*
* @param panelRelated PanelRelated to process.
* @param sidePanel Boolean to check if panelRelated is sidePanel.
* @param colSpan Colspan to add in panel lists.
*/
public void processPanelRelated(PanelRelated panelRelated, Boolean sidePanel, String colSpan) {
String title = panelRelated.getTitle();
String name = panelRelated.getName();
MetaField metaField = getMetaField(name, model);
if (Strings.isNullOrEmpty(title) && metaField != null) {
title = metaField.getLabel();
}
if (Strings.isNullOrEmpty(title)) {
title = inflector.humanize(name);
}
String field = "<td colSpan=\"2\"><h4>" + title + "</h4></td>";
String refModel = getRefModel(metaField.getTypeName());
String itemTable = createTable(panelRelated, refModel);
if (sidePanel != null && sidePanel) {
sidePanels.add(new String[] {"12", field});
sidePanels.add(new String[] {"12", itemTable});
} else {
panels.add(new String[] {colSpan, field});
panels.add(new String[] {colSpan, itemTable});
}
}
/**
* Process panelRelated to find right grid view of reference model. Grid view used to create html
* table.
*
* @param panelRelated PanelRelated to use.
* @param refModel Name of model refer by panelRelated.
* @return Html table string created.
*/
private String createTable(PanelRelated panelRelated, String refModel) {
List<AbstractWidget> items = panelRelated.getItems();
if (items != null && !items.isEmpty()) {
return getHtmlTable(panelRelated.getName(), items, refModel);
}
MetaView gridView = findGridView(panelRelated.getGridView(), refModel);
if (gridView != null) {
try {
ObjectViews views = XMLViews.fromXML(gridView.getXml());
GridView grid = (GridView) views.getViews().get(0);
return getHtmlTable(panelRelated.getName(), grid.getItems(), refModel);
} catch (JAXBException e) {
e.printStackTrace();
}
}
return "";
}
/**
* Create html table string from list of widgets(Items of grd view).
*
* @param fieldName Name of relational field.
* @param widgets List of widgets in reference model's grid view.
* @param refModel Name of reference model.
* @return Html table created.
*/
private String getHtmlTable(String fieldName, List<AbstractWidget> widgets, String refModel) {
String header = "";
String row = "";
for (AbstractWidget widget : widgets) {
if (widget instanceof Field) {
Field field = (Field) widget;
String name = field.getName();
String title = field.getTitle();
MetaField metaField = getMetaField(name, refModel);
if (Strings.isNullOrEmpty(title)) {
title = getFieldTitle(name, metaField);
}
name = processRelational(name, metaField);
header += "<th>" + title + "</th>";
row += "<td>$" + fieldName + "." + name + "$</td>";
}
}
String table =
"<td colSpan=\"2\"><table class=\"table table-bordered table-header\">"
+ "<tr>"
+ header
+ "</tr>"
+ "<tr>"
+ row
+ "</tr>"
+ "</table></td>";
return table;
}
/**
* Find MetaView record from given gridName and reference model.
*
* @param gridName Name of grid view.
* @param refModel Model of grid view.
* @return MetaView record searched.
*/
private MetaView findGridView(String gridName, String refModel) {
MetaView gridView = null;
if (gridName != null) {
gridView = metaViewRepo.findByName(gridName);
}
if (gridView == null) {
gridView =
metaViewRepo.all().filter("self.type = 'grid' and self.model = ?", refModel).fetchOne();
}
return gridView;
}
/**
* Get fullName of reference model.
*
* @param refModel Name of reference model.
* @return FullName of Model
*/
private String getRefModel(String refModel) {
MetaModel metaModel = metaModelRepo.findByName(refModel);
if (metaModel != null) {
refModel = metaModel.getFullName();
}
return refModel;
}
}

View File

@ -0,0 +1,170 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.filter;
import com.axelor.meta.db.MetaField;
import java.util.Arrays;
public class FilterCommonService {
/**
* It will return value of tag used by filter 'value'.
*
* @param value Value of chart filter.
* @return Context variable to use instead of tag.
*/
public String getTagValue(String value, boolean addColon) {
if (value != null) {
if (addColon) {
value = value.replace("$user", ":__user__");
value = value.replace("$date", ":__date__");
value = value.replace("$time", ":__datetime__");
} else {
value = value.replace("$user", "__user__");
value = value.replace("$date", "__date__");
value = value.replace("$time", "__datetime__");
}
}
return value;
}
/**
* Method create like condition for filter with string field.
*
* @param conditionField Chart filter field name
* @param value Value of input in chart filter.
* @param isLike boolean to check if condition is like or notLike
* @return String condition.
*/
public String getLikeCondition(String conditionField, String value, boolean isLike) {
String likeCondition = null;
String likeOpr = "LIKE";
if (!isLike) {
likeOpr = "NOT LIKE";
}
if (value.contains(",")) {
for (String val : Arrays.asList(value.split(","))) {
if (likeCondition == null) {
likeCondition = conditionField + " " + likeOpr + " " + val;
} else {
likeCondition += " OR " + conditionField + " " + likeOpr + " " + val;
}
}
} else {
likeCondition = conditionField + " " + likeOpr + " " + value;
}
return likeCondition;
}
/**
* Get simple field type from typeName of MetaField
*
* @param metaField MetaField to check for typeName.
* @return Simple field type.
*/
public String getFieldType(MetaField metaField) {
String relationship = metaField.getRelationship();
if (relationship != null) {
switch (relationship) {
case "OneToMany":
return "one-to-many";
case "ManyToMany":
return "many-to-many";
case "ManyToOne":
return "many-to-one";
}
}
return getFieldType(metaField.getTypeName());
}
public String getFieldType(String type) {
switch (type) {
case "String":
return "string";
case "Integer":
return "integer";
case "Boolean":
return "boolean";
case "BigDecimal":
return "decimal";
case "Long":
return "long";
case "byte[]":
return "binary";
case "LocalDate":
return "date";
case "ZonedDateTime":
return "datetime";
case "LocalDateTime":
return "datetime";
default:
return "string";
}
}
public String getCondition(String conditionField, String operator, String value) {
value = getTagValue(value, true);
String[] values = new String[] {""};
if (value != null) {
values = value.split(",");
}
switch (operator) {
case "like":
return getLikeCondition(conditionField, value, true);
case "notLike":
return getLikeCondition(conditionField, value, false);
case "in":
return conditionField + " IN" + " (" + value + ") ";
case "notIn":
return conditionField + " NOT IN" + " (" + value + ") ";
case "isNull":
return conditionField + " IS NULL ";
case "notNull":
return conditionField + " IS NOT NULL ";
case "between":
if (values.length > 1) {
return conditionField + " BETWEEN " + values[0] + " AND " + values[1];
}
return conditionField + " BETWEEN " + values[0] + " AND " + values[0];
case "notBetween":
if (values.length > 1) {
return conditionField + " NOT BETWEEN " + values[0] + " AND " + values[1];
}
return conditionField + " NOT BETWEEN " + values[0] + " AND " + values[0];
case "isTrue":
return conditionField + " IS TRUE ";
case "isFalse":
return conditionField + " IS FALSE ";
default:
return conditionField + " " + operator + " " + value;
}
}
}

View File

@ -0,0 +1,135 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.filter;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.studio.db.Filter;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FilterGroovyService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Inject private FilterCommonService filterCommonService;
/**
* Method to convert chart filter list to groovy expression string. Each filter of list will be
* joined by logical operator(logicalOp) selected.
*
* @param conditions List for chart filters.
* @param parentField Field that represent parent.
* @return Groovy expression string.
*/
public String getGroovyFilters(List<Filter> conditions, String parentField) {
String condition = null;
if (conditions == null) {
return null;
}
for (Filter filter : conditions) {
String activeFilter = createGroovyFilter(filter, parentField);
log.debug("Active filter: {}", filter);
if (condition == null) {
condition = "(" + activeFilter;
} else if (filter.getLogicOp() > 0) {
condition += ") || (" + activeFilter;
} else {
condition += " && " + activeFilter;
}
}
if (condition == null) {
return null;
}
return condition + ")";
}
/**
* Method to generate groovy expression for a single chart filter.
*
* @param chartFilter Chart filter to use .
* @param parentField Parent field.
* @return Groovy expression string.
*/
private String createGroovyFilter(Filter filter, String parentField) {
MetaJsonField metaJsonField = filter.getMetaJsonField();
String field =
parentField != null ? parentField + "." + metaJsonField.getName() : metaJsonField.getName();
String targetField =
parentField != null ? parentField + "." + filter.getTargetField() : filter.getTargetField();
String value = processValue(filter);
String operator = filter.getOperator();
if (targetField != null) {
targetField = targetField.replace(".", "?.");
if (metaJsonField.getType().equals("many-to-one")
|| metaJsonField.getType().equals("json-many-to-one")) {
field = targetField;
} else if (metaJsonField.getType().equals("many-to-many") && !operator.contains("empty")) {
targetField = targetField.replace(field + "?.", "it?.");
String condition = getConditionExpr(operator, targetField, value);
return field + ".findAll{it->" + condition + "}.size() > 0";
}
}
return getConditionExpr(operator, field, value);
}
private String processValue(Filter filter) {
String value = filter.getValue();
if (value == null) {
return value;
}
value = value.replace("$$", "_parent.");
return filterCommonService.getTagValue(value, false);
}
private String getConditionExpr(String operator, String field, String value) {
switch (operator) {
case "=":
return field + " == " + value;
case "isNull":
return field + " == null";
case "notNull":
return field + " != null";
case "empty":
return field + ".empty";
case "notEmpty":
return "!" + field + ".empty";
case "isTrue":
return field;
case "isFalse":
return "!" + field;
default:
return field + " " + operator + " " + value;
}
}
}

View File

@ -0,0 +1,98 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.filter;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.studio.db.Filter;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This service class use to generate groovy expression from chart filters.
*
* @author axelor
*/
public class FilterJpqlService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Inject private FilterCommonService filterCommonService;
public String getJpqlFilters(List<Filter> filterList) {
String filters = null;
if (filterList == null) {
return filters;
}
for (Filter filter : filterList) {
MetaField field = filter.getMetaField();
if (filter.getValue() != null) {
String value = filter.getValue();
value = value.replaceAll("\"", "");
value = value.replaceAll("'", "");
if (filter.getOperator().contains("like") && !value.contains("%")) {
value = "%" + value + "%";
}
filter.setValue("'" + value + "'");
}
String relationship = field.getRelationship();
String fieldName =
relationship != null ? filter.getTargetField() : filter.getMetaField().getName();
fieldName = "self." + fieldName;
if (filter.getTargetType().equals("String")) {
fieldName = "LOWER(" + fieldName + ")";
filter.setValue("LOWER(" + filter.getValue() + ")");
}
String condition =
filterCommonService.getCondition(fieldName, filter.getOperator(), filter.getValue());
if (filters == null) {
filters = condition;
} else {
String opt = filter.getLogicOp() != null && filter.getLogicOp() == 0 ? " AND " : " OR ";
filters = filters + opt + condition;
}
}
log.debug("JPQL filter: {}", filters);
return filters;
}
public String getJsonJpql(MetaJsonField jsonField) {
switch (jsonField.getType()) {
case "integer":
return "json_extract_integer";
case "decimal":
return "json_extract_decimal";
case "boolean":
return "json_extract_boolean";
default:
return "json_extract";
}
}
}

View File

@ -0,0 +1,485 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.filter;
import com.axelor.common.Inflector;
import com.axelor.db.JPA;
import com.axelor.db.mapper.Mapper;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.repo.TraceBackRepository;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaJsonModel;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.meta.db.MetaModel;
import com.axelor.meta.db.repo.MetaFieldRepository;
import com.axelor.meta.db.repo.MetaJsonFieldRepository;
import com.axelor.meta.db.repo.MetaModelRepository;
import com.axelor.studio.db.Filter;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import java.lang.invoke.MethodHandles;
import java.util.List;
import org.hibernate.internal.SessionImpl;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FilterSqlService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Inject private FilterCommonService filterCommonService;
@Inject private MetaFieldRepository metaFieldRepo;
@Inject private MetaModelRepository metaModelRepo;
@Inject private MetaJsonFieldRepository metaJsonFieldRepo;
public String getColumn(String model, String field) {
SessionImpl sessionImpl = (SessionImpl) JPA.em().getDelegate();
@SuppressWarnings("deprecation")
AbstractEntityPersister aep =
((AbstractEntityPersister)
sessionImpl.getSession().getSessionFactory().getClassMetadata(model));
String[] columns = aep.getPropertyColumnNames(field);
if (columns != null && columns.length > 0) {
return columns[0];
}
return null;
}
public String getColumn(MetaField metaField) {
return getColumn(metaField.getMetaModel().getFullName(), metaField.getName());
}
public String getSqlType(String type) {
switch (type) {
case "string":
return "varchar";
case "String":
return "varchar";
case "LocalDate":
return "date";
case "LocalDateTime":
return "timestamp";
case "datetime":
return "timestamp";
}
return type;
}
public String getSqlFilters(List<Filter> filterList, List<String> joins, boolean checkJson)
throws AxelorException {
String filters = null;
if (filterList == null) {
return filters;
}
for (Filter filter : filterList) {
StringBuilder parent = new StringBuilder("self");
Object target = getTargetField(parent, filter, joins, checkJson);
if (target == null) {
continue;
}
String[] fields = getSqlField(target, parent.toString(), null);
String field = checkDateTime(fields);
String value =
getParam(filter.getIsParameter(), filter.getValue(), filter.getId(), fields[1]);
String condition = filterCommonService.getCondition(field, filter.getOperator(), value);
if (filters == null) {
filters = condition;
} else {
String opt = filter.getLogicOp() == 0 ? " AND " : " OR ";
filters = filters + opt + condition;
}
}
return filters;
}
private String checkDateTime(String[] fields) {
switch (fields[1]) {
case "LocalDateTime":
return "(cast(to_char("
+ fields[0]
+ ",'yyyy-MM-dd hh24:mi') as timestamp with time zone)) at time zone 'utc'";
}
return fields[0];
}
public String[] getSqlField(Object target, String source, List<String> joins) {
String field = null;
String type = null;
String selection = null;
if (target instanceof MetaField) {
MetaField metaField = (MetaField) target;
field = source + "." + getColumn(metaField);
type = metaField.getTypeName();
try {
selection =
Mapper.of(Class.forName(metaField.getMetaModel().getFullName()))
.getProperty(metaField.getName())
.getSelection();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
MetaJsonField metaJsonField = (MetaJsonField) target;
selection = metaJsonField.getSelection();
String jsonColumn = getColumn(metaJsonField.getModel(), metaJsonField.getModelField());
field =
"cast("
+ source
+ "."
+ jsonColumn
+ "->>'"
+ metaJsonField.getName()
+ "' as "
+ getSqlType(metaJsonField.getType())
+ ")";
type = metaJsonField.getType();
}
log.debug("Selection for field :{} : {}", field, selection);
if (joins != null && !Strings.isNullOrEmpty(selection)) {
int join = joins.size();
joins.add(
"left join meta_select obj" + join + " on (obj" + join + ".name = '" + selection + "')");
join = joins.size();
joins.add(
"left join meta_select_item obj"
+ join
+ " on (obj"
+ join
+ ".select_id = obj"
+ (join - 1)
+ ".id and obj"
+ join
+ ".value = cast("
+ field
+ " as varchar))");
join = joins.size();
joins.add(
"left join meta_translation obj"
+ join
+ " on (obj"
+ join
+ ".message_key = obj"
+ (join - 1)
+ ".title and obj"
+ join
+ ".language = (select language from auth_user where id = :__user__))");
field = "COALESCE(nullif(obj" + join + ".message_value,''), obj" + (join - 1) + ".title)";
}
return new String[] {field, type};
}
private String getParam(boolean isParam, String value, Long filterId, String type) {
if (isParam) {
String sqlType = getSqlType(type);
if (!sqlType.equals(type) || sqlType.equals("date")) {
value = "cast(:param" + filterId + " as " + getSqlType(type) + ")";
} else {
value = ":param" + filterId;
}
}
return value;
}
public String[] getDefaultTarget(String fieldName, String modelName) {
MetaModel targetModel = null;
if (modelName.contains(".")) {
targetModel = metaModelRepo.all().filter("self.fullName = ?1", modelName).fetchOne();
} else {
targetModel = metaModelRepo.findByName(modelName);
}
if (targetModel == null) {
return new String[] {fieldName, null};
}
try {
Mapper mapper = Mapper.of(Class.forName(targetModel.getFullName()));
if (mapper.getNameField() != null) {
return new String[] {
fieldName + "." + mapper.getNameField().getName(),
mapper.getNameField().getJavaType().getSimpleName()
};
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
for (MetaField field : targetModel.getMetaFields()) {
if (field.getName().equals("name")) {
return new String[] {fieldName + ".name", field.getTypeName()};
}
if (field.getName().equals("code")) {
return new String[] {fieldName + ".code", field.getTypeName()};
}
}
return new String[] {fieldName, null};
}
public String[] getDefaultTargetJson(String fieldName, MetaJsonModel targetModel) {
String name = targetModel.getNameField();
if (name == null) {
MetaJsonField nameField =
metaJsonFieldRepo
.all()
.filter("self.name = 'name' and self.jsonModel = ?1", targetModel)
.fetchOne();
if (nameField == null) {
nameField =
metaJsonFieldRepo
.all()
.filter("self.name = 'code' and self.jsonModel = ?1", targetModel)
.fetchOne();
}
if (nameField != null) {
name = nameField.getName();
}
}
return new String[] {fieldName + "." + name, "string"};
}
public Object getTargetField(
StringBuilder parent, Filter filter, List<String> joins, boolean checkJson)
throws AxelorException {
Object target = null;
if (!filter.getIsJson() && filter.getMetaField() != null) {
target =
parseMetaField(filter.getMetaField(), filter.getTargetField(), joins, parent, checkJson);
} else if (checkJson && filter.getMetaJsonField() != null) {
target = parseJsonField(filter.getMetaJsonField(), filter.getTargetField(), joins, parent);
}
return target;
}
public String getTargetType(Object target) {
String targetType = null;
if (target instanceof MetaField) {
MetaField metaField = (MetaField) target;
String relationship = metaField.getRelationship();
if (relationship != null) {
targetType = relationship;
} else {
targetType = metaField.getTypeName();
}
} else if (target instanceof MetaJsonField) {
targetType = ((MetaJsonField) target).getType();
log.debug("Target json type:", targetType);
targetType = Inflector.getInstance().camelize(targetType);
}
log.debug("Target type: {}, field: {}", targetType, target);
return targetType;
}
public Object parseMetaField(
MetaField field, String target, List<String> joins, StringBuilder parent, boolean checkJson)
throws AxelorException {
if (target == null || !target.contains(".")) {
if (field.getRelationship() != null && joins != null) {
target = getDefaultTarget(field.getName(), field.getTypeName())[0];
} else {
return field;
}
}
target = target.substring(target.indexOf(".") + 1);
String targetName = target.contains(".") ? target.substring(0, target.indexOf(".")) : target;
if (field.getRelationship() == null) {
return field;
}
MetaModel model = metaModelRepo.findByName(field.getTypeName());
MetaField subMeta = findMetaField(targetName, model.getFullName());
if (subMeta != null) {
if (joins != null) {
addJoin(field, joins, parent);
}
return parseMetaField(subMeta, target, joins, parent, checkJson);
} else if (checkJson) {
MetaJsonField subJson = findJsonField(targetName, model.getName());
if (subJson != null) {
if (joins != null) {
addJoin(field, joins, parent);
}
return parseJsonField(subJson, target, joins, parent);
}
}
throw new AxelorException(
TraceBackRepository.CATEGORY_MISSING_FIELD,
"No sub field found field: %s model: %s ",
targetName,
model.getFullName());
}
public Object parseJsonField(
MetaJsonField field, String target, List<String> joins, StringBuilder parent)
throws AxelorException {
log.debug("Parse json target: {}", target);
if (target == null || !target.contains(".")) {
if (field.getTargetJsonModel() != null && joins != null) {
target = getDefaultTargetJson(field.getName(), field.getTargetJsonModel())[0];
} else if (field.getTargetModel() != null && joins != null) {
target = getDefaultTarget(field.getName(), field.getTargetModel())[0];
} else {
return field;
}
}
target = target.substring(target.indexOf(".") + 1);
String targetName = target.contains(".") ? target.substring(0, target.indexOf(".")) : target;
if (field.getTargetJsonModel() == null && field.getTargetModel() == null) {
return field;
}
if (field.getTargetJsonModel() != null) {
MetaJsonField subJson =
metaJsonFieldRepo
.all()
.filter(
"self.name = ?1 and self.jsonModel = ?2", targetName, field.getTargetJsonModel())
.fetchOne();
if (subJson != null) {
if (joins != null) {
addJoin(field, joins, parent);
}
return parseJsonField(subJson, target, joins, parent);
}
throw new AxelorException(
TraceBackRepository.CATEGORY_MISSING_FIELD,
"No sub field found model: %s field %s ",
field.getTargetJsonModel().getName(),
targetName);
} else {
MetaField subMeta = findMetaField(targetName, field.getTargetModel());
if (subMeta != null) {
if (joins != null) {
addJoin(field, joins, parent);
}
return parseMetaField(subMeta, target, joins, parent, true);
}
throw new AxelorException(
TraceBackRepository.CATEGORY_MISSING_FIELD,
"No sub field found model: %s field %s ",
field.getTargetModel(),
targetName);
}
}
private MetaField findMetaField(String name, String model) {
return metaFieldRepo
.all()
.filter("self.name = ?1 and self.metaModel.fullName = ?2", name, model)
.fetchOne();
}
private MetaJsonField findJsonField(String name, String model) {
return metaJsonFieldRepo
.all()
.filter("self.name = ?1 and self.model = ?2", name, model)
.fetchOne();
}
private void addJoin(MetaField field, List<String> joins, StringBuilder parent) {
MetaModel metaModel = metaModelRepo.findByName(field.getTypeName());
String parentField = getColumn(field);
joins.add(
"left join "
+ metaModel.getTableName()
+ " "
+ "obj"
+ joins.size()
+ " on ("
+ "obj"
+ joins.size()
+ ".id = "
+ parent.toString()
+ "."
+ parentField
+ ")");
parent.replace(0, parent.length(), "obj" + (joins.size() - 1));
}
private void addJoin(MetaJsonField field, List<String> joins, StringBuilder parent) {
String targetModel = null;
if (field.getTargetModel() != null) {
targetModel = field.getTargetModel();
} else if (field.getTargetJsonModel() != null) {
targetModel = MetaJsonRecord.class.getName();
}
MetaModel metaModel = metaModelRepo.all().filter("self.fullName = ?1", targetModel).fetchOne();
joins.add(
"left join "
+ metaModel.getTableName()
+ " "
+ "obj"
+ joins.size()
+ " on (obj"
+ joins.size()
+ ".id = "
+ "cast("
+ parent
+ "."
+ getColumn(field.getModel(), field.getModelField())
+ "->'"
+ field.getName()
+ "'->>'id' as integer))");
parent.replace(0, parent.length(), "obj" + (joins.size() - 1));
}
}

View File

@ -0,0 +1,289 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.wkf;
import com.axelor.apps.tool.xml.XPathParse;
import com.axelor.auth.db.repo.RoleRepository;
import com.axelor.common.Inflector;
import com.axelor.inject.Beans;
import com.axelor.meta.db.MetaField;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.db.WkfNode;
import com.axelor.studio.db.WkfTransition;
import com.axelor.studio.db.repo.WkfNodeRepository;
import com.axelor.studio.db.repo.WkfRepository;
import com.axelor.studio.db.repo.WkfTransitionRepository;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.io.IOException;
import java.io.StringReader;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* Handles bpmn xml processing of work-flow. Creates/removes work-flow nodes and transitions using
* bpmn xml.
*
* @author axelor
*/
public class WkfDesignerService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
protected static final String WKF_STATUS = "wkfStatus";
protected MetaField statusField = null;
protected String dasherizeModel = null;
protected String modelName = null;
protected Inflector inflector;
protected String defaultStatus = null;
private Set<WkfNode> nodes = new LinkedHashSet<>();
private Set<WkfTransition> transitions = new LinkedHashSet<>();
private Wkf instance;
private List<Integer> nodeSequences;
@Inject protected RoleRepository roleRepo;
@Inject private WkfRepository wkfRepo;
@Inject private WkfService wkfService;
/**
* Parses xml doc to create workflow nodes from it. Sets incoming and outgoing transitions of
* node.
*
* @param doc
*/
public void traverseXMLElement(Document doc) {
nodeSequences = new ArrayList<>();
NodeList list = doc.getElementsByTagName("*");
int nodeCount = 1;
Map<String, WkfNode> nodeMap = getNodeMap();
for (int i = 0; i < list.getLength(); i++) {
Element element = (Element) list.item(i);
if ((!element.getParentNode().getNodeName().equals("process"))
|| element.getNodeName().equals("sequenceFlow")) {
continue;
}
String elementName = element.getTagName();
WkfNode node = nodeMap.get(element.getAttribute("id"));
if (node == null) {
node = new WkfNode();
node.setXmlId(element.getAttribute("id"));
node.setName(element.getAttribute("name"));
node.setTitle(node.getName());
node.setWkf(instance);
while (nodeSequences.contains(nodeCount)) {
nodeCount += 10;
}
node.setSequence(nodeCount);
nodeCount += 10;
if (elementName.equals("startEvent")) node.setNodeType(WkfNodeRepository.START_NODE);
else if (elementName.equals("endEvent")) node.setNodeType(WkfNodeRepository.END_NODE);
} else {
node.setName(element.getAttribute("name"));
nodeMap.remove(node.getXmlId());
}
wkfService.clearNodes(nodeMap.values());
NodeList incomings = element.getElementsByTagName("incoming");
for (int j = 0; j < incomings.getLength(); j++) {
Element incElement = (Element) incomings.item(j);
String innerText = incElement.getTextContent();
for (WkfTransition trn : transitions) {
if (trn.getXmlId().equals(innerText)) {
Set<WkfTransition> existIncomings = node.getIncoming();
if (existIncomings == null) existIncomings = new HashSet<>();
existIncomings.add(trn);
node.setIncoming(existIncomings);
trn.setTarget(node);
}
}
}
NodeList outgoings = element.getElementsByTagName("outgoing");
for (int j = 0; j < outgoings.getLength(); j++) {
Element outElement = (Element) outgoings.item(j);
String innerText = outElement.getTextContent();
for (WkfTransition trn : transitions) {
if (trn.getXmlId().equals(innerText)) {
Set<WkfTransition> existOutgoings = node.getOutgoing();
if (existOutgoings == null) existOutgoings = new HashSet<>();
existOutgoings.add(trn);
node.setOutgoing(existOutgoings);
trn.setSource(node);
}
}
}
nodes.add(node);
}
}
private Map<String, WkfNode> getNodeMap() {
WkfNodeRepository wkfNodeRepository = Beans.get(WkfNodeRepository.class);
Map<String, WkfNode> nodeMap = new HashMap<>();
if (instance != null) {
List<WkfNode> wkfNodes =
wkfNodeRepository.all().filter("self.wkf.id = ?1", instance.getId()).fetch();
for (WkfNode node : wkfNodes) {
nodeMap.put(node.getXmlId(), node);
nodeSequences.add(node.getSequence());
}
}
return nodeMap;
}
private Map<String, WkfTransition> getTransitionMap() {
WkfTransitionRepository wkfTransitionRepo = Beans.get(WkfTransitionRepository.class);
Map<String, WkfTransition> transitionMap = new HashMap<>();
if (instance != null) {
List<WkfTransition> wkfTransitions =
wkfTransitionRepo.all().filter("self.wkf.id = ?1", instance.getId()).fetch();
for (WkfTransition transition : wkfTransitions) {
transitionMap.put(transition.getXmlId(), transition);
}
}
return transitionMap;
}
/**
* Fetches bpmn xml from workflow. Generates document from xml using dom parser. Generates
* transitions from dom document and calls method to create nodes.
*
* @param instance Workflow instance
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
* @throws Exception
*/
@Transactional(rollbackOn = {Exception.class})
public Wkf processXml(Wkf instance)
throws ParserConfigurationException, SAXException, IOException {
this.instance = instance;
String bpmnXml = instance.getBpmnXml();
if (bpmnXml != null) {
DocumentBuilder db =
Beans.get(XPathParse.class).getDocumentBuilderFactory().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(bpmnXml));
Document doc = db.parse(is);
NodeList list;
Map<String, WkfTransition> transitionMap = getTransitionMap();
list = doc.getElementsByTagName("sequenceFlow");
for (int i = 0; i < list.getLength(); i++) {
Element element = (Element) list.item(i);
WkfTransition transition = transitionMap.get(element.getAttribute("id"));
if (transition == null) {
transition = new WkfTransition();
transition.setXmlId(element.getAttribute("id"));
transition.setName(element.getAttribute("name"));
transition.setWkf(instance);
log.debug(
"New transition : {}, Version: {}", transition.getName(), transition.getVersion());
} else {
transition.setName(element.getAttribute("name"));
}
transitions.add(transition);
}
List<WkfNode> allRemoveNodes = instance.getNodes();
if (!allRemoveNodes.isEmpty()) {
for (WkfNode tempNode : allRemoveNodes) {
tempNode.getIncoming().clear();
tempNode.getOutgoing().clear();
}
}
instance.getTransitions().clear();
for (WkfTransition transition : transitions) {
if (transition.getVersion() == null) {
transition.setIsButton(true);
transition.setButtonTitle(transition.getName());
transition.setColSpan(transition.getColSpan());
}
instance.addTransition(transition);
}
traverseXMLElement(doc);
instance.getNodes().clear();
for (WkfNode node : nodes) {
instance.addNode(node);
}
}
return wkfRepo.save(instance);
}
}

View File

@ -0,0 +1,267 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.wkf;
import com.axelor.auth.db.Permission;
import com.axelor.auth.db.Role;
import com.axelor.auth.db.repo.PermissionRepository;
import com.axelor.meta.db.MetaAction;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaModel;
import com.axelor.meta.db.MetaSelect;
import com.axelor.meta.db.MetaSelectItem;
import com.axelor.meta.db.repo.MetaModelRepository;
import com.axelor.meta.db.repo.MetaSelectRepository;
import com.axelor.studio.db.WkfNode;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service handle processing of WkfNode. From wkfNode it generates status field for related model.
* It will generate field's selection according to nodes and add field in related ViewBuilder.
* Creates permissions for status related with node and assign to roles selected in node. Add status
* menus(MenuBuilder) according to menu details in WkfNode.
*
* @author axelor
*/
class WkfNodeService {
private WkfService wkfService;
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private List<String[]> nodeActions;
@Inject private MetaModelRepository metaModelRepo;
@Inject private PermissionRepository permissionRepo;
@Inject private MetaSelectRepository metaSelectRepo;
@Inject
protected WkfNodeService(WkfService wkfService) {
this.wkfService = wkfService;
}
/**
* Root method to access the service. It start processing of WkfNode and call different methods
* for that.
*/
protected List<String[]> process() {
MetaJsonField statusField = wkfService.workflow.getStatusField();
MetaSelect metaSelect = addMetaSelect(statusField);
nodeActions = new ArrayList<String[]>();
String defaultValue = processNodes(metaSelect, statusField);
statusField.setDefaultValue(defaultValue);
return nodeActions;
}
/**
* Add MetaSelect in statusField, if MetaSelect of field is null.
*
* @param statusField MetaField to update with MetaSelect.
* @return MetaSelect of statusField.
*/
@Transactional
public MetaSelect addMetaSelect(MetaJsonField statusField) {
String selectName = wkfService.getSelectName();
MetaSelect metaSelect = metaSelectRepo.findByName(selectName);
if (metaSelect == null) {
metaSelect = new MetaSelect(selectName);
metaSelect.setIsCustom(true);
metaSelect.setAppBuilder(wkfService.workflow.getAppBuilder());
metaSelect = metaSelectRepo.save(metaSelect);
}
if (metaSelect.getItems() == null) {
metaSelect.setItems(new ArrayList<MetaSelectItem>());
}
metaSelect.clearItems();
return metaSelect;
}
/**
* Method remove old options from metaSelect options if not found in nodeList.
*
* @param metaSelect MetaSelect to process.
* @param nodeList WkfNode list to compare.
* @return Updated MetaSelect.
*/
private MetaSelect removeOldOptions(MetaSelect metaSelect, List<WkfNode> nodeList) {
log.debug("Cleaning meta select: {}", metaSelect.getName());
List<MetaSelectItem> itemsToRemove = new ArrayList<MetaSelectItem>();
Iterator<MetaSelectItem> itemIter = metaSelect.getItems().iterator();
while (itemIter.hasNext()) {
MetaSelectItem item = itemIter.next();
boolean found = false;
for (WkfNode node : nodeList) {
if (item.getValue().equals(node.getSequence().toString())) {
found = true;
break;
}
}
if (!found) {
itemsToRemove.add(item);
itemIter.remove();
}
}
return metaSelect;
}
/**
* Add or update items in MetaSelect according to WkfNodes.
*
* @param metaSelect MetaSelect to update.
* @return Return first item as default value for wkfStatus field.
*/
private String processNodes(MetaSelect metaSelect, MetaJsonField statusField) {
List<WkfNode> nodeList = wkfService.workflow.getNodes();
String defaultValue = null;
removeOldOptions(metaSelect, nodeList);
Collections.sort(
nodeList,
(WkfNode node1, WkfNode node2) -> node1.getSequence().compareTo(node2.getSequence()));
for (WkfNode node : nodeList) {
log.debug("Procesing node: {}", node.getName());
String option = node.getSequence().toString();
MetaSelectItem metaSelectItem = getMetaSelectItem(metaSelect, option);
if (metaSelectItem == null) {
metaSelectItem = new MetaSelectItem();
metaSelectItem.setValue(option);
metaSelect.addItem(metaSelectItem);
}
metaSelectItem.setTitle(node.getTitle());
metaSelectItem.setOrder(node.getSequence());
if (defaultValue == null) {
defaultValue = metaSelectItem.getValue();
log.debug("Default value set: {}", defaultValue);
}
List<String[]> actions = new ArrayList<String[]>();
if (node.getMetaActionSet() != null) {
Stream<MetaAction> actionStream =
node.getMetaActionSet().stream().sorted(Comparator.comparing(MetaAction::getSequence));
actionStream.forEach(metaAction -> actions.add(new String[] {metaAction.getName()}));
}
if (!actions.isEmpty()) {
String name = getActionName(node.getName());
String value = node.getSequence().toString();
if (statusField.getType().equals("string")) {
value = "'" + value + "'";
}
String condition = statusField.getName() + " == " + value;
if (!wkfService.workflow.getIsJson()) {
condition = "$" + wkfService.workflow.getJsonField() + "." + condition;
}
nodeActions.add(new String[] {name, condition});
this.wkfService.updateActionGroup(name, actions);
}
}
return defaultValue;
}
public String getActionName(String node) {
String name = wkfService.inflector.simplify(node);
name = name.toLowerCase().replace(" ", "-");
name = "action-group-" + wkfService.wkfId + "-" + name;
return name;
}
/**
* Method to save MetaModel
*
* @param metaModel Model to save.
* @return Saved MetaModel
*/
@Transactional
public MetaModel saveModel(MetaModel metaModel) {
return metaModelRepo.save(metaModel);
}
/**
* Fetch MetaSelectItem from MetaSelect according to option.
*
* @param metaSelect MetaSelect to search for item.
* @param option Option to search.
* @return MetaSelctItem found or null.
*/
private MetaSelectItem getMetaSelectItem(MetaSelect metaSelect, String option) {
for (MetaSelectItem selectItem : metaSelect.getItems()) {
if (selectItem.getValue().equals(option)) {
return selectItem;
}
}
return null;
}
/**
* Method remove old permission according to name of permission.
*
* @param name Permission name.
*/
@Transactional
public void clearOldPermissions(String name) {
Permission permission = permissionRepo.findByName(name);
if (permission != null) {
List<Role> oldRoleList =
wkfService.roleRepo.all().filter("self.permissions.id = ?1", permission.getId()).fetch();
for (Role role : oldRoleList) {
role.removePermission(permission);
wkfService.roleRepo.save(role);
}
}
}
}

View File

@ -0,0 +1,531 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.wkf;
import com.axelor.auth.db.repo.RoleRepository;
import com.axelor.common.Inflector;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaJsonModel;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.meta.db.MetaSelect;
import com.axelor.meta.db.repo.MetaJsonFieldRepository;
import com.axelor.meta.db.repo.MetaJsonModelRepository;
import com.axelor.meta.db.repo.MetaSelectRepository;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.actions.ActionGroup;
import com.axelor.meta.schema.actions.ActionGroup.ActionItem;
import com.axelor.meta.schema.actions.ActionMethod;
import com.axelor.meta.schema.actions.ActionMethod.Call;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.db.WkfNode;
import com.axelor.studio.db.repo.WkfRepository;
import com.axelor.studio.service.StudioMetaService;
import com.axelor.studio.service.filter.FilterGroovyService;
import com.google.common.base.Joiner;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service class handle workflow processing. It updated related models/views according to update in
* workflow. Also remove effects of workflow it some workflow deleted. Call node and transition
* service for further processing.
*
* @author axelor
*/
public class WkfService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
protected Wkf workflow = null;
protected String wkfId = null;
protected Inflector inflector;
protected Integer wkfSequence = 0;
protected String applyCondition = null;
protected String trackingAction = null;
@Inject protected RoleRepository roleRepo;
@Inject private WkfNodeService nodeService;
@Inject private WkfTransitionService transitionService;
@Inject private StudioMetaService metaService;
@Inject private MetaJsonFieldRepository jsonFieldRepo;
@Inject private MetaJsonModelRepository jsonModelRepo;
@Inject private MetaSelectRepository metaSelectRepo;
@Inject private FilterGroovyService filterGroovyService;
@Inject private WkfRepository wkfRepository;
/**
* Method to process workflow. It calls node and transition service for nodes and transitions
* linked with workflow.
*
* @param wkf Worklfow to process.
* @return Exception string if any issue in processing else null.
*/
public String process(Wkf wkf) {
try {
initService(wkf);
createTrackingAction();
setWkfSequence();
setView();
List<String[]> actions = nodeService.process();
actions.addAll(transitionService.process());
actions.add(new String[] {"save"});
actions.add(new String[] {trackingAction});
updateActionGroup("action-group-" + wkfId, actions);
MetaStore.clear();
} catch (Exception e) {
e.printStackTrace();
return e.toString();
}
return null;
}
private void initService(Wkf wkf) {
workflow = wkf;
inflector = Inflector.getInstance();
wkfId = "wkf" + wkf.getId().toString();
trackingAction = "action-method-wkf-track-" + wkfId;
}
private void setView() {
// clearOldStatusField();
MetaJsonField status = workflow.getStatusField();
applyCondition =
filterGroovyService.getGroovyFilters(workflow.getConditions(), workflow.getJsonField());
MetaJsonField panel = getJsonField(wkfId + "Panel", "panel");
panel.setSequence(wkfSequence - 49);
panel.setVisibleInGrid(false);
panel.setIsWkf(true);
panel.setWidgetAttrs("{\"colSpan\": \"12\"}");
saveJsonField(panel);
status.setSequence(wkfSequence - 48);
status.setSelection(getSelectName());
status.setWidget(null);
status.setIsWkf(true);
status.setReadonly(true);
status.setShowIf(applyCondition);
status.setWidgetAttrs("{\"colSpan\": \"10\"}");
if (workflow.getDisplayTypeSelect() == 0) {
status.setWidget("NavSelect");
}
saveJsonField(workflow.getStatusField());
MetaJsonField trackFlow = getJsonField(wkfId + "TrackFlow", "button");
trackFlow.setSequence(wkfSequence - 47);
trackFlow.setTitle("Track flow");
trackFlow.setWidgetAttrs("{\"colSpan\": \"2\"}");
trackFlow.setOnClick(WkfTrackingService.ACTION_OPEN_TRACK);
trackFlow.setIsWkf(true);
trackFlow.setVisibleInGrid(false);
trackFlow.setHidden(!workflow.getIsTrackFlow());
saveJsonField(trackFlow);
MetaJsonField wkfEnd = getJsonField(wkfId + "Separator", "separator");
wkfEnd.setSequence(wkfSequence);
wkfEnd.setVisibleInGrid(false);
wkfEnd.setIsWkf(true);
wkfEnd.setWidgetAttrs("{\"colSpan\": \"12\"}");
saveJsonField(panel);
// setTrackOnSave(workflow, false);
}
@Transactional
public void clearOldStatusField() {
MetaJsonField field = null;
if (workflow.getIsJson()) {
field =
jsonFieldRepo
.all()
.filter(
"self.isWkf = true "
+ "and self.jsonModel.name = :workflowModel "
+ "and self.type in ('string','integer')")
.bind("workflowModel", workflow.getModel())
.fetchOne();
} else {
field =
jsonFieldRepo
.all()
.filter(
"self.isWkf = true "
+ "and self.model = :workflowModel "
+ "and self.modelField = :workflowJsonField "
+ "and self.type in ('string','integer')")
.bind("workflowModel", workflow.getModel())
.bind("workflowJsonField", workflow.getJsonField())
.fetchOne();
}
if (field != null) {
if (field.getSelection() != null) {
log.debug("Cleaning old status field: {}", field);
MetaSelect oldSelect = metaSelectRepo.findByName(field.getSelection());
if (oldSelect != null) {
log.debug("Removing old wkf selection: {}", oldSelect);
metaSelectRepo.remove(oldSelect);
}
}
field.setIsWkf(false);
field.setSelection(null);
field.setSequence(0);
field.setReadonly(false);
jsonFieldRepo.save(field);
}
}
public String getSelectName() {
if (workflow != null) {
MetaJsonField wkfField = workflow.getStatusField();
String selectName = "wkf." + inflector.dasherize(workflow.getName()).replace("_", ".");
selectName += "." + inflector.dasherize(wkfField.getName()).replace("_", ".") + ".select";
return selectName;
}
return null;
}
/**
* Update xml of MetaAction with xml string passed. It creates new MetaAction if no MetaAction not
* found.
*
* @param actionName Name of MetaAction to update.
* @param actionType Type of MetaAction.
* @param xml Xml to update in MetaAction.
*/
protected ActionGroup updateActionGroup(String name, List<String[]> actions) {
ActionGroup actionGroup = new ActionGroup();
actionGroup.setName(name);
List<ActionItem> actionItems = new ArrayList<>();
for (String[] action : actions) {
ActionItem actionItem = new ActionItem();
actionItem.setName(action[0]);
if (action.length > 1) {
actionItem.setCondition(action[1]);
}
actionItems.add(actionItem);
}
actionGroup.setActions(actionItems);
String xml = XMLViews.toXml(actionGroup, true);
metaService.updateMetaAction(name, "action-group", xml, null);
return actionGroup;
}
public MetaJsonField getJsonField(String name, String type) {
MetaJsonField field = null;
if (workflow.getIsJson()) {
field =
jsonFieldRepo
.all()
.filter(
"self.isWkf = true "
+ "and self.jsonModel.name = ?1 "
+ "and self.name = ?2 and self.type = ?3",
workflow.getModel(),
name,
type)
.fetchOne();
if (field == null) {
field = new MetaJsonField();
field.setModel(MetaJsonRecord.class.getName());
field.setModelField("attrs");
field.setJsonModel(jsonModelRepo.findByName(workflow.getModel()));
}
} else {
field =
jsonFieldRepo
.all()
.filter(
"self.isWkf = true "
+ "and self.model = :workflowModel "
+ "and self.modelField = :workflowJsonField "
+ "and self.name = :name and self.type = :type")
.bind("workflowModel", workflow.getModel())
.bind("workflowJsonField", workflow.getJsonField())
.bind("name", name)
.bind("type", type)
.fetchOne();
log.debug(
"Searching json field with model: {}, field: {}, name: {}, type: {}",
workflow.getModel(),
workflow.getJsonField(),
name,
type);
if (field == null) {
field = new MetaJsonField();
field.setModel(workflow.getModel());
field.setModelField(workflow.getJsonField());
field.setName(name);
}
}
field.setType(type);
field.setName(name);
field.setIsWkf(true);
field.setShowIf(applyCondition);
return saveJsonField(field);
}
@Transactional
public MetaJsonField saveJsonField(MetaJsonField jsonField) {
return jsonFieldRepo.save(jsonField);
}
@Transactional
public void clearWkf(Wkf wkf) {
initService(wkf);
String actions = "action-" + wkfId + ",action-group" + wkfId;
actions = clearFields(wkf, actions);
StringBuilder builder = new StringBuilder(actions);
for (WkfNode node : wkf.getNodes()) {
if (!node.getMetaActionSet().isEmpty()) {
builder.append("," + nodeService.getActionName(node.getName()));
}
}
builder.append(trackingAction);
actions = builder.toString();
metaService.removeMetaActions(actions);
String select = getSelectName();
MetaSelect metaSelect = metaSelectRepo.findByName(select);
if (metaSelect != null) {
metaSelectRepo.remove(metaSelect);
}
MetaJsonField status = wkf.getStatusField();
status.setWidget(null);
status.setSelection(null);
status.setWidgetAttrs(null);
saveJsonField(status);
// setTrackOnSave(wkf, true);
}
private String clearFields(Wkf wkf, String actions) {
List<MetaJsonField> fields = getFields(wkf);
StringBuilder builder = new StringBuilder(actions);
for (MetaJsonField field : fields) {
if (field.getIsWkf() && !field.equals(wkf.getStatusField())) {
if (field.getOnClick() != null) {
builder.append("," + field.getOnClick());
}
jsonFieldRepo.remove(field);
}
}
return builder.toString();
}
private List<MetaJsonField> getFields(Wkf wkf) {
List<MetaJsonField> fields;
String query = "self.isWkf = true and self.name LIKE '" + wkfId + "%' and ";
if (wkf.getIsJson()) {
fields =
jsonFieldRepo.all().filter(query + "self.jsonModel.name = ?1", wkf.getModel()).fetch();
} else {
fields =
jsonFieldRepo
.all()
.filter(
query + "self.model = ?1 and self.modelField = ?2",
wkf.getModel(),
wkf.getJsonField())
.fetch();
}
return fields;
}
@Transactional
public String clearOldButtons(List<String> skipList) {
log.debug("Cleaning old buttons. Skip list: {}", skipList);
if (skipList.isEmpty()) {
return null;
}
skipList.add(wkfId + "TrackFlow");
ArrayList<String> actions = new ArrayList<>();
List<MetaJsonField> fields = null;
if (workflow.getIsJson()) {
fields =
jsonFieldRepo
.all()
.filter(
"self.type = 'button' "
+ "and self.jsonModel.name = ?1 "
+ "and self.isWkf = true "
+ "and self.name not in (?2) "
+ "and self.name LIKE ?3",
workflow.getModel(),
skipList,
wkfId + "%")
.fetch();
} else {
fields =
jsonFieldRepo
.all()
.filter(
"self.type = 'button' "
+ "and self.model = ?1 "
+ "and self.modelField = ?2 "
+ "and self.name not in (?3) "
+ "and self.name LIKE ?4",
workflow.getModel(),
workflow.getJsonField(),
skipList,
wkfId + "%")
.fetch();
}
log.debug("Total Buttons to remove: {}", fields.size());
Iterator<MetaJsonField> buttons = fields.iterator();
MetaJsonModel jsonModel = jsonModelRepo.findByName(workflow.getModel());
while (buttons.hasNext()) {
MetaJsonField button = buttons.next();
String onClick = button.getOnClick();
log.debug("Removing button : {}, onClick: {}", button.getName(), onClick);
if (onClick != null) {
for (String action : onClick.split(",")) {
if (!action.equals("action-group" + wkfId)) {
actions.add(action);
}
}
}
buttons.remove();
jsonModel.getFields().remove(button);
jsonFieldRepo.remove(button);
}
return Joiner.on(",").join(actions);
}
public void clearNodes(Collection<WkfNode> nodes) {
List<String> actions = new ArrayList<>();
for (WkfNode node : nodes) {
if (workflow == null) {
workflow = node.getWkf();
inflector = Inflector.getInstance();
}
if (!node.getMetaActionSet().isEmpty()) {
actions.add(nodeService.getActionName(node.getName()));
}
}
metaService.removeMetaActions(Joiner.on(",").join(actions));
}
// @Transactional
// public void setTrackOnSave(Wkf wkf, boolean remove) {
// if (wkf.getIsJson()) {
// MetaJsonModel jsonModel = jsonModelRepo.findByName(wkf.getModel());
// if (jsonModel != null) {
// String onSave =
// metaService.updateAction(
// jsonModel.getOnSave(), "save," + trackingAction, remove);
// jsonModel.setOnSave(onSave);
// jsonModelRepo.save(jsonModel);
// }
// }
// }
@Transactional
public void createTrackingAction() {
ActionMethod actionMethod = new ActionMethod();
actionMethod.setName(trackingAction);
Call call = new Call();
call.setMethod("track(" + workflow.getId() + "," + "__self__)");
call.setController("com.axelor.studio.service.wkf.WkfTrackingService");
actionMethod.setCall(call);
String xml = XMLViews.toXml(actionMethod, true);
metaService.updateMetaAction(trackingAction, "action-method", xml, null);
}
@Transactional
public void setWkfSequence() {
Wkf wkf =
wkfRepository
.all()
.filter("self.model = ?1", workflow.getModel())
.order("wkfSequence")
.fetchOne();
if (wkf.getId() != workflow.getId() && workflow.getWkfSequence() == 0) {
workflow.setWkfSequence(wkf.getWkfSequence() - 50);
wkfRepository.save(workflow);
} else if (workflow.getWkfSequence() == 0) {
workflow.setWkfSequence(-1);
wkfRepository.save(workflow);
}
wkfSequence = workflow.getWkfSequence();
}
}

View File

@ -0,0 +1,289 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.wkf;
import com.axelor.db.EntityHelper;
import com.axelor.db.Model;
import com.axelor.meta.CallMethod;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaJsonRecord;
import com.axelor.meta.schema.views.Selection.Option;
import com.axelor.rpc.Context;
import com.axelor.rpc.JsonContext;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.db.WkfTracking;
import com.axelor.studio.db.WkfTrackingLine;
import com.axelor.studio.db.WkfTrackingTime;
import com.axelor.studio.db.WkfTrackingTotal;
import com.axelor.studio.db.repo.WkfRepository;
import com.axelor.studio.db.repo.WkfTrackingLineRepository;
import com.axelor.studio.db.repo.WkfTrackingRepository;
import com.axelor.studio.db.repo.WkfTrackingTimeRepository;
import com.axelor.studio.db.repo.WkfTrackingTotalRepository;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.lang.invoke.MethodHandles;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import javax.script.SimpleBindings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service handle tracking of workflow instance for particular record. Creates WkfTracking,
* WkfTrackingLine, WkfTrackingTime and WkfTrackingTotal records.
*
* @author axelor
*/
public class WkfTrackingService {
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String ACTION_TRACK = "action-method-wkf-track";
public static final String ACTION_OPEN_TRACK = "action-wkf-open-wkf-tracking";
@Inject private WkfRepository wkfRepo;
@Inject private WkfTrackingRepository wkfTrackingRepo;
@Inject private WkfTrackingLineRepository trackingLineRepo;
@Inject private WkfTrackingTotalRepository trackingTotalRepo;
@Inject private WkfTrackingTimeRepository trackingTimeRepo;
private BigDecimal durationHrs;
private String oldStatus;
/**
* Root method to access the service. It creates WkfTracking record. WkfTracking is linked with
* record of model and workflow of model.
*
* @param model Model having workflow.
* @param modelId Record id of model to track.
* @param status Current wkfStatus of record.
* @throws ClassNotFoundException
*/
@CallMethod
public void track(Long wkfId, Object object) {
if (object != null) {
SimpleBindings ctx = null;
object = EntityHelper.getEntity(object);
Model model = (Model) object;
if (object instanceof MetaJsonRecord) {
log.debug("Meta json record context");
MetaJsonRecord metaJsonRecord = (MetaJsonRecord) object;
log.debug(
"Json id: {}, Json model: {}", metaJsonRecord.getId(), metaJsonRecord.getJsonModel());
ctx = new JsonContext((MetaJsonRecord) object);
ctx.put("id", metaJsonRecord.getId());
ctx.put("jsonModel", metaJsonRecord.getJsonModel());
} else {
ctx = new Context(model.getId(), object.getClass());
}
ctx.put("wkfId", wkfId);
WkfTracking wkfTracking = getWorkflowTracking(ctx, object.getClass().getName());
if (wkfTracking == null) {
return;
}
MetaJsonField wkfField = wkfTracking.getWkf().getStatusField();
Object status = null;
status = ctx.get(wkfField.getName());
log.debug("Status value: {}", status);
if (status == null) {
return;
}
Option item = MetaStore.getSelectionItem(wkfField.getSelection(), status.toString());
log.debug("Fetching option {} from selection {}", status, wkfField.getSelection());
if (item == null) {
return;
}
durationHrs = BigDecimal.ZERO;
WkfTrackingLine trackingLine = updateTrackingLine(wkfTracking, item.getTitle());
if (trackingLine != null) {
updateTrackingTotal(wkfTracking, item.getTitle());
updateTrackingTime(wkfTracking, item.getTitle());
}
}
}
/**
* Method find or create WkfTracking for model record.
*
* @param model Model of record.
* @param modelId Id of record.
* @return WkfTracking instance created/found.s
*/
@Transactional
public WkfTracking getWorkflowTracking(SimpleBindings ctx, String model) {
String jsonModel = (String) ctx.get("jsonModel");
log.debug("Context json model: {}", jsonModel);
if (jsonModel != null) {
model = jsonModel;
}
Wkf wkf = wkfRepo.find((Long) ctx.get("wkfId"));
WkfTracking wkfTracking =
wkfTrackingRepo
.all()
.filter(
"self.wkf = ?1 and self.recordModel = ?2 and self.recordId = ?3",
wkf,
model,
ctx.get("id"))
.fetchOne();
if (wkfTracking == null) {
wkfTracking = new WkfTracking();
wkfTracking.setWkf(wkf);
wkfTracking.setRecordModel(model);
wkfTracking.setRecordId((Long) ctx.get("id"));
wkfTracking = wkfTrackingRepo.save(wkfTracking);
}
return wkfTracking;
}
/**
* Method add new WkfTrackingLine in WkfTracking for given status if that status is not last
* status added.
*
* @param wkfTracking WkfTracking to update with new line.
* @param status Status to check for update.
* @return WkfTrackingLine created or return null if status not changed.
*/
@Transactional
public WkfTrackingLine updateTrackingLine(WkfTracking wkfTracking, String status) {
WkfTrackingLine trackingLine =
trackingLineRepo.all().filter("self.wkfTracking = ?1", wkfTracking).fetchOne();
if (trackingLine == null || !trackingLine.getStatus().equals(status)) {
LocalDateTime now = LocalDateTime.now();
if (trackingLine != null) {
oldStatus = trackingLine.getStatus();
LocalDateTime lastUpdated = trackingLine.getCreatedOn();
long minutes = Duration.between(lastUpdated, now).toMinutes();
log.debug("Minutes between {} and {} : {}", lastUpdated, now, minutes);
durationHrs = new BigDecimal(minutes).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP);
log.debug("Hours between {} and {} : {}", lastUpdated, now, durationHrs);
trackingLine.setTimeSpent(durationHrs);
trackingLineRepo.save(trackingLine);
}
trackingLine = new WkfTrackingLine();
trackingLine.setWkfTracking(wkfTracking);
trackingLine.setStatus(status);
trackingLine.setWkfTracking(wkfTracking);
return trackingLineRepo.save(trackingLine);
}
return null;
}
/**
* Update o2m to WkfTrackingTotal in WkfTracking. Create or Update WkfTrackingTotal for given
* status with updated count of status.
*
* @param wkfTracking WkfTracking to update for WkfTrackingTotal.
* @param status Status to check for total update.
*/
@Transactional
public void updateTrackingTotal(WkfTracking wkfTracking, String status) {
WkfTrackingTotal trackingTotal =
trackingTotalRepo
.all()
.filter("self.wkfTracking = :wkfTracking and self.status = :status")
.bind("wkfTracking", wkfTracking)
.bind("status", status)
.fetchOne();
if (trackingTotal == null) {
trackingTotal = new WkfTrackingTotal();
trackingTotal.setWkfTracking(wkfTracking);
trackingTotal.setTotalCount(0);
trackingTotal.setStatus(status);
}
trackingTotal.setTotalCount(trackingTotal.getTotalCount() + 1);
trackingTotalRepo.save(trackingTotal);
}
/**
* This method create or update WkfTrackingTime record for given WkfTracking and status. For
* existing WkfTrackingTime it update total time in days and hours.
*
* @param wkfTracking WkfTracking to update for WkfTrackingTime.
* @param status Status to check for WkfTrackingTime.
*/
@Transactional
public void updateTrackingTime(WkfTracking wkfTracking, String status) {
WkfTrackingTime trackingTime =
trackingTimeRepo
.all()
.filter("self.wkfTracking = ?1 and self.status = ?2", wkfTracking, oldStatus)
.fetchOne();
if (trackingTime != null) {
BigDecimal days = durationHrs.divide(new BigDecimal(24), 2, RoundingMode.HALF_UP);
BigDecimal totalTimeDays = trackingTime.getTotalTimeDays().add(days);
trackingTime.setTotalTimeDays(totalTimeDays);
BigDecimal totalTimeHrs = trackingTime.getTotalTimeHours().add(durationHrs);
trackingTime.setTotalTimeHours(totalTimeHrs);
trackingTimeRepo.save(trackingTime);
}
trackingTime =
trackingTimeRepo
.all()
.filter("self.wkfTracking = ?1 and self.status = ?2", wkfTracking, status)
.fetchOne();
if (trackingTime == null) {
trackingTime = new WkfTrackingTime();
trackingTime.setWkfTracking(wkfTracking);
trackingTime.setStatus(status);
trackingTimeRepo.save(trackingTime);
}
}
}

View File

@ -0,0 +1,392 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.service.wkf;
import com.axelor.auth.db.Role;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.MetaPermission;
import com.axelor.meta.db.MetaPermissionRule;
import com.axelor.meta.db.repo.MetaPermissionRepository;
import com.axelor.meta.loader.XMLViews;
import com.axelor.meta.schema.actions.ActionAttrs;
import com.axelor.meta.schema.actions.ActionAttrs.Attribute;
import com.axelor.meta.schema.actions.ActionValidate;
import com.axelor.meta.schema.actions.ActionValidate.Alert;
import com.axelor.meta.schema.actions.ActionValidate.Info;
import com.axelor.meta.schema.actions.ActionValidate.Notify;
import com.axelor.meta.schema.actions.ActionValidate.Validator;
import com.axelor.studio.db.Filter;
import com.axelor.studio.db.WkfTransition;
import com.axelor.studio.service.StudioMetaService;
import com.axelor.studio.service.filter.FilterGroovyService;
import com.google.common.base.Joiner;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service class handle processing of WkfTransition. It creates buttons and actions from
* WkfTransition to change the status.
*
* @author axelor
*/
class WkfTransitionService {
private WkfService wkfService;
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private List<String> wkfButtonNames;
@Inject private MetaPermissionRepository metaPermissionRepo;
@Inject private FilterGroovyService filterGroovyService;
@Inject private StudioMetaService metaService;
@Inject
protected WkfTransitionService(WkfService wkfService) {
this.wkfService = wkfService;
}
/**
* Root method to access the service. Method call different method to process transition. Create
* wkf action that call on save of model to update status. It save all changes to ViewBuilder
* linked with Workflow.
*/
protected List<String[]> process() {
log.debug("Processing transitions");
List<String[]> actions = new ArrayList<String[]>();
String action = "action-" + wkfService.wkfId;
wkfButtonNames = new ArrayList<String>();
List<ActionAttrs.Attribute> fields = proccessTransitions();
if (!fields.isEmpty()) {
String xml = getActionXML(action, fields);
metaService.updateMetaAction(action, "action-attrs", xml, null);
actions.add(new String[] {action});
} else {
metaService.removeMetaActions(action);
}
String actionsToRemove = wkfService.clearOldButtons(wkfButtonNames);
metaService.removeMetaActions(actionsToRemove);
return actions;
}
/**
* Method process each WkfTransition and create RecordField. RecordField contains status and
* condition to assign the status. Based on record fields wkf action will be created. It also add
* button for transition if transition executed based on button.
*
* @return List of RecordField
*/
private List<ActionAttrs.Attribute> proccessTransitions() {
List<ActionAttrs.Attribute> fields = new ArrayList<ActionAttrs.Attribute>();
Integer buttonSeq = wkfService.wkfSequence - 46;
for (WkfTransition transition : wkfService.workflow.getTransitions()) {
MetaJsonField status = wkfService.workflow.getStatusField();
String condition =
status.getName() + " == " + getTyped(transition.getSource().getSequence(), status);
log.debug(
"Processing transition : {}, isButton: {}",
transition.getName(),
transition.getIsButton());
String filters = getFilters(transition.getConditions());
if (filters != null) {
condition += " && (" + filters + ")";
}
if (wkfService.applyCondition != null) {
condition += " && " + wkfService.applyCondition;
}
if (transition.getIsButton()) {
buttonSeq++;
addButton(transition, condition, buttonSeq);
continue;
}
log.debug("Conditions : {}", transition.getConditions());
ActionAttrs.Attribute attrs = new ActionAttrs.Attribute();
attrs.setName("value");
attrs.setFieldName(status.getName());
attrs.setCondition(condition);
attrs.setExpression("eval:" + getTyped(transition.getTarget().getSequence(), status));
fields.add(attrs);
}
return fields;
}
private String getFilters(List<Filter> filterList) {
String jsonField =
wkfService.workflow.getIsJson() ? null : "$" + wkfService.workflow.getJsonField();
if (jsonField != null && jsonField.equals("$attrs")) {
jsonField = null;
}
String filters = filterGroovyService.getGroovyFilters(filterList, jsonField);
log.debug("Filters : {}", filters);
return filters;
}
private String getTyped(Integer value, MetaJsonField status) {
String typeName = status.getType();
if (typeName.equals("integer")) {
return value.toString();
}
return "'" + value + "'";
}
/**
* Create toolbar ViewButton in ViewBuilder from WkfTransition. Method called if WkfTransition is
* based on button.
*
* @param viewBuilder ViewBuilder to update.
* @param transition WkfTransition to process.
* @param condition Condition to show button
* @param sequence Sequence of button to add in toolbar.
*/
private void addButton(WkfTransition transition, String condition, Integer sequence) {
// String source = transition.getSource().getName();
String title = transition.getButtonTitle();
// String name = wkfService.inflector.camelize(source + "-" + title, true);
// FIXME:Have to check if its working with import export of workflow.
String name = wkfService.wkfId + "Transition" + transition.getId();
if (name.equals("save") || name.equals("cancel") || name.equals("back")) {
name = "wkf" + name;
}
wkfButtonNames.add(name);
MetaJsonField button = wkfService.getJsonField(name, "button");
button.setTitle(title);
button.setShowIf(condition);
button.setSequence(sequence);
button.setVisibleInGrid(false);
button.setIsWkf(true);
button.setWidgetAttrs("{\"colSpan\": \"" + transition.getColSpan() + "\"}");
button.setOnClick(addButtonActions(transition, name));
if (transition.getRoleSet() != null) {
Set<Role> buttonRoles = new HashSet<>();
buttonRoles.addAll(transition.getRoleSet());
button.setRoles(buttonRoles);
}
log.debug("Adding button : {}", button.getName());
wkfService.saveJsonField(button);
// String permName = this.wkfService.moduleName + "."
// + wkfService.dasherizeModel.replace("-", ".") + name;
// clearOldMetaPermissions(permName);
// addButtonPermissions(permName, name, transition.getRoleSet());
}
/**
* Method create action for button from WkfTransition and related destination nodes. It set
* onClick of ViewButton with new action created.
*
* @param viewButton ViewButton to update for onClick.
* @param transition WkfTransition from where action created.
* @param buttonName Name of button used in creation of action name.
*/
private String addButtonActions(WkfTransition transition, String buttonName) {
String actionName = buttonName.toLowerCase().replace(" ", "-");
actionName = "action-" + wkfService.wkfId + "-" + actionName;
List<String> actions = new ArrayList<String>();
String xml = "";
Integer alterType = transition.getAlertTypeSelect();
String alertMsg = transition.getAlertMsg();
if (alterType > 0 && alertMsg != null) {
String type = "alert";
if (alterType == 2) {
type = "info";
}
String alertAction = actionName + "-alert";
xml = getActionValidateXML(alertAction, type, alertMsg, transition.getConditions());
metaService.updateMetaAction(alertAction, "action-validate", xml, null);
actions.add(alertAction);
}
List<Attribute> attrs = new ArrayList<Attribute>();
Attribute attr = new Attribute();
MetaJsonField wkfField = wkfService.workflow.getStatusField();
attr.setName("value");
attr.setFieldName(wkfField.getName());
attr.setExpression("eval:" + getTyped(transition.getTarget().getSequence(), wkfField));
attrs.add(attr);
actions.add(actionName);
xml = getActionXML(actionName, attrs);
metaService.updateMetaAction(actionName, "action-record", xml, null);
// actions.add("save");
// actions.add(wkfService.trackingAction);
String successMsg = transition.getSuccessMsg();
if (successMsg != null) {
String sucessAction = actionName + "-success";
xml = getActionValidateXML(sucessAction, "notify", successMsg, null);
metaService.updateMetaAction(sucessAction, "action-validate", xml, null);
actions.add(sucessAction);
}
actions.add("save");
actions.add("action-group-" + wkfService.wkfId);
// actions.add("save");
// actions.add(wkfService.trackingAction);
return Joiner.on(",").join(actions);
}
/**
* Method create ActionRecord from given name and list of RecordField. It generate xml from
* ActionRecord.
*
* @param name Name of action.
* @param fields List of ActionRecord.
* @return Xml of ActionRecord created.
*/
private String getActionXML(String name, List<Attribute> attrs) {
log.debug("Creating action attrs: {}", name);
ActionAttrs action = new ActionAttrs();
action.setName(name);
action.setAttributes(attrs);
return XMLViews.toXml(action, true);
}
/**
* Method create ActionValidate from given name,type and validation message.
*
* @param name Name of action
* @param type Type of validate action ('notify','info' or 'alert').
* @param message Message to display for action.
* @return Xml generated from ActionValidate.
*/
private String getActionValidateXML(
String name, String type, String message, List<Filter> conditions) {
ActionValidate actionValidate = new ActionValidate();
actionValidate.setName(name);
List<Validator> validators = new ArrayList<ActionValidate.Validator>();
String condition = getFilters(conditions);
switch (type) {
case "notify":
Notify notify = new Notify();
notify.setMessage(message);
notify.setCondition(condition);
validators.add(notify);
break;
case "info":
Info info = new Info();
info.setMessage(message);
info.setCondition(condition);
validators.add(info);
break;
default:
Alert alert = new Alert();
alert.setMessage(message);
alert.setCondition(condition);
validators.add(alert);
break;
}
actionValidate.setValidators(validators);
return XMLViews.toXml(actionValidate, true);
}
/**
* Create/Update MetaPermission for button and set this permission in roles.
*
* @param name Name of permission to create/update.
* @param buttonName Name of button to add permission.
* @param roles Roles to update with permission.
*/
@Transactional
public void addButtonPermissions(String name, String buttonName, Set<Role> roles) {
if (roles == null || roles.isEmpty()) {
return;
}
MetaPermission permission = metaPermissionRepo.findByName(name);
if (permission == null) {
permission = new MetaPermission(name);
permission.setObject(wkfService.workflow.getModel());
MetaPermissionRule rule = new MetaPermissionRule();
rule.setCanRead(false);
rule.setField(buttonName);
permission.addRule(rule);
permission = metaPermissionRepo.save(permission);
}
for (Role role : roles) {
role.addMetaPermission(permission);
wkfService.roleRepo.save(role);
}
}
/**
* Clear old button permission from all roles having it.
*
* @param name Name of permission to clear.
*/
@Transactional
public void clearOldMetaPermissions(String name) {
MetaPermission permission = metaPermissionRepo.findByName(name);
if (permission != null) {
List<Role> oldRoleList =
wkfService
.roleRepo
.all()
.filter("self.metaPermissions.id = ?1", permission.getId())
.fetch();
for (Role role : oldRoleList) {
role.removeMetaPermission(permission);
wkfService.roleRepo.save(role);
}
}
}
}

View File

@ -0,0 +1,81 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.translation;
public interface ITranslation {
public static final String EDITOR_CHOOSE_APP = /*$$(*/ "Choose App name"; /*)*/
public static final String EDITOR_BASE_MODEL = /*$$(*/ "Base model"; /*)*/
public static final String EDITOR_CUSTOM_MODEL = /*$$(*/ "Custom Model"; /*)*/
public static final String EDITOR_CUSTOM_FIELD = /*$$(*/ "Custom Field"; /*)*/
public static final String EDITOR_STRING = /*$$(*/ "String"; /*)*/
public static final String EDITOR_INTEGER = /*$$(*/ "Integer"; /*)*/
public static final String EDITOR_PANEL = /*$$(*/ "Panel"; /*)*/
public static final String EDITOR_BUTTON = /*$$(*/ "Button"; /*)*/
public static final String EDITOR_DECIMAL = /*$$(*/ "Decimal"; /*)*/
public static final String EDITOR_TIME = /*$$(*/ "Time"; /*)*/
public static final String EDITOR_DATE = /*$$(*/ "Date"; /*)*/
public static final String EDITOR_DATETIME = /*$$(*/ "Datetime"; /*)*/
public static final String EDITOR_SEPARATOR = /*$$(*/ "Separator"; /*)*/
public static final String EDITOR_BOOLEAN = /*$$(*/ "Boolean"; /*)*/
public static final String EDITOR_M2O = /*$$(*/ "Many To One"; /*)*/
public static final String EDITOR_M2M = /*$$(*/ "Many To Many"; /*)*/
public static final String EDITOR_JM2M = /*$$(*/ "Json Many To Many"; /*)*/
public static final String EDITOR_JM2O = /*$$(*/ "Json Many To One"; /*)*/
public static final String EDITOR_JO2M = /*$$(*/ "Json One To Many"; /*)*/
public static final String EDITOR_O2M = /*$$(*/ "One To Many"; /*)*/
public static final String EDITOR_ONNEW = /*$$(*/ "On New"; /*)*/
public static final String EDITOR_ONSAVE = /*$$(*/ "On Save"; /*)*/
public static final String EDITOR_DEFAULT = /*$$(*/ "Default Value"; /*)*/
public static final String EDITOR_SELECTION = /*$$(*/ "Selection"; /*)*/
public static final String EDITOR_WIDGET = /*$$(*/ "Widget"; /*)*/
public static final String EDITOR_HELP = /*$$(*/ "Help"; /*)*/
public static final String EDITOR_REQUIRED = /*$$(*/ "Required"; /*)*/
public static final String EDITOR_MIN_SIZE = /*$$(*/ "Min Size"; /*)*/
public static final String EDITOR_MAX_SIZE = /*$$(*/ "Max Size"; /*)*/
public static final String EDITOR_REGEX = /*$$(*/ "Regex"; /*)*/
public static final String EDITOR_ONCHANGE = /*$$(*/ "On Change"; /*)*/
public static final String EDITOR_COLSPAN = /*$$(*/ "Colspan"; /*)*/
public static final String EDITOR_NAMEFIELD = /*$$(*/ "Name Field"; /*)*/
public static final String EDITOR_ONCLICK = /*$$(*/ "On Click"; /*)*/
public static final String EDITOR_HIDDEN_GRID = /*$$(*/ "Hidden In Grid"; /*)*/
public static final String EDITOR_SHOW_IF = /*$$(*/ "Show If"; /*)*/
public static final String EDITOR_REQUIRED_IF = /*$$(*/ "Required If"; /*)*/
public static final String EDITOR_TYPE = /*$$(*/ "Type"; /*)*/
public static final String EDITOR_META_MODEL = /*$$(*/ "Meta Model"; /*)*/
public static final String EDITOR_DOMAIN = /*$$(*/ "Domain"; /*)*/
public static final String EDITOR_TARGET_JSON = /*$$(*/ "Target Json Model"; /*)*/
public static final String EDITOR_SELECT_OPT = /*$$(*/ "Select Option"; /*)*/
public static final String EDITOR_PROP = /*$$(*/ "Properties"; /*)*/
public static final String EDITOR_APP_NAME = /*$$(*/ "App name"; /*)*/
public static final String EDITOR_SHOW_TITLE = /*$$(*/ "Show Title"; /*)*/
public static final String EDITOR_NAME_COLUMN = /*$$(*/ "Name Column"; /*)*/
public static final String EDITOR_CAN_COLLAPSE = /*$$(*/ "Can Collapse"; /*)*/
public static final String EDITOR_COLLAPSE_IF = /*$$(*/ "Collapse if"; /*)*/
public static final String EDITOR_FIELD_OPTIONS = /*$$(*/ "Field options"; /*)*/
public static final String EDITOR_UI_OPTIONS = /*$$(*/ "UI options"; /*)*/
public static final String EDITOR_IS_JSON_RELATIONAL_FIELD = /*$$(*/
"Is Json Relational Field"; /*)*/
public static final String WKF_TRACK = /*$$(*/ "Track flow"; /*)*/
public static final String WKF_EDIT_NODE = /*$$(*/ "Edit Node"; /*)*/
public static final String WKF_EDIT_TRANSITION = /*$$(*/ "Edit Transition"; /*)*/
public static final String BPM_APP_NAME = /*$$(*/ "value:BPM"; /*)*/
public static final String PRODUCT_APP_NAME = /*$$(*/ "value:Product App"; /*)*/
}

View File

@ -0,0 +1,79 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.web;
import com.axelor.common.Inflector;
import com.axelor.inject.Beans;
import com.axelor.meta.db.MetaView;
import com.axelor.meta.db.repo.MetaViewRepository;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.db.ActionBuilderView;
import com.axelor.studio.db.repo.ActionBuilderRepository;
import java.util.ArrayList;
import java.util.List;
public class ActionBuilderController {
private Inflector inflector;
public void setViews(ActionRequest request, ActionResponse response) {
inflector = Inflector.getInstance();
ActionBuilder builder = request.getContext().asType(ActionBuilder.class);
String model = builder.getModel();
boolean isJson = false;
if (builder.getIsJson() != null) {
isJson = builder.getIsJson();
}
if (builder.getTypeSelect() == ActionBuilderRepository.TYPE_SELECT_VIEW && model != null) {
if (!isJson) {
model = model.substring(model.lastIndexOf('.') + 1);
model = inflector.dasherize(model);
}
List<ActionBuilderView> views = new ArrayList<>();
addActionBuilderView(views, model, "grid", isJson, 0);
addActionBuilderView(views, model, "form", isJson, 1);
response.setValue("actionBuilderViews", views);
}
}
private void addActionBuilderView(
List<ActionBuilderView> views, String model, String type, boolean isJson, int sequence) {
String viewName = model + "-" + type;
if (isJson) {
viewName = "custom-model-" + model + "-" + type;
}
MetaView view = Beans.get(MetaViewRepository.class).findByName(viewName);
if (view == null) {
return;
}
ActionBuilderView builderView = new ActionBuilderView();
builderView.setViewName(view.getName());
builderView.setViewType(view.getType());
builderView.setSequence(sequence);
views.add(builderView);
}
}

View File

@ -0,0 +1,107 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.web;
import com.axelor.data.Listener;
import com.axelor.data.xml.XMLImporter;
import com.axelor.db.Model;
import com.axelor.inject.Beans;
import com.axelor.meta.MetaFiles;
import com.axelor.meta.db.MetaFile;
import com.axelor.meta.db.repo.MetaFileRepository;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.google.common.io.Files;
import com.google.inject.persist.Transactional;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.xmlbeans.impl.common.IOUtil;
public class AppBuilderController {
@Transactional
public void importBpm(ActionRequest request, ActionResponse response) {
String config = "/data-import/import-bpm.xml";
try {
InputStream inputStream = this.getClass().getResourceAsStream(config);
File configFile = File.createTempFile("config", ".xml");
FileOutputStream fout = new FileOutputStream(configFile);
IOUtil.copyCompletely(inputStream, fout);
@SuppressWarnings("rawtypes")
Path path =
MetaFiles.getPath((String) ((Map) request.getContext().get("dataFile")).get("filePath"));
File tempDir = Files.createTempDir();
File importFile = new File(tempDir, "bpm.xml");
Files.copy(path.toFile(), importFile);
XMLImporter importer =
new XMLImporter(configFile.getAbsolutePath(), tempDir.getAbsolutePath());
final StringBuilder log = new StringBuilder();
Listener listner =
new Listener() {
@Override
public void imported(Integer imported, Integer total) {
// log.append("Total records: " + total + ", Total imported: " + total);
}
@Override
public void imported(Model arg0) {}
@Override
public void handle(Model arg0, Exception err) {
log.append("Error in import: " + err.getStackTrace().toString());
}
};
importer.addListener(listner);
importer.run();
FileUtils.forceDelete(configFile);
FileUtils.forceDelete(tempDir);
FileUtils.forceDelete(path.toFile());
@SuppressWarnings("unchecked")
Object metaFileId = ((Map<String, Object>) request.getContext().get("dataFile")).get("id");
MetaFileRepository metaFileRepository = Beans.get(MetaFileRepository.class);
if (metaFileId != null) {
MetaFile metaFile = metaFileRepository.find(Long.parseLong(metaFileId.toString()));
if (metaFile != null) {
metaFileRepository.remove(metaFile);
}
}
response.setValue("importLog", log.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,128 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.web;
import com.axelor.common.Inflector;
import com.axelor.exception.AxelorException;
import com.axelor.inject.Beans;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.db.repo.MetaFieldRepository;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.axelor.studio.db.Filter;
import com.axelor.studio.service.filter.FilterSqlService;
import java.util.Map;
public class FilterController {
public void updateTargetField(ActionRequest request, ActionResponse response) {
Filter filter = request.getContext().asType(Filter.class);
MetaField metaField = filter.getMetaField();
MetaJsonField metaJson = filter.getMetaJsonField();
Boolean isJson = filter.getIsJson() != null ? filter.getIsJson() : false;
if (!isJson && metaField != null) {
String type =
metaField.getRelationship() != null
? metaField.getRelationship()
: metaField.getTypeName();
response.setValue("targetType", type);
response.setValue("targetField", metaField.getName());
response.setValue(
"targetTitle",
metaField.getLabel() != null && !metaField.getLabel().isEmpty()
? metaField.getLabel()
: metaField.getName());
} else if (isJson && metaJson != null) {
response.setValue("targetType", Inflector.getInstance().camelize(metaJson.getType()));
response.setValue("targetField", metaJson.getName());
} else {
response.setValue("targetField", null);
response.setValue("targetType", null);
}
response.setValue("operator", null);
}
public void updateTargetType(ActionRequest request, ActionResponse response)
throws AxelorException {
Filter filter = request.getContext().asType(Filter.class);
FilterSqlService filterSqlService = Beans.get(FilterSqlService.class);
if (filter.getTargetField() == null) return;
StringBuilder parent = new StringBuilder("self");
String targetType =
filterSqlService.getTargetType(
filterSqlService.getTargetField(parent, filter, null, false));
response.setValue("targetType", targetType);
response.setValue("filterOperator", null);
}
public void updateTargetMetaField(ActionRequest request, ActionResponse response) {
Filter filter = request.getContext().asType(Filter.class);
if (request.getContext().get("targetMetaField") != null) {
Integer id = (Integer) ((Map) request.getContext().get("targetMetaField")).get("id");
MetaField targetMetaField = Beans.get(MetaFieldRepository.class).find(Long.valueOf(id));
String targetTitle =
targetMetaField.getLabel() != null && !targetMetaField.getLabel().isEmpty()
? targetMetaField.getLabel()
: targetMetaField.getName();
response.setValue("targetField", filter.getTargetField() + "." + targetMetaField.getName());
response.setValue("targetTitle", filter.getTargetTitle() + "." + targetTitle);
response.setValue(
"targetType",
targetMetaField.getRelationship() != null
? targetMetaField.getRelationship()
: targetMetaField.getTypeName());
if (targetMetaField.getRelationship() != null) {
response.setValue("metaTargetFieldDomain", targetMetaField.getTypeName());
response.setValue("targetMetaField", null);
}
}
response.setValue("operator", null);
}
public void clearSelection(ActionRequest request, ActionResponse response) {
Filter filter = request.getContext().asType(Filter.class);
if (filter.getMetaField() != null) {
response.setValue("targetField", filter.getMetaField().getName());
response.setValue(
"targetTitle",
filter.getMetaField().getLabel() != null && !filter.getMetaField().getLabel().isEmpty()
? filter.getMetaField().getLabel()
: filter.getMetaField().getName());
response.setValue("targetType", filter.getMetaField().getRelationship());
}
response.setValue("metaTargetFieldDomain", null);
response.setValue("targetMetaField", null);
response.setValue("operator", null);
}
}

View File

@ -0,0 +1,114 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.web;
import com.axelor.inject.Beans;
import com.axelor.meta.db.MetaMenu;
import com.axelor.meta.db.repo.MetaMenuRepository;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.axelor.rpc.Context;
import com.axelor.studio.db.ActionBuilder;
import com.axelor.studio.service.builder.MenuBuilderService;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class MenuBuilderController {
@SuppressWarnings("unchecked")
public void fetchMenu(ActionRequest request, ActionResponse response) {
Context context = request.getContext();
Map<String, Object> values = null;
Map<String, Object> existingMenu = (Map<String, Object>) context.get("existingMenu");
if (existingMenu == null) {
values = getEmptyMenu();
} else {
Long menuId = Long.parseLong(existingMenu.get("id").toString());
values = getMenu(Beans.get(MetaMenuRepository.class).find(menuId));
}
response.setValues(values);
}
private Map<String, Object> getMenu(MetaMenu menu) {
Map<String, Object> values = new HashMap<>();
values.put("name", menu.getName());
values.put("title", menu.getTitle());
values.put("icon", menu.getIcon());
values.put("iconBackground", menu.getIconBackground());
values.put("order", menu.getOrder());
values.put("conditionToCheck", menu.getConditionToCheck());
values.put("parentMenu", menu.getParent());
values.put("tag", menu.getTag());
values.put("tagGet", menu.getTagGet());
values.put("tagCount", menu.getTagCount());
values.put("tagStyle", menu.getTagStyle());
values.put("groups", menu.getGroups());
values.put("top", menu.getTop());
values.put("roles", menu.getRoles());
values.put("conditionTocheck", menu.getConditionToCheck());
values.put("link", menu.getLink());
values.put("left", menu.getLeft());
values.put("mobile", menu.getMobile());
values.put("hidden", menu.getHidden());
if (menu.getAction() != null && menu.getAction().getType().contentEquals("action-view")) {
Optional<ActionBuilder> actionBuilderOpt =
Beans.get(MenuBuilderService.class).createActionBuilder(menu.getAction());
actionBuilderOpt.ifPresent(
actionBuilder -> {
values.put("actionBuilder", actionBuilder);
values.put("showAction", true);
});
}
return values;
}
private Map<String, Object> getEmptyMenu() {
Map<String, Object> values = new HashMap<>();
values.put("name", null);
values.put("title", null);
values.put("icon", null);
values.put("iconBackground", null);
values.put("order", null);
values.put("conditionToCheck", null);
values.put("parentMenu", null);
values.put("tag", null);
values.put("tagGet", null);
values.put("tagCount", null);
values.put("tagStyle", null);
values.put("groups", null);
values.put("top", null);
values.put("roles", null);
values.put("conditionTocheck", null);
values.put("link", null);
values.put("left", null);
values.put("mobile", null);
values.put("hidden", null);
values.put("actionBuilder", null);
values.put("showAction", false);
return values;
}
}

View File

@ -0,0 +1,52 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.web;
import com.axelor.inject.Beans;
import com.axelor.meta.db.MetaJsonModel;
import com.axelor.meta.schema.actions.ActionView;
import com.axelor.meta.schema.actions.ActionView.ActionViewBuilder;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.db.repo.WkfRepository;
public class MetaJsonModelController {
public void openWorkflow(ActionRequest request, ActionResponse response) {
MetaJsonModel jsonModel = request.getContext().asType(MetaJsonModel.class);
Wkf wkf =
Beans.get(WkfRepository.class)
.all()
.filter("self.model = ?1", jsonModel.getName())
.fetchOne();
ActionViewBuilder builder =
ActionView.define("Workflow").add("form", "wkf-form").model("com.axelor.studio.db.Wkf");
if (wkf == null) {
builder.context("_jsonModel", jsonModel.getName());
} else {
builder.context("_showRecord", wkf.getId());
}
response.setView(builder.map());
}
}

View File

@ -0,0 +1,254 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2019 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.studio.web;
import com.axelor.common.Inflector;
import com.axelor.exception.service.TraceBackService;
import com.axelor.i18n.I18n;
import com.axelor.inject.Beans;
import com.axelor.meta.MetaStore;
import com.axelor.meta.db.MetaJsonField;
import com.axelor.meta.schema.actions.ActionView;
import com.axelor.meta.schema.views.Selection.Option;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.axelor.studio.db.Wkf;
import com.axelor.studio.db.WkfNode;
import com.axelor.studio.db.WkfTransition;
import com.axelor.studio.db.repo.WkfNodeRepository;
import com.axelor.studio.db.repo.WkfRepository;
import com.axelor.studio.db.repo.WkfTransitionRepository;
import com.axelor.studio.exception.IExceptionMessage;
import com.axelor.studio.service.wkf.WkfDesignerService;
import com.axelor.studio.service.wkf.WkfService;
import com.axelor.studio.translation.ITranslation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
public class WkfController {
public void processXml(ActionRequest request, ActionResponse response) {
try {
Wkf workflow = request.getContext().asType(Wkf.class);
workflow = Beans.get(WkfRepository.class).find(workflow.getId());
Beans.get(WkfDesignerService.class).processXml(workflow);
} catch (Exception e) {
TraceBackService.trace(response, e);
}
}
public void processWkf(ActionRequest request, ActionResponse response) {
try {
Wkf workflow = request.getContext().asType(Wkf.class);
workflow = Beans.get(WkfRepository.class).find(workflow.getId());
Beans.get(WkfService.class).process(workflow);
response.setReload(true);
} catch (Exception e) {
TraceBackService.trace(response, e);
}
}
public void onNodeEdit(ActionRequest request, ActionResponse response) {
try {
WkfNodeRepository repo = Beans.get(WkfNodeRepository.class);
WkfNode node = request.getContext().asType(WkfNode.class);
if (node.getWkf().getId() != null) {
WkfNode found =
repo.all()
.filter(
"self.wkf.id = ? and self.xmlId = ?", node.getWkf().getId(), node.getXmlId())
.fetchOne();
if (found != null) {
Map<String, Object> view =
ActionView.define(I18n.get(ITranslation.WKF_EDIT_NODE))
.add("form", "wkf-node-form")
.model(WkfNode.class.getName())
.context("_showRecord", found.getId())
.param("popup", "true")
.param("show-toolbar", "false")
.param("forceEdit", "true")
.map();
response.setView(view);
} else {
response.setFlash(I18n.get(IExceptionMessage.WKF_1));
}
} else {
response.setFlash(I18n.get(IExceptionMessage.WKF_1));
}
} catch (Exception e) {
TraceBackService.trace(response, e);
}
}
public void onTransitionEdit(ActionRequest request, ActionResponse response) {
try {
WkfTransitionRepository repo = Beans.get(WkfTransitionRepository.class);
WkfTransition transition = request.getContext().asType(WkfTransition.class);
WkfTransition found = repo.all().filter("self.xmlId = ?", transition.getXmlId()).fetchOne();
if (found != null) {
Map<String, Object> view =
ActionView.define(I18n.get(ITranslation.WKF_EDIT_TRANSITION))
.add("form", "wkf-transition-form")
.model(WkfTransition.class.getName())
.context("_showRecord", found.getId())
.param("popup", "true")
.param("show-toolbar", "false")
.param("forceEdit", "true")
.map();
response.setView(view);
} else {
response.setFlash(I18n.get(IExceptionMessage.WKF_1));
}
} catch (Exception e) {
TraceBackService.trace(response, e);
}
}
public void setDefaultNodes(ActionRequest request, ActionResponse response) {
Wkf wkf = request.getContext().asType(Wkf.class);
MetaJsonField wkfField = wkf.getStatusField();
if (wkfField != null) {
Optional<Pair<String, String>> nodesOpt = getDefaultNodes(wkfField);
nodesOpt.ifPresent(
nodes -> {
String bpmnXml =
" <?xml version=\"1.0\" encoding=\"UTF-8\"?> "
+ "<definitions xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" "
+ "xmlns:x=\"http://axelor.com\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" "
+ "xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" "
+ "targetNamespace=\"http://bpmn.io/schema/bpmn\" id=\"Definitions_1\"> "
+ "<process id=\"Process_1\" name=\""
+ wkf.getName()
+ "\" x:id=\""
+ wkf.getId()
+ "\" isExecutable=\"false\"> "
+ nodes.getLeft()
+ "</process>"
+ "<bpmndi:BPMNDiagram id=\"BPMNDiagram_1\">"
+ "<bpmndi:BPMNPlane id=\"BPMNPlane_1\" bpmnElement=\"Process_1\">"
+ nodes.getRight()
+ "</bpmndi:BPMNPlane>"
+ "</bpmndi:BPMNDiagram>"
+ "</definitions>";
response.setValue("$bpmnDefault", bpmnXml);
});
}
}
private Optional<Pair<String, String>> getDefaultNodes(MetaJsonField statusField) {
// String[] nodes = new String[] {
// "<startEvent id=\"StartEvent_1\" /><task id=\"Task_1\" /><endEvent id=\"EndEvent_1\"/>",
// "<bpmndi:BPMNShape id=\"_BPMNShape_StartEvent_2\" bpmnElement=\"StartEvent_1\">"
// + "<dc:Bounds x=\"100\" y=\"100\" width=\"36\" height=\"36\"/>"
// + "</bpmndi:BPMNShape>"
// + "<bpmndi:BPMNShape id=\"_BPMNShape_Task_1\" bpmnElement=\"Task_1\">"
// + "<dc:Bounds x=\"250\" y=\"100\" width=\"100\" height=\"80\"/>"
// + "</bpmndi:BPMNShape>"
// + "<bpmndi:BPMNShape id=\"_BPMNShape_EndEvent_2\" bpmnElement=\"EndEvent_1\">"
// + "<dc:Bounds x=\"500\" y=\"100\" width=\"36\" height=\"36\"/>"
// + "</bpmndi:BPMNShape>"
// };
//
List<Option> select = getSelect(statusField);
if (!CollectionUtils.isEmpty(select)) {
StringBuilder elements = new StringBuilder();
StringBuilder designs = new StringBuilder();
int count = 1;
int x = 100;
int y;
for (Option option : select) {
String element = null;
int width = 100;
int height = 80;
if (count == 1) {
width = 36;
height = 36;
y = 125;
element = "startEvent";
} else if (count == select.size()) {
width = 36;
height = 36;
x += 150;
y = 125;
element = "endEvent";
} else {
y = 100;
x += 150;
element = "task";
}
String elementId = Inflector.getInstance().camelize(element, false) + "_" + count;
element = "<" + element + " id=\"" + elementId + "\" name=\"" + option.getTitle() + "\" />";
elements.append(element);
String design =
"<bpmndi:BPMNShape id=\"_BPMNShape_"
+ elementId
+ "\" bpmnElement=\""
+ elementId
+ "\" >"
+ "<dc:Bounds x=\""
+ x
+ "\" y=\""
+ y
+ "\" width=\""
+ width
+ "\" height=\""
+ height
+ "\" />"
+ "</bpmndi:BPMNShape>";
designs.append(design);
count++;
}
if (elements.length() > 0) {
return Optional.of(Pair.of(elements.toString(), designs.toString()));
}
}
return Optional.empty();
}
private List<Option> getSelect(MetaJsonField wkfField) {
if (wkfField == null) {
return Collections.emptyList();
}
if (wkfField.getSelection() != null) {
return MetaStore.getSelectionList(wkfField.getSelection());
}
return Collections.emptyList();
}
}

View File

@ -0,0 +1,514 @@
<?xml version="1.0" encoding="utf-8"?>
<bpm>
<% allApps = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.AppBuilderRepository' as Class).all()
allModels = com.axelor.inject.Beans.get('com.axelor.meta.db.repo.MetaJsonModelRepository' as Class).all()
allFields = com.axelor.inject.Beans.get('com.axelor.meta.db.repo.MetaJsonFieldRepository' as Class).all()
allSelections = com.axelor.inject.Beans.get('com.axelor.meta.db.repo.MetaSelectRepository' as Class).all()
allCharts = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.ChartBuilderRepository' as Class).all()
allDashboards = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.DashboardBuilderRepository' as Class).all()
allDashlets = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.DashletBuilderRepository' as Class).all()
allActions = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.ActionBuilderRepository' as Class).all()
allMenus = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.MenuBuilderRepository' as Class).all()
allMenusParentMenu = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.MenuBuilderRepository' as Class).all()
allWkfs = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.WkfRepository' as Class).all()
if(__ids__ != null) {
allApps = allApps.filter('self.id in ?1',__ids__)
allModels = allModels.filter('self.appBuilder.id in ?1',__ids__)
allFields = allFields.filter('self.appBuilder.id in ?1 OR (self.appBuilder is null and self.jsonModel.appBuilder.id in ?1)',__ids__)
allSelections = allSelections.filter('(self.appBuilder.id in ?1 OR self.appBuilder is null) AND self.isCustom = true',__ids__)
allCharts = allCharts.filter('self.appBuilder.id in ?1',__ids__)
allDashboards = allDashboards.filter('self.appBuilder.id in ?1',__ids__)
allDashlets = allDashlets.filter('self.appBuilder.id in ?1 or (self.appBuilder is null and self.dashboardBuilder.appBuilder.id in ?1)',__ids__)
allActions = allActions.filter('self.appBuilder.id in ?1)',__ids__)
allMenus = allMenus.filter('self.appBuilder.id in ?1 and self.parentMenu is null)',__ids__).order('-parentMenu')
allMenusParentMenu = allMenusParentMenu.filter('self.appBuilder.id in ?1 and self.parentMenu is not null',__ids__)
allWkfs = allWkfs.filter('self.appBuilder.id in ?1)',__ids__)
} else {
allSelections = allSelections.filter('self.isCustom = true')
allMenus = allMenus.filter('self.parentMenu is null')
allMenusParentMenu = allMenusParentMenu.filter('self.parentMenu is not null')
}
apps = ""
allApps.fetch().each({
depends = ""
it.dependsOnSet?.each({ depend -> depends +="${depend.code}," })
apps += """\n\t<appBuilder>
<name>${it.name}</name>
<code>${it.code}</code>
<description>${it.description}</description>
<depends>$depends</depends>
<image name=\"${it.image?.fileName}\">${com.axelor.studio.service.ExportService.getImage(it.image)}</image>
<sequence>${it.sequence}</sequence>
\n\t</appBuilder>"""
})
models = ""
allModels.fetch().each({
model -> models += """\n\t\t<model>
\n\t\t\t<name>${model.name}</name>
\n\t\t\t<title>${model.title}</title>
\n\t\t\t<onNew>${model.onNew}</onNew>
\n\t\t\t<onSave>${model.onSave}</onSave>
\n\t\t\t<menuTitle>${model.menuTitle}</menuTitle>
\n\t\t\t<menuIcon>${model.menuIcon}</menuIcon>
\n\t\t\t<menuBackground>${model.menuBackground}</menuBackground>
\n\t\t\t<menuOrder>${model.menuOrder}</menuOrder>
\n\t\t\t<menuTop>${model.menuTop}</menuTop>
\n\t\t\t<menuParent>${model.menuParent?.id}</menuParent>
\n\t\t\t<appBuilder>${model.appBuilder?.code}</appBuilder>
\n\t\t</model>"""
})
fields = ""
allFields.fetch().each({
field -> fields += """\n\t\t<field>
\n\t\t\t<name>${field.name}</name>
\n\t\t\t<title>${field.title}</title>
\n\t\t\t<type>${field.type}</type>
\n\t\t\t<defaultValue>${field.defaultValue}</defaultValue>
\n\t\t\t<domain>${field.domain}</domain>
\n\t\t\t<enumType>${field.enumType}</enumType>
\n\t\t\t<help>${field.help}</help>
\n\t\t\t<formView>${field.formView}</formView>
\n\t\t\t<gridView>${field.gridView}</gridView>
\n\t\t\t<hidden>${field.hidden}</hidden>
\n\t\t\t<visibleInGrid>${field.visibleInGrid}</visibleInGrid>
\n\t\t\t<hideIf>${field.hideIf}</hideIf>
\n\t\t\t<isWkf>${field.isWkf}</isWkf>
\n\t\t\t<maxSize>${field.maxSize}</maxSize>
\n\t\t\t<minSize>${field.minSize}</minSize>
\n\t\t\t<model>${field.model}</model>
\n\t\t\t<modelField>${field.modelField}</modelField>
\n\t\t\t<nameField>${field.nameField}</nameField>
\n\t\t\t<onChange>${field.onChange}</onChange>
\n\t\t\t<onClick>${field.onClick}</onClick>
\n\t\t\t<precision>${field.precision}</precision>
\n\t\t\t<regex>${field.regex}</regex>
\n\t\t\t<required>${field.required}</required>
\n\t\t\t<requiredIf>${field.requiredIf}</requiredIf>
\n\t\t\t<readonly>${field.readonly}</readonly>
\n\t\t\t<scale>${field.scale}</scale>
\n\t\t\t<selection>${field.selection}</selection>
\n\t\t\t<sequence>${field.sequence}</sequence>
\n\t\t\t<showIf>${field.showIf}</showIf>
\n\t\t\t<targetModel>${field.targetModel}</targetModel>
\n\t\t\t<widget>${field.widget}</widget>
\n\t\t\t<widgetAttrs>""" + field.widgetAttrs + """</widgetAttrs>
\n\t\t\t<valueExpr>${field.valueExpr != null ? """ + field.valueExpr + """ : ""}</valueExpr>
\n\t\t\t<jsonModel>${field.jsonModel?.name}</jsonModel>
\n\t\t\t<targetJsonModel>${field.targetJsonModel?.name}</targetJsonModel>
\n\t\t\t<appBuilder>${field.appBuilder?.code}</appBuilder>
\n\t\t\t<modelAppBuilder>${field.jsonModel?.appBuilder?.code}</modelAppBuilder>
\n\t\t</field>"""
})
selections = ""
allSelections.fetch().each({
selection ->
options = ""
selection.items.each{
option -> options += """\n\t\t\t\t<option>
\n\t\t\t\t\t<title>${option.title}</title>
\n\t\t\t\t\t<value>${option.value}</value>
\n\t\t\t\t\t<icon>${option.icon}</icon>
\n\t\t\t\t\t<data>${option.data}</data>
\n\t\t\t\t\t<order>${option.order}</order>
\n\t\t\t\t\t<hidden>${option.hidden}</hidden>
\n\t\t\t\t\t<select>${option.select?.name}</select>
\n\t\t\t\t</option>"""
}
selections += """\n\t\t<selection>
\n\t\t\t<name>${selection.name}</name>
\n\t\t\t<module>${selection.module}</module>
\n\t\t\t<priority>${selection.priority}</priority>
\n\t\t\t<items>$options
\n\t\t\t</items>
\n\t\t\t<isCustom>${selection.isCustom}</isCustom>
\n\t\t\t<appBuilder>${selection.appBuilder?.code}</appBuilder>
\n\t\t</selection>"""
})
charts = ""
allCharts.fetch().each({
chart ->
filters = ""
chart.filterList.each{
filter->filters += """\n\t\t\t\t<filter>
\n\t\t\t\t\t<metaField>${filter.metaField?.name}</metaField>
\n\t\t\t\t\t<metaJsonField>${filter.metaJsonField?.name}</metaJsonField>
\n\t\t\t\t\t<operator>${filter.operator}</operator>
\n\t\t\t\t\t<targetField>${filter.targetField}</targetField>
\n\t\t\t\t\t<targetType>${filter.targetType}</targetType>
\n\t\t\t\t\t<value>${filter.value}</value>
\n\t\t\t\t\t<defaultValue>${filter.defaultValue}</defaultValue>
\n\t\t\t\t\t<isParameter>${filter.isParameter}</isParameter>
\n\t\t\t\t\t<isJson>${filter.isJson}</isJson>
\n\t\t\t\t\t<isTargetJson>${filter.isTargetJson}</isTargetJson>
\n\t\t\t\t\t<logicOp>${filter.logicOp}</logicOp>
\n\t\t\t\t</filter>"""
}
charts += """\n\t\t<chartBuilder>
\n\t\t\t<name>${chart.name}</name>
\n\t\t\t<title>${chart.title}</title>
\n\t\t\t<chartType>${chart.chartType}</chartType>
\n\t\t\t<isJson>${chart.isJson}</isJson>
\n\t\t\t<model>${chart.model}</model>
\n\t\t\t<groupOn>${chart.groupOn?.name}</groupOn>
\n\t\t\t<groupOnJson>${chart.groupOnJson?.name}</groupOnJson>
\n\t\t\t<groupDateType>${chart.groupDateType}</groupDateType>
\n\t\t\t<groupOnTarget>${chart.groupOnTarget}</groupOnTarget>
\n\t\t\t<groupOnTargetType>${chart.groupOnTargetType}</groupOnTargetType>
\n\t\t\t<isJsonGroupOn>${chart.isJsonGroupOn}</isJsonGroupOn>
\n\t\t\t<isJsonAggregateOn>${chart.isJsonAggregateOn}</isJsonAggregateOn>
\n\t\t\t<isJsonDisplayField>${chart.isJsonDisplayField}</isJsonDisplayField>
\n\t\t\t<aggregateOnJson>${chart.aggregateOnJson?.name}</aggregateOnJson>
\n\t\t\t<aggregateOn>${chart.aggregateOn?.name}</aggregateOn>
\n\t\t\t<aggregateOnTarget>${chart.aggregateOnTarget}</aggregateOnTarget>
\n\t\t\t<aggregateDateType>${chart.aggregateDateType}</aggregateDateType>
\n\t\t\t<aggregateOnTargetType>${chart.aggregateOnTargetType}</aggregateOnTargetType>
\n\t\t\t<displayField>${chart.displayField?.name}</displayField>
\n\t\t\t<displayFieldJson>${chart.displayFieldJson?.name}</displayFieldJson>
\n\t\t\t<displayType>${chart.displayType}</displayType>
\n\t\t\t<filters>$filters
\n\t\t\t</filters>
\n\t\t\t<appBuilder>${chart.appBuilder?.code}</appBuilder>
\n\t\t</chartBuilder>"""
})
dashboards = ""
allDashboards.fetch().each({
dashboard ->
dashboards += """\n\t\t<dashboardBuilder>
\n\t\t\t<name>${dashboard.name}</name>
\n\t\t\t<title>${dashboard.title}</title>
\n\t\t\t<model>${dashboard.model}</model>
\n\t\t\t<appBuilder>${dashboard.appBuilder?.code}</appBuilder>
\n\t\t</dashboardBuilder>"""
})
dashlets = ""
allDashlets.fetch().each({
dashlet ->
dashlets += """\n\t\t<dashletBuilder>
\n\t\t\t<name>${dashlet.name}</name>
\n\t\t\t<metaView>${dashlet.metaView?.name}</metaView>
\n\t\t\t<action>${dashlet.action?.name}</action>
\n\t\t\t<dashboardBuilder>${dashlet.dashboardBuilder?.name}</dashboardBuilder>
\n\t\t\t<sequence>${dashlet.sequence}</sequence>
\n\t\t\t<viewType>${dashlet.viewType}</viewType>
\n\t\t\t<colspan>${dashlet.colspan}</colspan>
\n\t\t\t<paginationLimit>${dashlet.paginationLimit}</paginationLimit>
\n\t\t\t<appBuilder>${dashlet.appBuilder?.code}</appBuilder>
\n\t\t\t<parentAppBuilder>${dashlet.dashboardBuilder.appBuilder?.code}</parentAppBuilder>
\n\t\t</dashletBuilder>"""
})
actions = ""
allActions.fetch().each({
action ->
lines = com.axelor.studio.service.ExportService.exportActionBuilderLines(action.lines, 4)
viewParams = com.axelor.studio.service.ExportService.exportActionBuilderLines(action.viewParams, 4)
views = ""
action.actionBuilderViews.each{
view->views += """\n\t\t\t\t<view>
\n\t\t\t\t\t<viewType>${view.viewType}</viewType>
\n\t\t\t\t\t<viewName>${view.viewName}</viewName>
\n\t\t\t\t\t<sequence>${view.sequence}</sequence>
\n\t\t\t\t</view>"""
}
actions += """\n\t\t<actionBuilder>
\n\t\t\t<name>${action.name}</name>
\n\t\t\t<typeSelect>${action.typeSelect}</typeSelect>
\n\t\t\t<model>${action.model}</model>
\n\t\t\t<targetModel>${action.targetModel}</targetModel>
\n\t\t\t<lines>$lines
\n\t\t\t</lines>
\n\t\t\t<title>${action.title}</title>
\n\t\t\t<transactional>${action.transactional}</transactional>
\n\t\t\t<scriptType>${action.scriptType}</scriptType>
\n\t\t\t<scriptText>${action.scriptText}</scriptText>
\n\t\t\t<actionBuilderViews>$views
\n\t\t\t</actionBuilderViews>
\n\t\t\t<isJson>${action.isJson}</isJson>
\n\t\t\t<domainCondition>${action.domainCondition}</domainCondition>
\n\t\t\t<viewParams>$viewParams
\n\t\t\t</viewParams>
\n\t\t\t<menuAction>${action.menuAction}</menuAction>
\n\t\t\t<appBuilder>${action.appBuilder?.code}</appBuilder>
\n\t\t</actionBuilder>"""
})
menus = ""
allMenus.fetch().each({
menu ->
groups = ""
menu.groups.each{
group -> groups += """\n\t\t\t\t<group>${group.code}</group>"""
}
roles = ""
menu.roles.each{
role -> roles += """\n\t\t\t\t<role>${role.name}</role>"""
}
menus += """\n\t\t<menuBuilder>
\n\t\t\t<name>${menu.name}</name>
\n\t\t\t<title>${menu.title}</title>
\n\t\t\t<icon>${menu.icon}</icon>
\n\t\t\t<iconBackground>${menu.iconBackground}</iconBackground>
\n\t\t\t<order>${menu.order}</order>
\n\t\t\t<tag>${menu.tag}</tag>
\n\t\t\t<tagGet>${menu.tagGet}</tagGet>
\n\t\t\t<tagCount>${menu.tagCount}</tagCount>
\n\t\t\t<tagStyle>${menu.tagStyle}</tagStyle>
\n\t\t\t<top>${menu.top}</top>
\n\t\t\t<left>${menu.left}</left>
\n\t\t\t<mobile>${menu.mobile}</mobile>
\n\t\t\t<hidden>${menu.hidden}</hidden>
\n\t\t\t<link>${menu.link}</link>
\n\t\t\t<conditionToCheck>${menu.conditionToCheck}</conditionToCheck>
\n\t\t\t<moduleToCheck>${menu.moduleToCheck}</moduleToCheck>
\n\t\t\t<showAction>${menu.showAction}</showAction>
\n\t\t\t<groups>$groups
\n\t\t\t</groups>
\n\t\t\t<roles>$roles
\n\t\t\t</roles>
\n\t\t\t<parentMenu>${menu.parentMenu?.name}</parentMenu>
\n\t\t\t<actionBuilder>${menu.actionBuilder?.name}</actionBuilder>
\n\t\t\t<appBuilder>${menu.appBuilder?.code}</appBuilder>
\n\t\t</menuBuilder>"""
})
allMenusParentMenu.fetch().each({
menu ->
groups = ""
menu.groups.each{
group -> groups += """\n\t\t\t\t<group>${group.code}</group>"""
}
roles = ""
menu.roles.each{
role -> roles += """\n\t\t\t\t<role>${role.name}</role>"""
}
menus += """\n\t\t<menuBuilder>
\n\t\t\t<name>${menu.name}</name>
\n\t\t\t<title>${menu.title}</title>
\n\t\t\t<icon>${menu.icon}</icon>
\n\t\t\t<iconBackground>${menu.iconBackground}</iconBackground>
\n\t\t\t<order>${menu.order}</order>
\n\t\t\t<tag>${menu.tag}</tag>
\n\t\t\t<tagGet>${menu.tagGet}</tagGet>
\n\t\t\t<tagCount>${menu.tagCount}</tagCount>
\n\t\t\t<tagStyle>${menu.tagStyle}</tagStyle>
\n\t\t\t<top>${menu.top}</top>
\n\t\t\t<left>${menu.left}</left>
\n\t\t\t<mobile>${menu.mobile}</mobile>
\n\t\t\t<hidden>${menu.hidden}</hidden>
\n\t\t\t<link>${menu.link}</link>
\n\t\t\t<conditionToCheck>${menu.conditionToCheck}</conditionToCheck>
\n\t\t\t<moduleToCheck>${menu.moduleToCheck}</moduleToCheck>
\n\t\t\t<showAction>${menu.showAction}</showAction>
\n\t\t\t<groups>$groups
\n\t\t\t</groups>
\n\t\t\t<roles>$roles
\n\t\t\t</roles>
\n\t\t\t<parentMenu>${menu.parentMenu?.name}</parentMenu>
\n\t\t\t<actionBuilder>${menu.actionBuilder?.name}</actionBuilder>
\n\t\t\t<appBuilder>${menu.appBuilder?.code}</appBuilder>
\n\t\t</menuBuilder>"""
})
wkfs = ""
nodes = ""
transitions = ""
allWkfs.fetch().each({
wkf ->
wkf.nodes.each{
node ->
node = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.WkfNodeRepository' as Class).find(node.id)
incoming = ""
node.incoming.each{
incom -> incoming += """\n\t\t\t<incoming>${incom.name}</incoming>"""
}
outgoing = ""
node.outgoing.each{
outg -> outgoing += """\n\t\t\t\t<outgoing>${outg.name}</outgoing>"""
}
roles = ""
node.roleSet.each{
role -> roles += """\n\t\t\t<role>${role.name}</role>"""
}
metaActions = ""
node.metaActionSet.each{
action -> metaActions += """\n\t\t\t<action>${action.name}</action>"""
}
nodes += """\n\t\t\t<node>
\n\t\t\t<wkf>${node.wkf.name}</wkf>
\n\t\t\t<name>${node.name}</name>
\n\t\t\t<title>${node.title}</title>
\n\t\t\t<xmlId>${node.xmlId}</xmlId>
\n\t\t\t<metaField>${node.metaField?.name}</metaField>
\n\t\t\t<metaFieldModel>${node.metaField?.metaModel?.name}</metaFieldModel>
\n\t\t\t<incomings>$incoming
\n\t\t\t</incomings>
\n\t\t\t<outgoings>$outgoing
\n\t\t\t</outgoings>
\n\t\t\t<roleSet>$roles
\n\t\t\t</roleSet>
\n\t\t\t<metaActionSet>$metaActions
\n\t\t\t</metaActionSet>
\n\t\t\t<sequence>${node.sequence}</sequence>
\n\t\t\t<nodeType>${node.nodeType}</nodeType>
\n\t\t\t</node>"""
}
wkf.transitions.each{
transition ->
conditions = ""
transition = com.axelor.inject.Beans.get('com.axelor.studio.db.repo.WkfTransitionRepository' as Class).find(transition.id)
transition.conditions.each{
condition-> conditions += """\n\t\t\t<condition>
\n\t\t\t\t<metaField>${condition.metaField?.name}</metaField>
\n\t\t\t\t<metaModel>${condition.metaField?.metaModel?.name}</metaModel>
\n\t\t\t\t<metaJsonField>${condition.metaJsonField?.name}</metaJsonField>
\n\t\t\t\t<jsonModel>${condition.metaJsonField?.jsonModel?.name}</jsonModel>
\n\t\t\t\t<operator>${condition.operator}</operator>
\n\t\t\t\t<targetField>${condition.targetField}</targetField>
\n\t\t\t\t<targetType>${condition.targetType}</targetType>
\n\t\t\t\t<value>${condition.value}</value>
\n\t\t\t\t<isTargetJson>${condition.isTargetJson}</isTargetJson>
\n\t\t\t\t<logicOp>${condition.logicOp}</logicOp>
\n\t\t\t\t<model>${condition.metaJsonField?.model}</model>
\n\t\t\t\t<modelField>${condition.metaJsonField?.modelField}</modelField>
\n\t\t\t</condition>"""
}
roles = ""
transition.roleSet.each{
role -> roles += """\n\t\t\t\t<role>${role.name}</role>"""
}
transitions += """\n\t\t\t<transition>
\n\t\t\t<wkf>${transition.wkf.name}</wkf>
\n\t\t\t<name>${transition.name}</name>
\n\t\t\t<xmlId>${transition.xmlId}</xmlId>
\n\t\t\t<isButton>${transition.isButton}</isButton>
\n\t\t\t<buttonTitle>${transition.buttonTitle}</buttonTitle>
\n\t\t\t<roleSet>$roles
\n\t\t\t</roleSet>
\n\t\t\t<conditions>$conditions
\n\t\t\t</conditions>
\n\t\t\t<source>${transition.source?.name}</source>
\n\t\t\t<target>${transition.target?.name}</target>
\n\t\t\t<alertTypeSelect>${transition.alertTypeSelect}</alertTypeSelect>
\n\t\t\t<alertMsg>${transition.alertMsg}</alertMsg>
\n\t\t\t<successMsg>${transition.successMsg}</successMsg>
\n\t\t\t</transition>"""
}
wkfs += """\n\t\t<wkf>
\n\t\t\t<name>${wkf.name}</name>
\n\t\t\t<model>${wkf.model}</model>
\n\t\t\t<jsonField>${wkf.jsonField}</jsonField>
\n\t\t\t<isJson>${wkf.isJson}</isJson>
\n\t\t\t<isTrackFlow>${wkf.isTrackFlow}</isTrackFlow>
\n\t\t\t<statusField>${wkf.statusField?.name}</statusField>
\n\t\t\t<displayTypeSelect>${wkf.displayTypeSelect}</displayTypeSelect>
\n\t\t\t<bpmnXml><![CDATA[""" + wkf.bpmnXml + """]]></bpmnXml>
\n\t\t\t<appBuilder>${wkf.appBuilder.code}</appBuilder>
\n\t\t</wkf>"""
})
out <<
"""
$apps
<models>
$models
</models>
<fields>
$fields
</fields>
<selections>
$selections
</selections>
<chartBuilders>
$charts
</chartBuilders>
<actionBuilders>
$actions
</actionBuilders>
<dashboardBuilders>
$dashboards
</dashboardBuilders>
<dashletBuilders>
$dashlets
</dashletBuilders>
<menuBuilders>
$menus
</menuBuilders>
<wkfs>
$wkfs
</wkfs>
<nodes>
$nodes
</nodes>
<transitions>
$transitions
</transitions>
"""
%>
</bpm>

View File

@ -0,0 +1,409 @@
<?xml version="1.0" encoding="utf-8"?>
<xml-inputs xmlns="http://axelor.com/xml/ns/data-import"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/data-import http://axelor.com/xml/ns/data-import/data-import_5.2.xsd">
<input file="bpm.xml" root="bpm" >
<bind node="appBuilder" type="com.axelor.studio.db.AppBuilder" search="self.code = :code" update="true" call="com.axelor.studio.service.ImportService:importAppBuilderImg">
<bind node="name" to="name" />
<bind node="code" to="code" />
<bind node="description" to="description" />
<bind node="sequence" to="sequence" />
<bind node="image/@name" alias="fileName"/>
<bind node="image" alias="imageData" />
</bind>
<bind node="appBuilder" type="com.axelor.studio.db.AppBuilder" search="self.code = :code" create="false" update="true" call="com.axelor.studio.service.ImportService:importAppBuilder">
<bind node="code" to="code" />
<bind node="depends" alias="depends" />
<bind to="dependsOnSet" alias="deps" search="self.code in :deps" eval="depends != null ? depends.split(',') as List : []" create="false"/>
</bind>
<bind node="models/model" type="com.axelor.meta.db.MetaJsonModel" search="self.name = :name" update="true">
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="onNew" to="onNew" />
<bind node="onSave" to="onSave" />
<bind node="menuTitle" to="menuTitle" />
<bind node="menuIcon" to="menuIcon" />
<bind node="menuBackground" to="menuBackground" />
<bind node="menuOrder" to="menuOrder" />
<bind node="menuTop" to="menuTop" />
<bind node="menuParent" to="menuParent" search="self.id = :menuParent" create="false" />
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
</bind>
<bind node="fields/field" type="com.axelor.meta.db.MetaJsonField" if="jsonModel != null &amp;&amp; !jsonModel.empty"
search="self.name = :name and self.model = :model and self.modelField = :modelField and self.jsonModel.name = :jsonModel"
call="com.axelor.studio.service.ImportService:importJsonModelField" update="true">
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="type" to="type" />
<bind node="defaultValue" to="defaultValue" />
<bind node="domain" to="domain" />
<bind node="enumType" to="enumType" />
<bind node="help" to="help" />
<bind node="formView" to="formView" />
<bind node="gridView" to="gridView" />
<bind node="hidden" to="hidden" />
<bind node="visibleInGrid" to="visibleInGrid" />
<bind node="hideIf" to="hideIf" />
<bind node="isWkf" to="isWkf" />
<bind node="maxSize" to="maxSize" />
<bind node="minSize" to="minSize" />
<bind node="model" to="model" />
<bind node="modelField" to="modelField" />
<bind node="nameField" to="nameField" />
<bind node="onChange" to="onChange" />
<bind node="onClick" to="onClick" />
<bind node="precision" to="precision" />
<bind node="regex" to="regex" />
<bind node="required" to="required" />
<bind node="requiredIf" to="requiredIf" />
<bind node="readonly" to="readonly" />
<bind node="scale" to="scale" />
<bind node="selection" to="selection" />
<bind node="sequence" to="sequence" />
<bind node="showIf" to="showIf" />
<bind node="targetModel" to="targetModel" />
<bind node="widget" to="widget" />
<bind node="widgetAttrs" to="widgetAttrs" />
<bind node="valueExpr" to="valueExpr"/>
<bind node="jsonModel" to="jsonModel" search="self.name = :jsonModel" update="true" alias="jsonModel" create="false" />
<bind node="targetJsonModel" to="targetJsonModel" search="self.name = :targetJsonModel" update="true" create="false" />
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
<bind node="modelAppBuilder" alias="modelAppBuilder" />
</bind>
<bind node="fields/field" type="com.axelor.meta.db.MetaJsonField" if="jsonModel == null"
search="self.name = :name and self.model = :model and self.modelField = :modelField and self.jsonModel is null"
call="com.axelor.studio.service.ImportService:importJsonField" update="true">
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="type" to="type" />
<bind node="defaultValue" to="defaultValue" />
<bind node="domain" to="domain" />
<bind node="enumType" to="enumType" />
<bind node="help" to="help" />
<bind node="formView" to="formView" />
<bind node="gridView" to="gridView" />
<bind node="hidden" to="hidden" />
<bind node="visibleInGrid" to="visibleInGrid" />
<bind node="hideIf" to="hideIf" />
<bind node="isWkf" to="isWkf" />
<bind node="maxSize" to="maxSize" />
<bind node="minSize" to="minSize" />
<bind node="model" to="model" />
<bind node="modelField" to="modelField" />
<bind node="nameField" to="nameField" />
<bind node="onChange" to="onChange" />
<bind node="onClick" to="onClick" />
<bind node="precision" to="precision" />
<bind node="regex" to="regex" />
<bind node="required" to="required" />
<bind node="requiredIf" to="requiredIf" />
<bind node="readonly" to="readonly" />
<bind node="scale" to="scale" />
<bind node="selection" to="selection" />
<bind node="sequence" to="sequence" />
<bind node="showIf" to="showIf" />
<bind node="targetModel" to="targetModel" />
<bind node="widget" to="widget" />
<bind node="widgetAttrs" to="widgetAttrs" />
<bind node="valueExpr" to="valueExpr"/>
<bind node="jsonModel" to="jsonModel" search="self.name = :jsonModel" update="true" create="false" />
<bind node="targetJsonModel" to="targetJsonModel" search="self.name = :targetJsonModel" update="true" create="false" />
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false"/>
<bind node="modelAppBuilder" alias="modelAppBuilder" create="false"/>
</bind>
</input>
<input file="bpm.xml" root="bpm" >
<bind node="models/model" type="com.axelor.meta.db.MetaJsonModel" search="self.name = :name" create="false" call="com.axelor.studio.service.ImportService:importAppMetaJsonModel" update="true">
<bind node="name" to="name" />
</bind>
</input>
<input file="bpm.xml" root="bpm" >
<bind node="selections/selection" type="com.axelor.meta.db.MetaSelect" search="self.name = :name" update="true">
<bind node="name" to="name"/>
<bind node="module" to="module"/>
<bind node="priority" to="priority"/>
<bind node="items/option" to="items">
<bind node="title" to="title"/>
<bind node="value" to="value"/>
<bind node="icon" to="icon"/>
<bind node="data" to="data"/>
<bind node="order" to="order"/>
<bind node="hidden" to="hidden"/>
<bind node="select" to="select" search="self.name = :select" create="false"/>
</bind>
<bind node="isCustom" to="isCustom"/>
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
</bind>
<bind node="chartBuilders/chartBuilder" type="com.axelor.studio.db.ChartBuilder" search="self.name = :name" call="com.axelor.studio.service.ImportService:importChartBuilder" update="true">
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="chartType" to="chartType" />
<bind node="isJson" to="isJson" />
<bind node="model" to="model" alias="_model"/>
<bind node="groupOn" to="groupOn" search="self.name = :groupOn and self.metaModel.fullName = :_model" />
<bind node="groupOnJson" to="groupOnJson" search="self.name = :groupOnJson and self.jsonModel.name = :_model" />
<bind node="groupDateType" to="groupDateType" />
<bind node="groupOnTarget" to="groupOnTarget" />
<bind node="groupOnTargetType" to="groupOnTargetType" />
<bind node="isJsonGroupOn" to="isJsonGroupOn" />
<bind node="isJsonAggregateOn" to="isJsonAggregateOn" />
<bind node="isJsonDisplayField" to="isJsonDisplayField" />
<bind node="aggregateOnJson" to="aggregateOnJson" search="self.name = :aggregateOnJson and self.jsonModel.name = :_model" create="false" />
<bind node="aggregateOn" to="aggregateOn" search="self.name = :aggregateOn and self.metaModel.fullName = :_model" create="false" />
<bind node="aggregateOnTarget" to="aggregateOnTarget" />
<bind node="aggregateDateType" to="aggregateDateType" />
<bind node="aggregateOnTargetType" to="aggregateOnTargetType" />
<bind node="displayField" to="displayField" search="self.name = :displayField and self.metaModel.fullName = :_model" create="false"/>
<bind node="displayFieldJson" to="displayFieldJson" search="self.name = :displayFieldJson and self.jsonModel.name = :_model" create="false" />
<bind node="displayType" to="displayType" />
<bind node="filters/filter" to="filterList">
<bind node="metaField" to="metaField" search="self.name = :metaField and self.metaModel.fullName = :_model" create="false" />
<bind node="metaJsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :_model" create="false" />
<bind node="operator" to="operator" />
<bind node="targetField" to="targetField"/>
<bind node="targetType" to="targetType"/>
<bind node="value" to="value"/>
<bind node="defaultValue" to="defaultValue"/>
<bind node="isParameter" to="isParameter"/>
<bind node="isJson" to="isJson" />
<bind node="isTargetJson" to="isTargetJson" />
<bind node="logicOp" to="logicOp" />
</bind>
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
</bind>
<bind node="dashboardBuilders/dashboardBuilder" type="com.axelor.studio.db.DashboardBuilder" search="self.name = :name" update="true">
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="model" to="model" />
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
</bind>
<bind node="dashletBuilders/dashletBuilder" type="com.axelor.studio.db.DashletBuilder"
search="self.name = :name and self.dashboardBuilder.name = :dashboardBuilder and (self.appBuilder.code = :appBuilder OR self.dashboardBuilder.appBuilder.code = :parentAppBuilder)" update="true">
<bind node="name" to="name" />
<bind node="metaView" to="metaView" search="self.name = :metaView" />
<bind node="dashboardBuilder" to="dashboardBuilder" search="self.name = :dashboardBuilder" create="false" />
<bind node="action" to="action" search="self.name = :action" create="false" />
<bind node="sequence" to="sequence" />
<bind node="viewType" to="viewType" />
<bind node="colspan" to="colspan" />
<bind node="paginationLimit" to="paginationLimit" />
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
<bind node="parentAppBuilder" alias="parentAppBuilder" />
</bind>
</input>
<input file="bpm.xml" root="bpm" >
<bind node="dashboardBuilders/dashboardBuilder" type="com.axelor.studio.db.DashboardBuilder" search="self.name = :name" create="false" call="com.axelor.studio.service.ImportService:importAppDashboardBuilder" update="true">
<bind node="name" to="name" />
</bind>
</input>
<input file="bpm.xml" root="bpm" >
<bind node="actionBuilders/actionBuilder" type="com.axelor.studio.db.ActionBuilder" search="self.name = :name" call="com.axelor.studio.service.ImportService:importActionBuilder" update="true">
<bind node="name" to="name" />
<bind node="typeSelect" to="typeSelect" alias="_type" />
<bind node="model" to="model" alias="_model"/>
<bind node="targetModel" to="targetModel" alias="_targetModel" />
<bind node="title" to="title" />
<bind node="transactional" to="transactional" />
<bind node="scriptType" to="scriptType" />
<bind node="scriptText" to="scriptText" />
<bind node="actionBuilderViews/view" to="actionBuilderViews">
<bind node="viewType" to="viewType" />
<bind node="viewName" to="viewName" />
<bind node="sequence" to="sequence" />
</bind>
<bind node="isJson" to="isJson" alias="_isJson" />
<bind node="domainCondition" to="domainCondition" />
<bind node="viewParams/line" to="viewParams">
<bind node="name" to="name"/>
<bind node="value" to="value"/>
</bind>
<bind node="menuAction" to="menuAction"/>
<bind node="lines/line" to="lines">
<bind node="target" alias="target" />
<bind node="source" alias="source" />
<bind node="metaJsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :target" create="false"/>
<bind node="metaField" to="metaField" search="self.name = :metaField and self.metaModel.fullName = :target" create="false"/>
<bind node="valueJson" to="valueJson" search="self.name = :valueJson and self.jsonModel.name = :source" create="false" />
<bind node="valueField" to="valueField" search="self.name = :valueField and self.metaModel.fullName = :source" create="false" />
<bind node="value" to="value"/>
<bind node="conditionText" to="conditionText"/>
<bind node="filter" to="filter"/>
<bind node="validationTypeSelect" to="validationTypeSelect"/>
<bind node="validationMsg" to="validationMsg"/>
<bind node="name" to="name"/>
<bind node="dummy" to="dummy"/>
<bind node="subLines/line" to="subLines">
<bind node="target" alias="target" />
<bind node="source" alias="source" />
<bind node="metaJsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :target" create="false"/>
<bind node="metaField" to="metaField" search="self.name = :metaField and (self.metaModel.fullName = :target OR self.metaModel.name = :target)" create="false" />
<bind node="valueJson" to="valueJson" search="self.name = :valueJson and self.jsonModel.name = :source" create="false" />
<bind node="valueField" to="valueField" search="self.name = :valueField and (self.metaModel.fullName = :source OR self.metaModel.fullName = :source)" create="false" />
<bind node="value" to="value"/>
<bind node="conditionText" to="conditionText"/>
<bind node="filter" to="filter"/>
<bind node="validationTypeSelect" to="validationTypeSelect"/>
<bind node="validationMsg" to="validationMsg"/>
<bind node="name" to="name"/>
<bind node="dummy" to="dummy"/>
<bind node="subLines/line" to="subLines">
<bind node="target" alias="target" />
<bind node="source" alias="source" />
<bind node="metaJsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :target" create="false"/>
<bind node="metaField" to="metaField" search="self.name = :metaField and (self.metaModel.fullName = :target OR self.metaModel.name = :target)" create="false" />
<bind node="valueJson" to="valueJson" search="self.name = :valueJson and self.jsonModel.name = :source" create="false"/>
<bind node="valueField" to="valueField" search="self.name = :valueField and (self.metaModel.fullName = :source OR self.metaModel.fullName = :source)" create="false" />
<bind node="value" to="value"/>
<bind node="conditionText" to="conditionText"/>
<bind node="filter" to="filter"/>
<bind node="validationTypeSelect" to="validationTypeSelect"/>
<bind node="validationMsg" to="validationMsg"/>
<bind node="name" to="name"/>
<bind node="dummy" to="dummy"/>
</bind>
</bind>
</bind>
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false" />
</bind>
<bind node="menuBuilders/menuBuilder" type="com.axelor.studio.db.MenuBuilder" search="self.name = :name" call="com.axelor.studio.service.ImportService:importMenuBuilder" update="true">
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="icon" to="icon" />
<bind node="iconBackground" to="iconBackground" />
<bind node="order" to="order" />
<bind node="tag" to="tag" />
<bind node="tagCount" to="tagCount" />
<bind node="tagStyle" to="tagStyle" />
<bind node="top" to="top" />
<bind node="left" to="left" />
<bind node="mobile" to="mobile" />
<bind node="hidden" to="hidden" />
<bind node="link" to="link" />
<bind node="conditionToCheck" to="conditionToCheck" />
<bind node="moduleToCheck" to="moduleToCheck" />
<bind node="showAction" to="showAction" />
<bind node="parentMenu" to="parentMenu" search="self.name = :parentMenu" />
<bind node="actionBuilder" to="actionBuilder" search="self.name = :actionBuilder"/>
<bind node="groups/group" to="groups" search="self.code = :groupCode" update="true" create="false" >
<bind node="text()" to="code" alias="groupCode"/>
</bind>
<bind node="roles/role" to="roles" search="self.name = :roleName" update="true" create="false">
<bind node="text()" to="name" alias="roleName"/>
</bind>
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false"/>
</bind>
<bind node="wkfs/wkf" type="com.axelor.studio.db.Wkf" search="self.name = :name" update="true">
<bind node="name" to="name" />
<bind node="model" to="model" />
<bind node="isJson" to="isJson" alias="_isJson"/>
<bind node="jsonField" to="jsonField" />
<bind node="isTrackFlow" to="isTrackFlow"/>
<bind node="statusField" to="statusField" search="self.jsonModel.name = :model and self.name = :statusField" if="_isJson == 'true'" create="false" />
<bind node="statusField" to="statusField" search="self.model = :model and self.modelField = :jsonField and self.name = :statusField and self.jsonModel is null" if="_isJson == 'false'" create="false" />
<bind node="displayTypeSelect" to="displayTypeSelect" />
<bind node="bpmnXml" to="bpmnXml" />
<bind node="appBuilder" to="appBuilder" search="self.code = :appBuilder" create="false"/>
</bind>
<bind node="nodes/node" type="com.axelor.studio.db.WkfNode" search="self.name = :name and self.wkf.name = :wkf" update="true">
<bind node="wkf" to="wkf" search="self.name = :wkf" create="false"/>
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="xmlId" to="xmlId" />
<bind node="sequence" to="sequence" />
<bind node="nodeType" to="nodeType" />
<bind node="metaFieldModel" alias="metaFieldModel" />
<bind node="metaField" to="metaField" search="self.name = :metaField and self.metaModel.name = :metaFieldModel" create="false"/>
<bind node="roleSet/role" to="roleSet" search="self.name = :roleName" update="false" create="false">
<bind node="text()" to="name" alias="roleName"/>
</bind>
<bind node="metaActionSet/action" to="metaActionSet" search="self.name = :actionName" update="false" create="false">
<bind node="text()" to="name" alias="actionName"/>
</bind>
</bind>
<bind node="nodes/node" type="com.axelor.studio.db.WkfNode" search="self.name = :name and self.wkf.name = :wkf" update="true" create="false">
<bind node="wkf" to="wkf" search="self.name = :wkf" create="false"/>
<bind node="name" to="name" />
<bind node="title" to="title" />
<bind node="xmlId" to="xmlId" />
<bind node="sequence" to="sequence" />
<bind node="nodeType" to="nodeType" />
<bind node="metaFieldModel" alias="metaFieldModel" />
<bind node="metaField" to="metaField" search="self.name = :metaField and self.metaModel.name = :metaFieldModel" />
<bind node="roleSet/role" to="roleSet" search="self.name = :roleName" update="false" create="false">
<bind node="text()" to="name" alias="roleName"/>
</bind>
<bind node="metaActionSet/action" to="metaActionSet" search="self.name = :actionName" update="false" create="false">
<bind node="text()" to="name" alias="actionName"/>
</bind>
</bind>
<bind node="transitions/transition" type="com.axelor.studio.db.WkfTransition" search="self.name = :name and self.wkf.name = :wkf" update="true">
<bind node="wkf" to="wkf" search="self.name = :wkf" update="true" create="false"/>
<bind node="name" to="name" />
<bind node="xmlId" to="xmlId" />
<bind node="isButton" to="isButton" />
<bind node="buttonTitle" to="buttonTitle" />
<bind node="roleSet/role" to="roleSet" search="self.name = :roleName" create="false">
<bind node="text()" to="name" alias="roleName"/>
</bind>
<bind node="conditions/condition" to="conditions">
<bind node="metaModel" alias="metaModel" />
<bind node="jsonModel" alias="jsonModel" />
<bind node="metaField" to="metaField" search="self.name = :metaField and self.metaModel.fullName = :metaModel" create="false"/>
<bind node="metaJsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :jsonModel" create="false" if="jsonModel != null"/>
<bind node="metaJsonField" to="metaJsonField" search="self.name = :metaJsonField and self.model = :model and self.modelField = :modelField" create="false" if="jsonModel == null"/>
<bind node="operator" to="operator" />
<bind node="targetField" to="targetField"/>
<bind node="targetType" to="targetType"/>
<bind node="value" to="value"/>
<bind node="isJson" to="isJson" />
<bind node="isTargetJson" to="isTargetJson" />
<bind node="logicOp" to="logicOp" />
</bind>
<bind node="source" to="source" search="self.name = :source and self.wkf.name = :wkf" update="false" create="false" />
<bind node="target" to="target" search="self.name = :target and self.wkf.name = :wkf" update="false" create="false" />
<bind node="alertTypeSelect" to="alertTypeSelect" />
<bind node="alertMsg" to="alertMsg" />
<bind node="successMsg" to="successMsg" />
</bind>
<bind node="nodes/node" type="com.axelor.studio.db.WkfNode" search="self.name = :nodeName and self.wkf.name = :wkf" update="true" create="false">
<bind node="wkf" to="wkf" search="self.name = :wkf" update="true" create="false" />
<bind node="name" to="name" alias="nodeName" />
<bind node="incomings/incoming" to="incoming" search="self.name = :inNode and self.wkf.name = :wkf" update="false" create="false">
<bind node="text()" to="name" alias="inNode" />
</bind>
<bind node="outgoings/outgoing" to="outgoings" search="self.name = :outNode and self.wkf.name = :wkf" update="false" create="false">
<bind node="text()" to="name" alias="outNode" />
</bind>
</bind>
</input>
<input file="bpm.xml" root="bpm" >
<bind node="wkfs/wkf" type="com.axelor.studio.db.Wkf" search="self.name = :name" create="false" call="com.axelor.studio.service.ImportService:importAppWkf">
<bind node="name" to="name" />
</bind>
</input>
</xml-inputs>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<csv-inputs xmlns="http://axelor.com/xml/ns/data-import"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/data-import http://axelor.com/xml/ns/data-import/data-import_5.2.xsd">
<input file="auth_permission.csv" separator=";" type="com.axelor.auth.db.Permission" search="self.name = :name" call="com.axelor.csv.script.ImportPermission:importPermissionToRole">
<bind to="canRead" eval="can_read == 'x' ? 'true' : 'false'"/>
<bind to="canWrite" eval="can_write == 'x' ? 'true' : 'false'"/>
<bind to="canCreate" eval="can_create == 'x' ? 'true' : 'false'"/>
<bind to="canRemove" eval="can_remove == 'x' ? 'true' : 'false'"/>
<bind to="canExport" eval="can_export == 'x' ? 'true' : 'false'"/>
</input>
<input file="base_appBpm.csv" separator=";" type="com.axelor.apps.base.db.AppBpm" call="com.axelor.csv.script.ImportApp:importApp">
<bind column="dependsOn" to="dependsOnSet" search="self.code in :dependsOn" eval="dependsOn.split(',') as List"/>
</input>
<input file="meta_metaMenu.csv" separator=";" type="com.axelor.meta.db.MetaMenu" search="self.name = :name" update="true" />
</csv-inputs>

View File

@ -0,0 +1,2 @@
"name";"object";"can_read";"can_write";"can_create";"can_remove";"can_export";"condition";"conditionParams";"roleName"
"perm.studio.all";"com.axelor.studio.db.*";"x";"x";"x";"x";"x";;;"Admin"
1 name object can_read can_write can_create can_remove can_export condition conditionParams roleName
2 perm.studio.all com.axelor.studio.db.* x x x x x Admin

View File

@ -0,0 +1,2 @@
"importId";"name";"code";"installOrder";"description";"imagePath";"modules";"dependsOn";"sequence"
50;"BPM";"bpm";28;"Business Process Modeling";"app-bpm.png";"axelor-studio";;29
1 importId name code installOrder description imagePath modules dependsOn sequence
2 50 BPM bpm 28 Business Process Modeling app-bpm.png axelor-studio 29

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,15 @@
"name";"roles.name"
"app-builder-root";"Admin"
"app-builder-models-views";"Admin"
"app-builder-models-views-model-studio";"Admin"
"app-builder-models-views-custom-models";"Admin"
"app-builder-models-views-custom-fields";"Admin"
"app-builder-bpm";"Admin"
"app-builder-bpm-process-studio";"Admin"
"app-builder-bpm-process-tracking";"Admin"
"app-builder-bpm-actions-reporting";"Admin"
"app-builder-bpm-actions-reporting-chart-builders";"Admin"
"app-builder-bpm-actions-reporting-dashboard-builders";"Admin"
"app-builder-bpm-actions-reporting-action-builders";"Admin"
"app-builder-bpm-actions-reporting-menu-builders";"Admin"
"app-builder-bpm-apps-configurator";"Admin"
1 name roles.name
2 app-builder-root Admin
3 app-builder-models-views Admin
4 app-builder-models-views-model-studio Admin
5 app-builder-models-views-custom-models Admin
6 app-builder-models-views-custom-fields Admin
7 app-builder-bpm Admin
8 app-builder-bpm-process-studio Admin
9 app-builder-bpm-process-tracking Admin
10 app-builder-bpm-actions-reporting Admin
11 app-builder-bpm-actions-reporting-chart-builders Admin
12 app-builder-bpm-actions-reporting-dashboard-builders Admin
13 app-builder-bpm-actions-reporting-action-builders Admin
14 app-builder-bpm-actions-reporting-menu-builders Admin
15 app-builder-bpm-apps-configurator Admin

View File

@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8"?>
<xml-inputs xmlns="http://axelor.com/xml/ns/data-import"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/data-import http://axelor.com/xml/ns/data-import/data-import_5.2.xsd">
<input file="bpm_appBuilder.xml" root="app-builders">
<bind node="app-builder" type="com.axelor.studio.db.AppBuilder" call="com.axelor.studio.service.ImportService:importAppBuilderImg">
<bind node="name" to="name" />
<bind node="code" to="code" />
<bind node="description" to="description" />
<bind node="sequence" to="sequence" />
<bind node="depends" alias="depends" />
<bind to="dependsOnSet" alias="deps" search="self.code in :deps" eval="depends.split(',') as List" update="true" />
<bind node="image/@name" alias="fileName"/>
<bind node="image" alias="imageData" />
</bind>
</input>
<input file="bpm_metaJsonModel.xml" root="json-models">
<bind node="json-model" type="com.axelor.meta.db.MetaJsonModel" call="com.axelor.studio.service.ImportService:importMetaJsonModel">
<bind node="@name" to="name" />
<bind node="@title" to="title" />
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="fields/field" to="fields">
<bind node="@name" to="name"/>
<bind node="@title" to="title" />
<bind node="@type" to="type" />
<bind node="@target-model" to="targetModel"/>
<bind node="@target-json-model" alias="targetJsonModel" to="targetJsonModel" search="self.name = :targetJsonModel" update="true"/>
<bind node="@required" to="required"/>
<bind node="@domain" to="domain"/>
<bind to="model" eval="'com.axelor.meta.db.MetaJsonRecord'" />
<bind to="modelField" eval="'attrs'" />
<bind node="@sequence" to="sequence"/>
<bind node="@onChange" to="onChange" />
<bind node="@visibleInGrid" to="visibleInGrid" />
</bind>
</bind>
<bind node="json-field" type="com.axelor.meta.db.MetaJsonField" call="com.axelor.studio.service.ImportService:importMetaJsonField">
<bind node="@name" to="name" />
<bind node="@title" to="title" />
<bind node="@type" to="type" />
<bind node="@model" to="model" />
<bind node="@modelField" to="modelField" />
<bind node="@onClick" to="onClick" />
<bind node="@target-json-model" alias="targetJsonModel" to="targetJsonModel" search="self.name = :targetJsonModel" update="true"/>
<bind node="@jsonModel" to="jsonModel" search="self.name = :jsonModel" update="true" />
<bind node="@sequence" to="sequence"/>
<bind node="@onChange" to="onChange" />
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="@showIf" to="showIf" />
</bind>
</input>
<input file="bpm_chartBuilder.xml" root="chart-builders">
<bind node="chart-builder" type="com.axelor.studio.db.ChartBuilder" call="com.axelor.studio.service.ImportService:importChartBuilder">
<bind node="@name" to="name" />
<bind node="@title" to="title" />
<bind node="@type" to="chartType" />
<bind node="@json" to="isJson" />
<bind node="@model" to="model" alias="_model"/>
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="@groupOnJson" to="groupOnJson" search="self.name = :groupOnJson and self.jsonModel.name = :_model" />
<bind node="@groupOn" to="groupOn" search="self.name = :groupOn and self.metaModel.fullName = :_model" />
<bind node="@groupDateType" to="groupDateType" />
<bind node="@groupOnTarget" to="groupOnTarget" />
<bind node="@groupOnTargetType" to="groupOnTargetType" />
<bind node="@isJsonGroupOn" to="isJsonGroupOn" />
<bind node="@isJsonAggregateOn" to="isJsonAggregateOn" />
<bind node="@isJsonDisplayField" to="isJsonDisplayField" />
<bind node="@aggregateOnJson" to="aggregateOnJson" search="self.name = :aggregateOnJson and self.jsonModel.name = :_model" />
<bind node="@aggregateOn" to="aggregateOn" search="self.name = :aggregateOn and self.metaModel.fullName = :_model" />
<bind node="@aggregateOnTarget" to="aggregateOnTarget" />
<bind node="@aggregateOnTargetType" to="aggregateOnTargetType" />
<bind node="@displayFieldJson" to="displayFieldJson" search="self.name = :displayFieldJson and self.jsonModel.name = :_model" />
<bind node="@displayField" to="displayField" search="self.name = :displayField and self.metaModel.fullName = :_model" />
<bind node="filters/filter" to="filterList">
<bind node="@json" to="isJson" />
<bind node="@targetType" to="targetType" />
<bind node="@operator" to="operator" />
<bind node="@targetField" to="targetField"/>
<bind node="@jsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :_model" />
<bind node="@field" to="metaField" search="self.name = :metaField and self.metaModel.fullName = :_model" />
<bind node="@value" to="value"/>
<bind node="@isParameter" to="isParameter"/>
</bind>
</bind>
</input>
<input file="bpm_dashboardBuilder.xml" root="dashboard-builders">
<bind node="dashboard-builder" type="com.axelor.studio.db.DashboardBuilder" call="com.axelor.studio.service.ImportService:importDashboardBuilder">
<bind node="@name" to="name" />
<bind node="@title" to="title" />
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="dashlets/dashlet" to="dashletBuilderList">
<bind node="@name" to="name" />
<bind node="@sequence" to="sequence" />
<bind node="@viewType" to="viewType" />
<bind node="@colspan" to="colspan" />
<bind node="@view" to="metaView" search="self.name = :metaView" />
</bind>
</bind>
</input>
<input file="bpm_menuBuilder.xml" root="menu-builders">
<bind node="menu-builder" type="com.axelor.studio.db.MenuBuilder" call="com.axelor.studio.service.ImportService:importMenuBuilder">
<bind node="@name" to="name" />
<bind node="@title" to="title" />
<bind node="@icon" to="icon" />
<bind node="@background" to="iconBackground" />
<bind node="@parent" to="parentMenu" search="self.name = :parentMenu" />
<bind node="@show-action" to="showAction" />
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="action" to="actionBuilder" if="actionName != null">
<bind node="@name" to="name" alias="actionName" />
<bind node="@model" to="model" />
<bind node="@isJson" to="isJson" />
<bind node="@title" to="title" />
<bind to="typeSelect" eval="3"/>
<bind node="views/view" to="actionBuilderViews">
<bind node="@type" to="viewType" />
<bind node="@name" to="viewName" />
<bind node="@sequence" to="sequence" />
</bind>
<bind node="@domain" to="domainCondition" />
<bind node="context/ctx" to="lines">
<bind node="@value" to="value" />
<bind node="@name" to="name" />
</bind>
</bind>
</bind>
</input>
<input file="bpm_actionBuilder.xml" root="action-builders">
<bind node="action-builder" type="com.axelor.studio.db.ActionBuilder" call="com.axelor.studio.service.ImportService:importActionBuilder">
<bind node="@name" to="name" />
<bind node="@isJson" to="isJson" />
<bind node="@typeSelect" to="typeSelect" />
<bind node="@model" to="model" />
<bind node="@targetModel" to="targetModel" />
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="lines/line" to="lines">
<bind node="@metaModel" to="metaModel" />
<bind node="@valueModel" to="valueModel" />
<bind node="@jsonModel" to="jsonModel" />
<bind node="@valueJsonModel" to="valueJsonModel" />
<bind node="@metaField" to="metaField" search="self.name = :metaField and self.metaModel.name = :metaModel" />
<bind node="@valueField" to="valueField" search="self.name = :valueField and self.metaModel.name = :valueModel" />
<bind node="@jsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :jsonModel" />
<bind node="@valueJsonField" to="valueJson" search="self.name = :valueJson and self.jsonModel.name = :valueJsonModel" />
<bind node="@name" to="name" if="metaField == null &amp;&amp; metaJsonField == null"/>
<bind node="@metaField" to="name" if="metaField != null"/>
<bind node="@jsonField" to="name" if="metaJsonField != null"/>
<bind node="@value" to="value"/>
<bind node="@filter" to="filter"/>
<bind node="@dummy" to="dummy"/>
<bind node="subLines/line" to="subLines">
<bind node="@metaModel" to="metaModel" />
<bind node="@valueModel" to="valueModel" />
<bind node="@jsonModel" to="jsonModel" />
<bind node="@valueJsonModel" to="valueJsonModel" />
<bind node="@metaField" to="metaField" search="self.name = :metaField and self.metaModel.name = :metaModel" />
<bind node="@valueField" to="valueField" search="self.name = :valueField and self.metaModel.name = :valueModel" />
<bind node="@jsonField" to="metaJsonField" search="self.name = :metaJsonField and self.jsonModel.name = :jsonModel" />
<bind node="@valueJsonField" to="valueJson" search="self.name = :valueJson and self.jsonModel.name = :valueJsonModel" />
<bind node="@name" to="name" if="metaField == null &amp;&amp; metaJsonField == null"/>
<bind node="@metaField" to="name" if="metaField != null"/>
<bind node="@jsonField" to="name" if="metaJsonField != null"/>
<bind node="@value" to="value"/>
<bind node="@filter" to="filter"/>
<bind node="@dummy" to="dummy"/>
</bind>
</bind>
</bind>
</input>
<input file="bpm_workflow.xml" root="wkfs" >
<bind node="wkf" type="com.axelor.studio.db.Wkf">
<bind node="@appBuilder" to="appBuilder" search="self.code = :appBuilder" />
<bind node="@name" to="name" />
<bind node="@isJson" to="isJson" />
<bind node="@model" to="model" />
<bind node="@statusField" to="statusField" search="self.jsonModel.name = :model and self.name = :statusField" update="true" />
<bind node="@displayTypeSelect" to="displayTypeSelect" />
<bind node="xml" to="bpmnXml" />
</bind>
<bind node="wkfNode" type="com.axelor.studio.db.WkfNode">
<bind node="@name" to="name" />
<bind node="@title" to="title" />
<bind node="@wkf" to="wkf" search="self.name = :wkf" update="true"/>
<bind node="@sequence" to="sequence" />
<bind node="@nodeType" to="nodeType" />
<bind node="@xmlId" to="xmlId" />
</bind>
<bind node="transition" type="com.axelor.studio.db.WkfTransition">
<bind node="@name" to="name" />
<bind node="@wkf" to="wkf" search="self.name = :wkf" update="true"/>
<bind node="@source" to="source" search="self.name = :source and self.wkf.name = :wkf" update="true"/>
<bind node="@target" to="target" search="self.name = :target and self.wkf.name = :wkf" update="true"/>
<bind node="@isButton" to="isButton" />
<bind node="@buttonTitle" to="buttonTitle" />
<bind node="@alertTypeSelect" to="alertTypeSelect" />
<bind node="@alertMsg" to="alertMsg" />
<bind node="@successMsg" to="successMsg" />
<bind node="@xmlId" to="xmlId" />
</bind>
<bind node="node" type="com.axelor.studio.db.WkfNode" search="self.name = :nodeName and self.wkf.name = :wkf" update="true">
<bind node="@wkf" to="wkf" search="self.name = :wkf" update="true" />
<bind node="@name" to="name" alias="nodeName" />
<bind node="incomings/incoming" to="incoming" search="self.name = :name and self.wkf.name = :wkf" update="true">
<bind node="@name" to="name" />
</bind>
<bind node="outgoings/outgoing" to="outgoings" search="self.name = :name and self.wkf.name = :wkf" update="true">
<bind node="@name" to="name" />
</bind>
</bind>
</input>
<input file="bpm_workflow.xml" root="wkfs" >
<bind node="workflow" type="com.axelor.studio.db.Wkf" search="self.name = :name" update="true" call="com.axelor.studio.service.ImportService:importWkf">
<bind node="@name" to="name" />
</bind>
</input>
<input file="bpm_translation.xml" root="meta-translations" >
<bind node="meta-translation" type="com.axelor.meta.db.MetaTranslation" search="self.key = :key and self.language = :language">
<bind node="@key" to="key" />
<bind node="@message" to="message" />
<bind node="@language" to="language"/>
</bind>
</input>
</xml-inputs>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<action-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<action-builder name="action-create-invoice-from-timesheet"
isJson="false"
typeSelect="0"
appBuilder="PRD"
model="com.axelor.apps.hr.db.Timesheet"
targetModel="com.axelor.apps.account.db.Invoice">
<lines>
<line metaField="partner" metaModel="Invoice" valueField="company" valueModel="Timesheet" value="$.company.partner" />
<line metaField="company" metaModel="Invoice" valueField="company" valueModel="Timesheet" value="$.company" />
<line metaField="currency" metaModel="Invoice" valueField="company" valueModel="Timesheet" value="$.company.currency" />
<line metaField="operationTypeSelect" metaModel="Invoice" value="3"/>
<line metaField="paymentCondition" metaModel="Invoice" filter="self.code = '15D_EOM'"/>
<line metaField="paymentMode" metaModel="Invoice" filter="self.code = 'OUT_WT'"/>
<line name="total" value="$.timesheetLineList.sum($.hoursDuration*$$.user.employee.hourlyRate)" dummy="true"/>
<line metaField="exTaxTotal" metaModel="Invoice" value="_$.total" />
<line metaField="inTaxTotal" metaModel="Invoice" value="_$.total" />
<line metaField="invoiceLineList" metaModel="Invoice" valueField="timesheetLineList" valueModel="Timesheet" value="$.timesheetLineList">
<subLines>
<line metaField="exTaxTotal" metaModel="InvoiceLine" value="$.hoursDuration*$$.user.employee.hourlyRate" />
<line metaField="price" metaModel="InvoiceLine" value="$$.user.employee.hourlyRate" />
<line metaField="product" metaModel="InvoiceLine" valueModel="TimesheetLine" valueField="product" value="$.product" />
<line metaField="productName" metaModel="InvoiceLine" valueModel="TimesheetLine" valueField="product" value="$.product.name" />
<line metaField="qty" metaModel="InvoiceLine" valueModel="TimesheetLine" valueField="hoursDuration" value="$.hoursDuration" />
<line metaField="unit" metaModel="InvoiceLine" filter="self.name = 'Hour'"/>
</subLines>
</line>
</lines>
</action-builder>
<action-builder name="action-timesheet-line-invert-to-invoice"
isJson="false"
typeSelect="1"
appBuilder="PRD"
model="com.axelor.apps.hr.db.Timesheet">
<lines>
<line metaField="timesheetLineList" metaModel="Timesheet" value="$.timesheetLineList" valueModel="Timesheet" valueField="timesheetLineList">
<subLines>
<line metaField="toInvoice" metaModel="TimesheetLine" value="!$.toInvoice" valueModel="TimesheetLine" valueField="toInvoice" />
</subLines>
</line>
</lines>
</action-builder>
<action-builder name="action-create-product-order-from-category"
isJson="true"
typeSelect="0"
appBuilder="PRD"
model="ProductCategory"
targetModel="ProductOrder">
<lines>
<line jsonField="customer" jsonModel="ProductOrder" filter="self.name = 'Axelor'" />
<line jsonField="status" jsonModel="ProductOrder" value="1" />
<line jsonField="total" jsonModel="ProductOrder" value="$.products.sum($.price)" />
<line jsonField="lines" jsonModel="ProductOrder" value="$.products" valueJsonModel="ProductCategory" valueJsonField="products">
<subLines>
<line jsonField="product" jsonModel="ProductOrderLine" value="$" />
<line jsonField="price" jsonModel="ProductOrderLine" value="$.price" valueJsonModel="Product" valueJsonField="price" />
<line jsonField="qty" jsonModel="ProductOrderLine" value="1" />
<line jsonField="total" jsonModel="ProductOrderLine" value="$.price" valueJsonModel="Product" valueJsonField="price" />
</subLines>
</line>
</lines>
</action-builder>
<action-builder name="action-product-order-line-update-total"
isJson="true"
typeSelect="1"
appBuilder="PRD"
model="ProductOrderLine"
targetModel="ProductOrderLine">
<lines>
<line jsonField="total" jsonModel="ProductOrderLine" value="$.price*$.qty" />
</lines>
</action-builder>
<action-builder name="action-product-order-line-get-product-details"
isJson="true"
typeSelect="1"
appBuilder="PRD"
model="ProductOrderLine"
targetModel="ProductOrderLine">
<lines>
<line jsonField="price" jsonModel="ProductOrderLine" valueJson="Product" valueJsonModel="ProductOrderLine" valueJsonField="product" value="$.product.price" />
</lines>
</action-builder>
<action-builder name="action-product-order-update-total"
isJson="true"
typeSelect="1"
appBuilder="PRD"
model="ProductOrder"
targetModel="ProductOrder">
<lines>
<line jsonField="total" jsonModel="ProductOrder" valueJson="Product" valueJsonModel="ProductOrder" valueJsonField="lines" value="$.lines.sum($.total)" />
</lines>
</action-builder>
</action-builders>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<chart-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<chart-builder name="product-order-chart" title="Product orders per month" appBuilder="PRD"
type="bar" model="ProductOrder" json="true" groupOnJson="orderDate" groupOnTarget="orderDate" groupOnTargetType="Date" groupDateType="month"
isJsonGroupOn="true" isJsonAggregateOn="true" isJsonDisplayField="true"
aggregateOnJson="customer" aggregateOnTarget="customer.fullName" aggregateOnTargetType="String" displayFieldJson="total">
<filters>
<filter json="true" targetType="many-to-one" operator="notNull" targetField="customer" jsonField="customer" />
<filter json="true" targetType="date" operator="&lt;=" targetField="orderDate" value="$date" jsonField="orderDate" />
</filters>
</chart-builder>
<chart-builder name="product-order-per-author-per-category" title="Product orders per supplier per category" appBuilder="PRD"
type="pie" model="ProductOrderLine" json="true" groupOnJson="product"
isJsonGroupOn="true" isJsonAggregateOn="true" isJsonDisplayField="true"
groupOnTarget="product.supplier.name" groupOnTargetType="String" displayFieldJson="total">
<filters>
<filter json="true" targetType="json-many-to-one" operator="=" targetField="product.category" isParameter="true" jsonField="product" />
</filters>
</chart-builder>
<!-- <chart-builder name="sal" title="Product sale per category" -->
<!-- type="pie" model="com.axelor.apps.sale.db.SaleOrderLine" groupOn="product" -->
<!-- groupOnTarget="product.productCategory.name" displayField="exTaxTotal"> -->
<!-- <filters> -->
<!-- <filter targetType="many-to-one" operator="=" targetField="product.productFamily" isParameter="true" field="product" /> -->
<!-- <filter targetType="Integer" operator="in" targetField="saleOrder.statusSelect" field="saleOrder" value="3,4" /> -->
<!-- </filters> -->
<!-- </chart-builder> -->
<!-- <chart-builder name="products-order-per-month-per-customer" title="Product sale per month per customer" -->
<!-- type="bar" model="com.axelor.apps.sale.db.SaleOrderLine" groupOn="saleOrder" groupOnTarget="saleOrder.orderDate" groupOnTargetType="LocalDate" groupDateType="month" -->
<!-- aggregateOn="saleOrder" aggregateOnTarget="saleOrder.clientPartner.fullName" displayField="exTaxTotal"> -->
<!-- <filters> -->
<!-- <filter targetType="Integer" operator="in" targetField="saleOrder.statusSelect" value="3,4" field="saleOrder" /> -->
<!-- <filter targetType="LocalDate" operator="notNull" targetField="saleOrder.orderDate" field="saleOrder" /> -->
<!-- <filter targetType="many-to-one" operator="=" targetField="product" isParameter="true" field="product" /> -->
<!-- </filters> -->
<!-- </chart-builder> -->
</chart-builders>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<dashboard-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<dashboard-builder name="product-dashboard" title="Product dashboard" appBuilder="PRD">
<dashlets>
<dashlet name="Product orders" sequence="0" viewType="grid" colspan="12" view="custom-model-ProductOrder-grid" />
<dashlet name="Product orders per month" sequence="1" viewType="chart" colspan="6" view="product-order-chart" />
<dashlet name="Product orders per supplier per category" sequence="2" viewType="chart" colspan="6" view="product-order-per-author-per-category" />
</dashlets>
</dashboard-builder>
<!-- <dashboard-builder name="product-order-dashboard" title="Product dashboard"> -->
<!-- <dashlets> -->
<!-- <dashlet name="All products" sequence="0" viewType="grid" colspan="12" view="product-grid" /> -->
<!-- <dashlet name="Product sale per category" sequence="1" viewType="chart" colspan="6" view="products-order-per-category" /> -->
<!-- <dashlet name="Product sale per month per customer" sequence="2" viewType="chart" colspan="6" view="products-order-per-month-per-customer" /> -->
<!-- </dashlets> -->
<!-- </dashboard-builder> -->
</dashboard-builders>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<menu-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<menu-builder name="bpm-product-root" title="Products" icon="fa-cube" background="red" appBuilder="PRD" />
<menu-builder name="menu-json-model-ProductCategory" title="Product category" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="all.json.ProductCategory" title="Product category" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-ProductCategory-grid" sequence="1" />
<view type="form" name="custom-model-ProductCategory-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'ProductCategory'" />
</context>
</action>
</menu-builder>
<menu-builder name="menu-json-model-Product" title="Product" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="all.json.Product" title="Product" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-Product-grid" sequence="1" />
<view type="form" name="custom-model-Product-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'Product'" />
</context>
</action>
</menu-builder>
<menu-builder name="menu-json-model-ProductOrder" title="Product order" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="all.json.ProductOrder" title="Product order" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-ProductOrder-grid" sequence="1" />
<view type="form" name="custom-model-ProductOrder-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'ProductOrder'" />
</context>
</action>
</menu-builder>
<menu-builder name="menu-json-model-ProductOrderLine" title="Product order line" parent="bpm-product-root" show-action="true" appBuilder="PRD" >
<action name="all.json.ProductOrderLine" title="Product order line" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-ProductOrderLine-grid" sequence="1" />
<view type="form" name="custom-model-ProductOrderLine-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'ProductOrderLine'" />
</context>
</action>
</menu-builder>
<menu-builder name="bpm-dashboard-product-dashboard" title="Product dashboard" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="bpm.dashboard.product.dashboard" title="Product dashboard" isJson="true">
<views>
<view type="dashboard" name="product-dashboard" sequence="1" />
</views>
</action>
</menu-builder>
<!-- <menu-builder name="bpm-dashboard-crm-dashboard" title="Crm dashboard" parent="bpm-dashboard-root" show-action="true"> -->
<!-- <action name="bpm.dashboard.sales.dashboard" title="Sales dashboard"> -->
<!-- <views> -->
<!-- <view type="dashboard" name="sales-order-dashboard" /> -->
<!-- </views> -->
<!-- </action> -->
<!-- </menu-builder> -->
</menu-builders>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<json-models xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<json-model name="ProductCategory" title="Product category" appBuilder="PRD">
<fields>
<field name="name" title="Name" required="true" type="string" sequence="1" visibleInGrid="true"/>
<field name="code" title="Code" type="string" sequence="2" visibleInGrid="true"/>
</fields>
</json-model>
<json-model name="Product" title="Product" appBuilder="PRD">
<fields>
<field name="name" title="Name" required="true" type="string" sequence="1" visibleInGrid="true"/>
<field name="code" title="Code" type="string" sequence="2" visibleInGrid="true"/>
<field name="price" title="Price" type="decimal" sequence="3" visibleInGrid="true"/>
<field name="launchDate" title="Launch Date" type="date" sequence="4"/>
<field name="supplier" title="Supplier" type="many-to-one" target-model="com.axelor.apps.base.db.Partner" sequence="5"/>
<field name="category" title="Main Category" type="json-many-to-one" target-json-model="ProductCategory" sequence="6" visibleInGrid="true"/>
</fields>
</json-model>
<json-model name="ProductOrderLine" title="Product order line" appBuilder="PRD">
<fields>
<field name="product" title="Product" type="json-many-to-one" target-json-model="Product" sequence="1" onChange="action-product-order-line-get-product-details,action-product-order-line-update-total" visibleInGrid="true"/>
<field name="price" title="Price" type="decimal" sequence="2" onChange="action-product-order-line-update-total" visibleInGrid="true"/>
<field name="qty" title="Qty" type="integer" sequence="3" onChange="action-product-order-line-update-total" visibleInGrid="true"/>
<field name="total" title="Total" type="decimal" sequence="4" visibleInGrid="true"/>
</fields>
</json-model>
<json-model name="ProductOrder" title="Product order" appBuilder="PRD">
<fields>
<field name="reference" title="Ref" type="string" sequence="1" visibleInGrid="true"/>
<field name="customer" title="Customer" type="many-to-one" target-model="com.axelor.apps.base.db.Partner" domain="isCustomer = true" sequence="2" visibleInGrid="true"/>
<field name="orderDate" title="Order Date" type="date" sequence="3" visibleInGrid="true"/>
<field name="total" title="Total" type="decimal" sequence="4" visibleInGrid="true"/>
<field name="lines" title="Lines" type="json-one-to-many" target-json-model="ProductOrderLine" sequence="5" onChange="action-product-order-update-total"/>
<field name="status" title="Status" type="integer" sequence="6" visibleInGrid="true"/>
</fields>
</json-model>
<json-field name="createInvoice" type="button"
model="com.axelor.apps.hr.db.Timesheet" modelField="attrs"
onClick="action-create-invoice-from-timesheet" sequence="1"
appBuilder="PRD" showIf="$record.user.employee"
title="Create invoice"/>
<json-field name="createPlanning" type="button"
model="com.axelor.apps.project.db.Project" modelField="attrs"
onClick="action-create-project-planning" sequence="1" appBuilder="PRD"
title="Create planning"/>
<json-field name="invertToInvoice" title="Check/Uncheck 'to invoice'" type="button" model="com.axelor.apps.hr.db.Timesheet" modelField="attrs" onClick="action-timesheet-line-invert-to-invoice" sequence="2" appBuilder="PRD"/>
<json-field name="products" title="Products" type="json-many-to-many" target-json-model="Product" model="com.axelor.meta.db.MetaJsonRecord" modelField="attrs" jsonModel="ProductCategory" sequence="3" appBuilder="PRD"/>
<json-field name="createProduct" title="Create product order" type="button" onClick="action-create-product-order-from-category" model="com.axelor.meta.db.MetaJsonRecord" modelField="attrs" jsonModel="ProductCategory" sequence="4" appBuilder="PRD"/>
</json-models>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<meta-translations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<meta-translation key="Launch Date" message="Date de lancement" language="fr"/>
<meta-translation key="Main Category" message="Catégorie principale" language="fr"/>
<meta-translation key="Product order line" message="Ligne de commande produit" language="fr"/>
<meta-translation key="Product order" message="Commande produit" language="fr"/>
<meta-translation key="Create product order" message="Créer commande produit" language="fr"/>
<meta-translation key="Product dashboard" message="Tableau de bord produit" language="fr"/>
<meta-translation key="Product orders per month" message="Commandes produit par mois" language="fr"/>
<meta-translation key="Product orders per supplier per category" message="Commandes produit par fournisseurs et catégorie" language="fr"/>
<meta-translation key="Reset" message="Réinitialiser" language="fr"/>
<meta-translation key="Are you sure wants to validate." message="Êtes-vous sûr de vouloir valider cette commande?" language="fr"/>
<meta-translation key="Order validated" message="Commande validée" language="fr"/>
<meta-translation key="Are you sure wants to cancel ?" message="Êtes-vous sûr de vouloir annuler cette commande??" language="fr"/>
<meta-translation key="Order finished." message="Commande terminée" language="fr"/>
<meta-translation key="Check/Uncheck 'to invoice'" message="Cocher/Décocher 'A facturer'" language="fr"/>
</meta-translations>

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<wkfs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wkf name="Product Order Flow" isJson="true" model="ProductOrder" statusField="status" displayTypeSelect="0" appBuilder="PRD">
<xml>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="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:x="http://axelor.com" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<process id="Process_1" name="undefined" isExecutable="false" x:id="undefined">
<endEvent id="EndEvent_062urgf" name="Finished">
<incoming>SequenceFlow_18u3b2a</incoming>
</endEvent>
<startEvent id="StartEvent_07npy19" name="Draft">
<incoming>SequenceFlow_1yn5orr</incoming>
<outgoing>SequenceFlow_0qljt6y</outgoing>
</startEvent>
<task id="Task_07my1i6" name="Confirmed">
<incoming>SequenceFlow_0qljt6y</incoming>
<outgoing>SequenceFlow_10bvr21</outgoing>
<outgoing>SequenceFlow_02m6a90</outgoing>
</task>
<sequenceFlow id="SequenceFlow_0qljt6y" name="Confirm" sourceRef="StartEvent_07npy19" targetRef="Task_07my1i6" />
<task id="Task_0k79fbo" name="Validated">
<incoming>SequenceFlow_10bvr21</incoming>
<outgoing>SequenceFlow_18u3b2a</outgoing>
</task>
<sequenceFlow id="SequenceFlow_10bvr21" name="Validate" sourceRef="Task_07my1i6" targetRef="Task_0k79fbo" />
<task id="Task_069h0a2" name="Canceled">
<incoming>SequenceFlow_02m6a90</incoming>
<outgoing>SequenceFlow_1yn5orr</outgoing>
</task>
<sequenceFlow id="SequenceFlow_02m6a90" name="Cancel" sourceRef="Task_07my1i6" targetRef="Task_069h0a2" />
<sequenceFlow id="SequenceFlow_18u3b2a" name="Finish" sourceRef="Task_0k79fbo" targetRef="EndEvent_062urgf" />
<sequenceFlow id="SequenceFlow_1yn5orr" name="Reset" sourceRef="Task_069h0a2" targetRef="StartEvent_07npy19" />
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="EndEvent_062urgf_di" bpmnElement="EndEvent_062urgf">
<dc:Bounds x="747" y="120" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="720" y="156" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="StartEvent_07npy19_di" bpmnElement="StartEvent_07npy19">
<dc:Bounds x="133" y="120" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="87" y="168" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_07my1i6_di" bpmnElement="Task_07my1i6">
<dc:Bounds x="291" y="98" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0qljt6y_di" bpmnElement="SequenceFlow_0qljt6y">
<di:waypoint xsi:type="dc:Point" x="169" y="138" />
<di:waypoint xsi:type="dc:Point" x="291" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="190" y="117" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0k79fbo_di" bpmnElement="Task_0k79fbo">
<dc:Bounds x="492" y="98" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_10bvr21_di" bpmnElement="SequenceFlow_10bvr21">
<di:waypoint xsi:type="dc:Point" x="391" y="138" />
<di:waypoint xsi:type="dc:Point" x="492" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="392" y="105" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_069h0a2_di" bpmnElement="Task_069h0a2">
<dc:Bounds x="500" y="239" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_02m6a90_di" bpmnElement="SequenceFlow_02m6a90">
<di:waypoint xsi:type="dc:Point" x="341" y="178" />
<di:waypoint xsi:type="dc:Point" x="341" y="279" />
<di:waypoint xsi:type="dc:Point" x="500" y="279" />
<bpmndi:BPMNLabel>
<dc:Bounds x="373" y="253.5" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_18u3b2a_di" bpmnElement="SequenceFlow_18u3b2a">
<di:waypoint xsi:type="dc:Point" x="592" y="138" />
<di:waypoint xsi:type="dc:Point" x="747" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="625" y="112" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1yn5orr_di" bpmnElement="SequenceFlow_1yn5orr">
<di:waypoint xsi:type="dc:Point" x="550" y="319" />
<di:waypoint xsi:type="dc:Point" x="550" y="356" />
<di:waypoint xsi:type="dc:Point" x="151" y="356" />
<di:waypoint xsi:type="dc:Point" x="151" y="156" />
<bpmndi:BPMNLabel>
<dc:Bounds x="266" y="330.5" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
]]>
</xml>
</wkf>
<wkfNode wkf="Product Order Flow" name="Draft" title="Draft" nodeType="0" sequence="1" xmlId="StartEvent_07npy19"/>
<wkfNode wkf="Product Order Flow" name="Confirmed" title="Confirmed" nodeType="1" sequence="2" xmlId="Task_07my1i6" />
<wkfNode wkf="Product Order Flow" name="Validated" title="Validated" nodeType="1" sequence="3" xmlId="Task_0k79fbo" />
<wkfNode wkf="Product Order Flow" name="Canceled" title="Canceled" nodeType="1" sequence="4" xmlId="Task_069h0a2"/>
<wkfNode wkf="Product Order Flow" name="Finished" title="Finished" nodeType="2" sequence="5" xmlId="EndEvent_062urgf"/>
<transition wkf="Product Order Flow" name="Confirm" source="Draft" target="Confirmed" isButton="true" buttonTitle="Confirm" xmlId="SequenceFlow_0qljt6y"/>
<transition wkf="Product Order Flow" name="Validate" source="Confirmed" target="Validated" isButton="true" buttonTitle="Validate" xmlId="SequenceFlow_10bvr21" alertTypeSelect="1" alertMsg="Are you sure wants to validate." successMsg="Order validated" />
<transition wkf="Product Order Flow" name="Cancel" source="Confirmed" target="Canceled" isButton="true" buttonTitle="Cancel" xmlId="SequenceFlow_02m6a90" alertTypeSelect="1" alertMsg="Are you sure wants to cancel ?" />
<transition wkf="Product Order Flow" name="Finish" source="Validated" target="Finished" isButton="true" buttonTitle="Finish" xmlId="SequenceFlow_18u3b2a" alertTypeSelect="2" alertMsg="Order finished." />
<transition wkf="Product Order Flow" name="Reset" source="Canceled" target="Draft" isButton="true" buttonTitle="Reset" xmlId="SequenceFlow_1yn5orr" />
<node wkf="Product Order Flow" name="Draft">
<incomings>
<incoming name="Reset" />
</incomings>
<outgoings>
<outgoing name="Confirm" />
</outgoings>
</node>
<node wkf="Product Order Flow" name="Confirmed">
<incomings>
<incoming name="Confirm" />
</incomings>
<outgoings>
<outgoing name="Validate" />
<outgoing name="Cancel" />
</outgoings>
</node>
<node wkf="Product Order Flow" name="Validated">
<incomings>
<incoming name="Validate" />
</incomings>
<outgoings>
<outgoing name="Finish" />
</outgoings>
</node>
<node wkf="Product Order Flow" name="Canceled">
<incomings>
<incoming name="Cancel" />
</incomings>
<outgoings>
<outgoing name="Reset" />
</outgoings>
</node>
<node wkf="Product Order Flow" name="Finished">
<incomings>
<incoming name="Finish" />
</incomings>
</node>
<workflow name="Product Order Flow" />
</wkfs>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<action-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<action-builder name="action-create-invoice-from-timesheet"
isJson="false"
typeSelect="0"
appBuilder="PRD"
model="com.axelor.apps.hr.db.Timesheet"
targetModel="com.axelor.apps.account.db.Invoice">
<lines>
<line metaField="partner" metaModel="Invoice" valueField="company" valueModel="Timesheet" value="$.company.partner" />
<line metaField="company" metaModel="Invoice" valueField="company" valueModel="Timesheet" value="$.company" />
<line metaField="currency" metaModel="Invoice" valueField="company" valueModel="Timesheet" value="$.company.currency" />
<line metaField="operationTypeSelect" metaModel="Invoice" value="3"/>
<line metaField="paymentCondition" metaModel="Invoice" filter="self.code = '15D_EOM'"/>
<line metaField="paymentMode" metaModel="Invoice" filter="self.code = 'OUT_WT'"/>
<line name="total" value="$.timesheetLineList.sum($.hoursDuration*$$.user.employee.hourlyRate)" dummy="true"/>
<line metaField="exTaxTotal" metaModel="Invoice" value="_$.total" />
<line metaField="inTaxTotal" metaModel="Invoice" value="_$.total" />
<line metaField="invoiceLineList" metaModel="Invoice" valueField="timesheetLineList" valueModel="Timesheet" value="$.timesheetLineList">
<subLines>
<line metaField="exTaxTotal" metaModel="InvoiceLine" value="$.hoursDuration*$$.user.employee.hourlyRate" />
<line metaField="price" metaModel="InvoiceLine" value="$$.user.employee.hourlyRate" />
<line metaField="product" metaModel="InvoiceLine" valueModel="TimesheetLine" valueField="product" value="$.product" />
<line metaField="productName" metaModel="InvoiceLine" valueModel="TimesheetLine" valueField="product" value="$.product.name" />
<line metaField="qty" metaModel="InvoiceLine" valueModel="TimesheetLine" valueField="hoursDuration" value="$.hoursDuration" />
<line metaField="unit" metaModel="InvoiceLine" filter="self.name = 'Hour'"/>
</subLines>
</line>
</lines>
</action-builder>
<action-builder name="action-timesheet-line-invert-to-invoice"
isJson="false"
typeSelect="1"
appBuilder="PRD"
model="com.axelor.apps.hr.db.Timesheet">
<lines>
<line metaField="timesheetLineList" metaModel="Timesheet" value="$.timesheetLineList" valueModel="Timesheet" valueField="timesheetLineList">
<subLines>
<line metaField="toInvoice" metaModel="TimesheetLine" value="!$.toInvoice" valueModel="TimesheetLine" valueField="toInvoice" />
</subLines>
</line>
</lines>
</action-builder>
<action-builder name="action-create-product-order-from-category"
isJson="true"
typeSelect="0"
appBuilder="PRD"
model="ProductCategory"
targetModel="ProductOrder">
<lines>
<line jsonField="customer" jsonModel="ProductOrder" filter="self.name = 'Axelor'" />
<line jsonField="status" jsonModel="ProductOrder" value="1" />
<line jsonField="total" jsonModel="ProductOrder" value="$.products.sum($.price)" />
<line jsonField="lines" jsonModel="ProductOrder" value="$.products" valueJsonModel="ProductCategory" valueJsonField="products">
<subLines>
<line jsonField="product" jsonModel="ProductOrderLine" value="$" />
<line jsonField="price" jsonModel="ProductOrderLine" value="$.price" valueJsonModel="Product" valueJsonField="price" />
<line jsonField="qty" jsonModel="ProductOrderLine" value="1" />
<line jsonField="total" jsonModel="ProductOrderLine" value="$.price" valueJsonModel="Product" valueJsonField="price" />
</subLines>
</line>
</lines>
</action-builder>
<action-builder name="action-product-order-line-update-total"
isJson="true"
typeSelect="1"
appBuilder="PRD"
model="ProductOrderLine"
targetModel="ProductOrderLine">
<lines>
<line jsonField="total" jsonModel="ProductOrderLine" value="$.price*$.qty" />
</lines>
</action-builder>
<action-builder name="action-product-order-line-get-product-details"
isJson="true"
typeSelect="1"
appBuilder="PRD"
model="ProductOrderLine"
targetModel="ProductOrderLine">
<lines>
<line jsonField="price" jsonModel="ProductOrderLine" valueJson="Product" valueJsonModel="ProductOrderLine" valueJsonField="product" value="$.product.price" />
</lines>
</action-builder>
<action-builder name="action-product-order-update-total"
isJson="true"
typeSelect="1"
appBuilder="PRD"
model="ProductOrder"
targetModel="ProductOrder">
<lines>
<line jsonField="total" jsonModel="ProductOrder" valueJson="Product" valueJsonModel="ProductOrder" valueJsonField="lines" value="$.lines.sum($.total)" />
</lines>
</action-builder>
</action-builders>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<chart-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<chart-builder name="product-order-chart" title="Commandes produit par mois" appBuilder="PRD"
type="bar" model="ProductOrder" json="true" groupOnJson="orderDate" groupOnTarget="orderDate" groupOnTargetType="Date" groupDateType="month"
isJsonGroupOn="true" isJsonAggregateOn="true" isJsonDisplayField="true"
aggregateOnJson="customer" aggregateOnTarget="customer.fullName" aggregateOnTargetType="String" displayFieldJson="total">
<filters>
<filter json="true" targetType="many-to-one" operator="notNull" targetField="customer" jsonField="customer" />
<filter json="true" targetType="date" operator="&lt;=" targetField="orderDate" value="$date" jsonField="orderDate" />
</filters>
</chart-builder>
<chart-builder name="product-order-per-author-per-category" title="Commandes produit par fournisseurs et catégorie" appBuilder="PRD"
type="pie" model="ProductOrderLine" json="true" groupOnJson="product"
isJsonGroupOn="true" isJsonAggregateOn="true" isJsonDisplayField="true"
groupOnTarget="product.supplier.name" groupOnTargetType="String" displayFieldJson="total">
<filters>
<filter json="true" targetType="json-many-to-one" operator="=" targetField="product.category" isParameter="true" jsonField="product" />
</filters>
</chart-builder>
<!-- <chart-builder name="sal" title="Ventes de produit par catégorie" -->
<!-- type="pie" model="com.axelor.apps.sale.db.SaleOrderLine" groupOn="product" -->
<!-- groupOnTarget="product.productCategory.name" displayField="exTaxTotal"> -->
<!-- <filters> -->
<!-- <filter targetType="many-to-one" operator="=" targetField="product.productFamily" isParameter="true" field="product" /> -->
<!-- <filter targetType="Integer" operator="in" targetField="saleOrder.statusSelect" field="saleOrder" value="3,4" /> -->
<!-- </filters> -->
<!-- </chart-builder> -->
<!-- <chart-builder name="products-order-per-month-per-customer" title="Ventes de produit par mois et par client" -->
<!-- type="bar" model="com.axelor.apps.sale.db.SaleOrderLine" groupOn="saleOrder" groupOnTarget="saleOrder.orderDate" groupOnTargetType="LocalDate" groupDateType="month" -->
<!-- aggregateOn="saleOrder" aggregateOnTarget="saleOrder.clientPartner.fullName" displayField="exTaxTotal"> -->
<!-- <filters> -->
<!-- <filter targetType="Integer" operator="in" targetField="saleOrder.statusSelect" value="3,4" field="saleOrder" /> -->
<!-- <filter targetType="LocalDate" operator="notNull" targetField="saleOrder.orderDate" field="saleOrder" /> -->
<!-- <filter targetType="many-to-one" operator="=" targetField="product" isParameter="true" field="product" /> -->
<!-- </filters> -->
<!-- </chart-builder> -->
</chart-builders>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<dashboard-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<dashboard-builder name="product-dashboard" title="Tableau de bord produit" appBuilder="PRD">
<dashlets>
<dashlet name="Commande produit" sequence="0" viewType="grid" colspan="12" view="custom-model-ProductOrder-grid" />
<dashlet name="Commandes produit par mois" sequence="1" viewType="chart" colspan="6" view="product-order-chart" />
<dashlet name="Commandes produit par fournisseurs et catégorie" sequence="2" viewType="chart" colspan="6" view="product-order-per-author-per-category" />
</dashlets>
</dashboard-builder>
<!-- <dashboard-builder name="product-order-dashboard" title="Tableau de bord produit"> -->
<!-- <dashlets> -->
<!-- <dashlet name="Tous les produits" sequence="0" viewType="grid" colspan="12" view="product-grid" /> -->
<!-- <dashlet name="Ventes de produit par catégorie" sequence="1" viewType="chart" colspan="6" view="products-order-per-category" /> -->
<!-- <dashlet name="Ventes de produit par mois et par client" sequence="2" viewType="chart" colspan="6" view="products-order-per-month-per-customer" /> -->
<!-- </dashlets> -->
<!-- </dashboard-builder> -->
</dashboard-builders>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<menu-builders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<menu-builder name="bpm-product-root" title="Produits" icon="fa-cube" background="red" appBuilder="PRD" />
<menu-builder name="menu-json-model-ProductCategory" title="Catégorie de produit" parent="bpm-product-root" appBuilder="PRD" show-action="true">
<action name="all.json.ProductCategory" title="Catégorie de produit" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-ProductCategory-grid" sequence="1" />
<view type="form" name="custom-model-ProductCategory-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'ProductCategory'" />
</context>
</action>
</menu-builder>
<menu-builder name="menu-json-model-Product" title="Produits" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="all.json.Product" title="Produits" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-Product-grid" sequence="1" />
<view type="form" name="custom-model-Product-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'Product'" />
</context>
</action>
</menu-builder>
<menu-builder name="menu-json-model-ProductOrder" title="Commande produit" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="all.json.ProductOrder" title="Commande produit" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-ProductOrder-grid" sequence="1" />
<view type="form" name="custom-model-ProductOrder-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'ProductOrder'" />
</context>
</action>
</menu-builder>
<menu-builder name="menu-json-model-ProductOrderLine" title="Ligne de commande produit" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="all.json.ProductOrderLine" title="Ligne de commande produit" model="com.axelor.meta.db.MetaJsonRecord"
domain="self.jsonModel = :jsonModel" isJson="true">
<views>
<view type="grid" name="custom-model-ProductOrderLine-grid" sequence="1" />
<view type="form" name="custom-model-ProductOrderLine-form" sequence="2" />
</views>
<context>
<ctx name="jsonModel" value="'ProductOrderLine'" />
</context>
</action>
</menu-builder>
<menu-builder name="bpm-dashboard-product-dashboard" title="Tableau de bord produit" parent="bpm-product-root" show-action="true" appBuilder="PRD">
<action name="bpm.dashboard.product.dashboard" title="Tableau de bord produit" isJson="true">
<views>
<view type="dashboard" name="product-dashboard" sequence="1" />
</views>
</action>
</menu-builder>
<!-- <menu-builder name="bpm-dashboard-crm-dashboard" title="Crm dashboard" parent="bpm-dashboard-root" show-action="true"> -->
<!-- <action name="bpm.dashboard.sales.dashboard" title="Sales dashboard"> -->
<!-- <views> -->
<!-- <view type="dashboard" name="sales-order-dashboard" /> -->
<!-- </views> -->
<!-- </action> -->
<!-- </menu-builder> -->
</menu-builders>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<json-models xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<json-model name="ProductCategory" title="Catégorie de produit" appBuilder="PRD">
<fields>
<field name="name" title="Nom" required="true" type="string" sequence="1" visibleInGrid="true"/>
<field name="code" title="Code" type="string" sequence="2" visibleInGrid="true"/>
</fields>
</json-model>
<json-model name="Product" title="Produit" appBuilder="PRD">
<fields>
<field name="name" title="Nom" required="true" type="string" sequence="1" visibleInGrid="true"/>
<field name="code" title="Code" type="string" sequence="2" visibleInGrid="true"/>
<field name="price" title="Prix" type="decimal" sequence="3" visibleInGrid="true"/>
<field name="launchDate" title="Date de lancement" type="date" sequence="4"/>
<field name="supplier" title="Fournisseur" type="many-to-one" target-model="com.axelor.apps.base.db.Partner" sequence="5"/>
<field name="category" title="Catégorie principale" type="json-many-to-one" target-json-model="ProductCategory" sequence="6" visibleInGrid="true"/>
</fields>
</json-model>
<json-model name="ProductOrderLine" title="Ligne de commande produit" appBuilder="PRD">
<fields>
<field name="product" title="Produit" type="json-many-to-one" target-json-model="Product" sequence="1" onChange="action-product-order-line-get-product-details,action-product-order-line-update-total" visibleInGrid="true"/>
<field name="price" title="Prix" type="decimal" sequence="2" onChange="action-product-order-line-update-total" visibleInGrid="true"/>
<field name="qty" title="Qté" type="integer" sequence="3" onChange="action-product-order-line-update-total" visibleInGrid="true"/>
<field name="total" title="Total" type="decimal" sequence="4" visibleInGrid="true"/>
</fields>
</json-model>
<json-model name="ProductOrder" title="Commande produit" appBuilder="PRD">
<fields>
<field name="reference" title="Réf" type="string" sequence="1" visibleInGrid="true"/>
<field name="customer" title="Client" type="many-to-one" target-model="com.axelor.apps.base.db.Partner" domain="isCustomer = true" sequence="2" visibleInGrid="true"/>
<field name="orderDate" title="Date de commande" type="date" sequence="3" visibleInGrid="true"/>
<field name="total" title="Total" type="decimal" sequence="4" visibleInGrid="true"/>
<field name="lines" title="Lignes" type="json-one-to-many" target-json-model="ProductOrderLine" sequence="5" onChange="action-product-order-update-total"/>
<field name="status" title="Statut" type="integer" sequence="6" visibleInGrid="true"/>
</fields>
</json-model>
<json-field name="createInvoice" type="button"
model="com.axelor.apps.hr.db.Timesheet" modelField="attrs"
onClick="action-create-invoice-from-timesheet" sequence="1"
appBuilder="PRD" showIf="$record.user.employee"
title="Créer facture"/>
<json-field name="createPlanning" type="button"
model="com.axelor.apps.project.db.Project" modelField="attrs"
onClick="action-create-project-planning" sequence="1" appBuilder="PRD"
title="Créer planning"/>
<json-field name="invertToInvoice" title="Cocher/Décocher 'A facturer'" type="button" model="com.axelor.apps.hr.db.Timesheet" modelField="attrs" onClick="action-timesheet-line-invert-to-invoice" sequence="2" appBuilder="PRD"/>
<json-field name="products" title="Produit" type="json-many-to-many" target-json-model="Product" model="com.axelor.meta.db.MetaJsonRecord" modelField="attrs" jsonModel="ProductCategory" sequence="3" appBuilder="PRD"/>
<json-field name="createProduct" title="Créer commande produit" type="button" onClick="action-create-product-order-from-category" model="com.axelor.meta.db.MetaJsonRecord" modelField="attrs" jsonModel="ProductCategory" sequence="4" appBuilder="PRD"/>
</json-models>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<meta-translations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<meta-translation key="Date de lancement" message="Launch Date" language="en"/>
<meta-translation key="Catégorie de produit" message="Product category" language="en"/>
<meta-translation key="Produit" message="Product" language="en"/>
<meta-translation key="Produits" message="Products" language="en"/>
<meta-translation key="Catégorie principale" message="Main Category" language="en"/>
<meta-translation key="Ligne de commande produit" message="Product order line" language="en"/>
<meta-translation key="Commande produit" message="Product order" language="en"/>
<meta-translation key="Créer commande produit" message="Create product order" language="en"/>
<meta-translation key="Tableau de bord produit" message="Product dashboard" language="en"/>
<meta-translation key="Commandes produit par mois" message="Product orders per month" language="en"/>
<meta-translation key="Commandes produit par fournisseurs et catégorie" message="Product orders per supplier per category" language="en"/>
<meta-translation key="Réinitialiser" message="Reset" language="en"/>
<meta-translation key="Êtes-vous sûr de vouloir valider cette commande?" message="Are you sure wants to validate." language="en"/>
<meta-translation key="Commande validée" message="Order validated" language="en"/>
<meta-translation key="Êtes-vous sûr de vouloir annuler cette commande??" message="Are you sure wants to cancel ?" language="en"/>
<meta-translation key="Commande terminée" message="Order finished." language="en"/>
<meta-translation key="Cocher/Décocher 'A facturer'" message="Check/Uncheck 'to invoice'" language="en"/>
</meta-translations>

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<wkfs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wkf name="Commande produit" isJson="true" model="ProductOrder" statusField="status" displayTypeSelect="0" appBuilder="PRD">
<xml>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="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:x="http://axelor.com" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
<process id="Process_1" name="undefined" isExecutable="false" x:id="undefined">
<endEvent id="EndEvent_062urgf" name="Terminé">
<incoming>SequenceFlow_18u3b2a</incoming>
</endEvent>
<startEvent id="StartEvent_07npy19" name="Brouillon">
<incoming>SequenceFlow_1yn5orr</incoming>
<outgoing>SequenceFlow_0qljt6y</outgoing>
</startEvent>
<task id="Task_07my1i6" name="Confirmé">
<incoming>SequenceFlow_0qljt6y</incoming>
<outgoing>SequenceFlow_10bvr21</outgoing>
<outgoing>SequenceFlow_02m6a90</outgoing>
</task>
<sequenceFlow id="SequenceFlow_0qljt6y" name="Confirmer" sourceRef="StartEvent_07npy19" targetRef="Task_07my1i6" />
<task id="Task_0k79fbo" name="Validé">
<incoming>SequenceFlow_10bvr21</incoming>
<outgoing>SequenceFlow_18u3b2a</outgoing>
</task>
<sequenceFlow id="SequenceFlow_10bvr21" name="Valider" sourceRef="Task_07my1i6" targetRef="Task_0k79fbo" />
<task id="Task_069h0a2" name="Annulé">
<incoming>SequenceFlow_02m6a90</incoming>
<outgoing>SequenceFlow_1yn5orr</outgoing>
</task>
<sequenceFlow id="SequenceFlow_02m6a90" name="Annuler" sourceRef="Task_07my1i6" targetRef="Task_069h0a2" />
<sequenceFlow id="SequenceFlow_18u3b2a" name="Terminer" sourceRef="Task_0k79fbo" targetRef="EndEvent_062urgf" />
<sequenceFlow id="SequenceFlow_1yn5orr" name="Réinitialiser" sourceRef="Task_069h0a2" targetRef="StartEvent_07npy19" />
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="EndEvent_062urgf_di" bpmnElement="EndEvent_062urgf">
<dc:Bounds x="747" y="120" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="720" y="156" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="StartEvent_07npy19_di" bpmnElement="StartEvent_07npy19">
<dc:Bounds x="133" y="120" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="87" y="168" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_07my1i6_di" bpmnElement="Task_07my1i6">
<dc:Bounds x="291" y="98" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0qljt6y_di" bpmnElement="SequenceFlow_0qljt6y">
<di:waypoint xsi:type="dc:Point" x="169" y="138" />
<di:waypoint xsi:type="dc:Point" x="291" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="190" y="117" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_0k79fbo_di" bpmnElement="Task_0k79fbo">
<dc:Bounds x="492" y="98" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_10bvr21_di" bpmnElement="SequenceFlow_10bvr21">
<di:waypoint xsi:type="dc:Point" x="391" y="138" />
<di:waypoint xsi:type="dc:Point" x="492" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="392" y="105" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Task_069h0a2_di" bpmnElement="Task_069h0a2">
<dc:Bounds x="500" y="239" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_02m6a90_di" bpmnElement="SequenceFlow_02m6a90">
<di:waypoint xsi:type="dc:Point" x="341" y="178" />
<di:waypoint xsi:type="dc:Point" x="341" y="279" />
<di:waypoint xsi:type="dc:Point" x="500" y="279" />
<bpmndi:BPMNLabel>
<dc:Bounds x="373" y="253.5" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_18u3b2a_di" bpmnElement="SequenceFlow_18u3b2a">
<di:waypoint xsi:type="dc:Point" x="592" y="138" />
<di:waypoint xsi:type="dc:Point" x="747" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="625" y="112" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_1yn5orr_di" bpmnElement="SequenceFlow_1yn5orr">
<di:waypoint xsi:type="dc:Point" x="550" y="319" />
<di:waypoint xsi:type="dc:Point" x="550" y="356" />
<di:waypoint xsi:type="dc:Point" x="151" y="356" />
<di:waypoint xsi:type="dc:Point" x="151" y="156" />
<bpmndi:BPMNLabel>
<dc:Bounds x="266" y="330.5" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
]]>
</xml>
</wkf>
<wkfNode wkf="Commande produit" name="Brouillon" title="Brouillon" nodeType="0" sequence="1" xmlId="StartEvent_07npy19"/>
<wkfNode wkf="Commande produit" name="Confirmé" title="Confirmé" nodeType="1" sequence="2" xmlId="Task_07my1i6" />
<wkfNode wkf="Commande produit" name="Validé" title="Validé" nodeType="1" sequence="3" xmlId="Task_0k79fbo" />
<wkfNode wkf="Commande produit" name="Annulé" title="Annulé" nodeType="1" sequence="4" xmlId="Task_069h0a2"/>
<wkfNode wkf="Commande produit" name="Terminé" title="Terminé" nodeType="2" sequence="5" xmlId="EndEvent_062urgf"/>
<transition wkf="Commande produit" name="Confirmer" source="Brouillon" target="Confirmé" isButton="true" buttonTitle="Confirmer" xmlId="SequenceFlow_0qljt6y"/>
<transition wkf="Commande produit" name="Valider" source="Confirmé" target="Validé" isButton="true" buttonTitle="Valider" xmlId="SequenceFlow_10bvr21" alertTypeSelect="1" alertMsg="Êtes-vous sûr de vouloir valider cette commande?" successMsg="Commande validée" />
<transition wkf="Commande produit" name="Annuler" source="Confirmé" target="Annulé" isButton="true" buttonTitle="Annuler" xmlId="SequenceFlow_02m6a90" alertTypeSelect="1" alertMsg="Êtes-vous sûr de vouloir annuler cette commande??" />
<transition wkf="Commande produit" name="Terminer" source="Validé" target="Terminé" isButton="true" buttonTitle="Terminer" xmlId="SequenceFlow_18u3b2a" alertTypeSelect="2" alertMsg="Commande terminée" />
<transition wkf="Commande produit" name="Réinitialiser" source="Annulé" target="Brouillon" isButton="true" buttonTitle="Réinitialiser" xmlId="SequenceFlow_1yn5orr" />
<node wkf="Commande produit" name="Brouillon">
<incomings>
<incoming name="Réinitialiser" />
</incomings>
<outgoings>
<outgoing name="Confirmer" />
</outgoings>
</node>
<node wkf="Commande produit" name="Confirmé">
<incomings>
<incoming name="Confirmer" />
</incomings>
<outgoings>
<outgoing name="Valider" />
<outgoing name="Annuler" />
</outgoings>
</node>
<node wkf="Commande produit" name="Validé">
<incomings>
<incoming name="Valider" />
</incomings>
<outgoings>
<outgoing name="Terminer" />
</outgoings>
</node>
<node wkf="Commande produit" name="Annulé">
<incomings>
<incoming name="Annuler" />
</incomings>
<outgoings>
<outgoing name="Réinitialiser" />
</outgoings>
</node>
<node wkf="Commande produit" name="Terminé">
<incomings>
<incoming name="Terminer" />
</incomings>
</node>
<workflow name="Commande produit" />
</wkfs>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="ActionBuilder" cacheable="true">
<string name="name" title="Name" unique="true"/>
<integer name="typeSelect" title="Type" selection="studio.action.builder.type.select" />
<string name="model" title="Object" />
<string name="targetModel" title="Target object" />
<one-to-many name="lines" ref="ActionBuilderLine" title="Fields" mappedBy="actionBuilder"/>
<many-to-one name="assignValueTo" title="Assign value to" ref="com.axelor.meta.db.MetaField" />
<string name="firstGroupBy" title="First group by"/>
<string name="secondGroupBy" title="Second group by"/>
<string name="title" title="Title" />
<many-to-one name="emailTemplate" ref="com.axelor.apps.message.db.Template" title="Template" />
<one-to-many name="filters" ref="Filter" title="Filters"/>
<boolean name="transactional" title="Transactional" />
<integer name="scriptType" title="Script type" selection="studio.action.builder.script.type.select"/>
<string name="scriptText" title="Script" large="true"/>
<boolean name="openRecord" title="Open record" />
<string name="displayMsg" title="Display message" />
<integer name="emailSendOptionSelect" title="Send option" selection="studio.action.builder.email.send.option.select"/>
<!-- Action view fields -->
<one-to-many name="actionBuilderViews" title="Views" ref="ActionBuilderView" mappedBy="actionBuilder" orderBy="sequence"/>
<boolean name="isJson" title="Json" />
<string name="domainCondition" title="Domain" />
<one-to-many name="viewParams" title="View params" ref="ActionBuilderLine" orphanRemoval="true" />
<boolean name="menuAction" />
<many-to-one name="appBuilder" ref="AppBuilder" title="App builder" />
<many-to-one name="metaModule" ref="com.axelor.meta.db.MetaModule" />
<extra-code><![CDATA[
public static final int TYPE_SELECT_CREATE = 0;
public static final int TYPE_SELECT_UPDATE = 1;
public static final int TYPE_SELECT_SCRIPT = 2;
public static final int TYPE_SELECT_VIEW= 3;
public static final int TYPE_SELECT_EMAIL = 4;
public static final int TYPE_SELECT_REPORT = 5;
]]></extra-code>
</entity>
</domain-models>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="ActionBuilderLine" cacheable="true">
<many-to-one name="actionBuilder" ref="ActionBuilder" title="Action builder" />
<many-to-one name="metaJsonField" ref="com.axelor.meta.db.MetaJsonField" title="Target field" />
<many-to-one name="metaField" ref="com.axelor.meta.db.MetaField" title="Target field" />
<many-to-one name="valueJson" ref="com.axelor.meta.db.MetaJsonField" title="Source field" />
<many-to-one name="valueField" ref="com.axelor.meta.db.MetaField" title="Source field" />
<string name="value" title="Value expr"/>
<string name="conditionText" title="Condition" />
<string name="filter" title="Filter" />
<string name="validationTypeSelect" title="Validation type"/>
<string name="validationMsg" title="Message" />
<one-to-many name="subLines" ref="ActionBuilderLine" mappedBy="parent"/>
<many-to-one name="parent" ref="ActionBuilderLine" />
<string name="name" title="Target field" />
<boolean name="dummy" title="Dummy" />
</entity>
</domain-models>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="ActionBuilderView" cacheable="true">
<string name="viewType" title="Type" required="true" selection="view.type.selection"/>
<string name="viewName" title="Name" required="true"/>
<many-to-one name="actionBuilder" ref="ActionBuilder" />
<integer name="sequence" title="Sequence" />
<string name="viewConditionToCheck" title="If"/>
</entity>
</domain-models>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="base" package="com.axelor.apps.base.db"/>
<entity name="AppBpm" lang="java" cacheable="true" extends="App" />
</domain-models>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="AppBuilder" cacheable="true">
<string name="name" title="Name" required="true" translatable="true"/>
<string name="code" title="Code" required="true" unique="true" />
<string name="description" title="Description" large="true" translatable="true"/>
<many-to-many name="dependsOnSet" title="Depends on" ref="App"/>
<many-to-one name="image" ref="com.axelor.meta.db.MetaFile" title="Image"/>
<integer name="sequence" title="Sequence" />
<many-to-one name="generatedApp" ref="com.axelor.apps.base.db.App" />
</entity>
</domain-models>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="ChartBuilder" cacheable="true">
<string name="title" title="Title" required="true" />
<string name="name" title="Name" required="true" unique="true"/>
<string name="model" title="Model" />
<boolean name="isJson" title="Json" />
<one-to-many name="filterList" title="Filters" ref="com.axelor.studio.db.Filter" mappedBy="chartBuilder" />
<many-to-one name="aggregateOn" title="Aggregate On" ref="com.axelor.meta.db.MetaField"/>
<boolean name="isJsonAggregateOn" title="Json" />
<many-to-one name="aggregateOnJson" title="Aggregate On" ref="com.axelor.meta.db.MetaJsonField"/>
<string name="aggregateOnTarget" title="Target" />
<string name="aggregateOnTargetType" title="Aggregate On type" />
<string name="aggregateDateType" selection="studio.chart.builder.date.type" />
<many-to-one name="groupOn" title="Group By" ref="com.axelor.meta.db.MetaField" />
<boolean name="isJsonGroupOn" title="Json" />
<many-to-one name="groupOnJson" title="Group By" ref="com.axelor.meta.db.MetaJsonField" />
<string name="groupOnTarget" title="Target" />
<string name="groupOnTargetType" title="Group on type" />
<string name="groupDateType" selection="studio.chart.builder.date.type" />
<many-to-one name="displayField" title="Display" ref="com.axelor.meta.db.MetaField" />
<integer name="displayType" selection="studio.chart.builder.display.type" />
<boolean name="isJsonDisplayField" title="Json" />
<many-to-one name="displayFieldJson" title="Display" ref="com.axelor.meta.db.MetaJsonField" />
<string name="chartType" selection="studio.chart.builder.chart.type" default="bar"/>
<many-to-one name="metaViewGenerated" title="View generated" ref="com.axelor.meta.db.MetaView" />
<many-to-one name="appBuilder" ref="AppBuilder" title="App builder" />
</entity>
</domain-models>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="DashboardBuilder" cacheable="true">
<string name="title" title="Title" required="true" />
<string name="name" title="Name" required="true" unique="true"/>
<string name="model" title="Model" />
<one-to-many name="dashletBuilderList" ref="com.axelor.studio.db.DashletBuilder" mappedBy="dashboardBuilder" orderBy="sequence"/>
<many-to-one name="metaViewGenerated" title="View generated" ref="com.axelor.meta.db.MetaView" />
<one-to-many name="generatedActions" ref="com.axelor.meta.db.MetaAction" title="Generated Actions" orphanRemoval="true" />
<many-to-one name="appBuilder" ref="AppBuilder" title="App builder" />
</entity>
</domain-models>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="DashletBuilder" cacheable="true">
<![CDATA[
It represents a custom dashlet. It contains fields required to generate a Axelor Open Platform supported dashlet xml.
]]>
<string name="name" title="Name" required="true" />
<many-to-one name="metaView" ref="com.axelor.meta.db.MetaView" title="View" />
<many-to-one name="dashboardBuilder" ref="DashboardBuilder"/>
<many-to-one name="action" ref="com.axelor.meta.db.MetaAction" title="Action" />
<integer name="sequence" title="Sequence" />
<string name="viewType" title="Type" selection="view.type.selection" />
<integer name="colspan" title="Colspan" />
<integer name="paginationLimit" title="Pagination limit" />
<many-to-one name="appBuilder" ref="AppBuilder" title="App builder" />
<unique-constraint columns="name,dashboardBuilder"/>
</entity>
</domain-models>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="Filter" cacheable="true">
<![CDATA[
Filter represents a condition to evaluate. It stores condition components like operand, operator and value.
A sql or groovy condition will be created by using this.
]]>
<string name="moduleName" title="Module" />
<many-to-one name="chartBuilder" ref="com.axelor.studio.db.ChartBuilder" />
<many-to-one name="metaField" title="Field" ref="com.axelor.meta.db.MetaField"/>
<many-to-one name="metaJsonField" title="Json Field" ref="com.axelor.meta.db.MetaJsonField"/>
<many-to-one name="wkfTransition" ref="com.axelor.studio.db.WkfTransition" />
<many-to-one name="wkf" ref="com.axelor.studio.db.Wkf" />
<string name="operator" title="Operator" selection="studio.filter.operator" required="true" />
<many-to-one name="actionBuilder" ref="com.axelor.studio.db.ActionBuilder" />
<string name="targetField" title="Target field"/>
<string name="targetType" title="Target type"/>
<string name="value" title="Value" />
<string name="defaultValue" title="Default Value" />
<string name="targetTitle" title="Target title"/>
<boolean name="isParameter" title="Is parameter" />
<boolean name="isJson" title="Is json" />
<boolean name="isTargetJson" title="Target json" />
<integer name="logicOp" title="Logic operator" selection="studio.filter.logic.operator" default="0"/>
</entity>
</domain-models>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="MenuBuilder" cacheable="true">
<string name="name" title="Name" unique="true"/>
<string name="title" title="Title" required="true" />
<string name="icon" title="Icon" />
<string name="iconBackground" title="Background" />
<integer name="order" title="MenuBuilder.Order" column="order_seq" />
<string name="tag" title="Tag label"/>
<string name="tagGet" title="Tag method"/>
<boolean name="tagCount" title="Tag count"/>
<string name="tagStyle" selection="label.style.selection" title="Tag style"/>
<boolean name="top" column="top_menu" title="Top menu"/>
<boolean name="left" column="left_menu" default="true" title="Left menu"/>
<boolean name="mobile" column="mobile_menu" title="Mobile menu"/>
<boolean name="hidden" title="Hidden menu"/>
<string name="link" />
<many-to-many name="groups" ref="com.axelor.auth.db.Group"/>
<many-to-many name="roles" ref="com.axelor.auth.db.Role"/>
<string name="conditionToCheck" max="1024" title="If" help="Only use this menu-item if the given expression is true."/>
<string name="moduleToCheck" title="If-module" help="Only use this menu-item if the given module is installed."/>
<many-to-one name="metaMenu" title="MetaMenu" ref="com.axelor.meta.db.MetaMenu"/>
<many-to-one name="parentMenu" title="Parent" ref="com.axelor.meta.db.MetaMenu"/>
<many-to-one name="actionBuilder" ref="ActionBuilder" title="Action"/>
<boolean name="showAction" title="Object"/>
<many-to-one name="appBuilder" ref="AppBuilder" title="App builder" />
<many-to-one name="metaModule" ref="com.axelor.meta.db.MetaModule" />
<finder-method name="findByParentMenu" using="parentMenu" all="true"/>
</entity>
</domain-models>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="meta" package="com.axelor.meta.db" />
<entity name="MetaAction" cacheable="true">
<integer name="sequence" title="Sequence" />
</entity>
</domain-models>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="meta" package="com.axelor.meta.db" />
<entity name="MetaJsonField" table="META_JSON_FIELD">
<boolean name="isWkf" />
<many-to-one name="appBuilder" ref="com.axelor.studio.db.AppBuilder"
title="App builder" />
</entity>
</domain-models>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="meta" package="com.axelor.meta.db" />
<entity name="MetaJsonModel" table="META_JSON_MODEL">
<many-to-one name="appBuilder" ref="com.axelor.studio.db.AppBuilder" title="App builder" />
<boolean name="showProcessTracking" title="Show process tracking" />
</entity>
</domain-models>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="meta" package="com.axelor.meta.db" />
<entity name="MetaSelect" table="META_SELECT" cacheable="true">
<many-to-one name="appBuilder" ref="com.axelor.studio.db.AppBuilder" title="App builder"/>
<boolean name="isCustom" title="Custom"/>
</entity>
</domain-models>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="Wkf" cacheable="true">
<![CDATA[
This class is a root class used to store the workflow. A workflow is linked with a model and a form view of that model.
Wkf stores the bpmn xml of the worklfow diagram. The nodes and transitions of a wkf will be created by using the bpmn xml.
]]>
<string name="name" title="Name" required="true" />
<string name="model" title="Object" required="true" />
<string name="jsonField" title="Json Field"/>
<boolean name="isJson" title="Custom" default="true" />
<many-to-one name="statusField" ref="com.axelor.meta.db.MetaJsonField" title="Wkf field" required="true"/>
<one-to-many name="nodes" ref="WkfNode" mappedBy="wkf" orderBy="sequence"/>
<one-to-many name="transitions" ref="WkfTransition" mappedBy="wkf"/>
<one-to-many name="wkfTrackings" ref="WkfTracking" mappedBy="wkf"/>
<integer name="displayTypeSelect" title="Process display type" selection="studio.business.wkf.display.type.select"/>
<string name="bpmnXml" title="Bpmn xml" large="true" />
<many-to-one name="appBuilder" ref="AppBuilder" title="App builder" required="true" />
<string name="description" title="Description" large="true"/>
<one-to-many name="conditions" ref="Filter" title="Apply if" mappedBy="wkf"/>
<integer name="wkfSequence" title="Wkf sequence" />
<boolean name="isTrackFlow" title="Track flow"/>
</entity>
</domain-models>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="WkfNode" cacheable="true">
<![CDATA[
WkfNode represents a state of the workflow. A workflow must contain at least two states.
It is also used to generate a menu entry based on state.
]]>
<string name="name" title="Name" required="true"/>
<string name="title" title="Title" required="true" />
<string name="xmlId" title="xmlId" />
<many-to-one name="wkf" ref="Wkf" />
<many-to-one name="metaField" ref="com.axelor.meta.db.MetaField" title="Field for 'My menu'" />
<many-to-many name="incoming" ref="WkfTransition" title="Incoming" />
<many-to-many name="outgoing" ref="WkfTransition" title="Outgoing" />
<many-to-many name="roleSet" ref="com.axelor.auth.db.Role" title="ReadOnly for"/>
<integer name="sequence" title="Sequence" />
<integer name="nodeType" title="Node type" selection="studio.node.type.select" default="1" />
<many-to-many name="metaActionSet" ref="com.axelor.meta.db.MetaAction" title="Actions" orderBy="sequence"/>
<unique-constraint columns="wkf,sequence"/>
<extra-code>
<![CDATA[
public static final Integer START_NODE = 0;
public static final Integer TASK_NODE = 1;
public static final Integer END_NODE = 2;
]]>
</extra-code>
</entity>
</domain-models>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="WkfTracking" cacheable="true">
<![CDATA[
WkfTracking stores the information related to the workflow instance for an object.
The information like number of time some status changed, the user who changed the state, date and time when state is changed.
]]>
<many-to-one name="wkf" ref="Wkf" required="true"/>
<string name="recordModel" title="Record model" required="true"/>
<long name="recordId" required="true" title="Record Id"/>
<string name="recordName" title="Record name"/>
<one-to-many name="wkfTrackingLines" title="Tracking lines" ref="WkfTrackingLine" mappedBy="wkfTracking"/>
<one-to-many name="totalLines" title="Nb of passes per status" ref="WkfTrackingTotal" mappedBy="wkfTracking" />
<one-to-many name="totalTimeLines" title="Time spent (hours/days)" ref="WkfTrackingTime" mappedBy="wkfTracking" />
</entity>
</domain-models>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="WkfTrackingLine" cacheable="true">
<![CDATA[
This object stores the sub details of the {@link WkfTracking} class.
The details like status and time spent on particular status.
]]>
<many-to-one name="wkfTracking" ref="WkfTracking" required="true"/>
<string name="status" title="Status" required="true"/>
<decimal name="timeSpent" title="Time spent" />
</entity>
</domain-models>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="WkfTrackingTime" cacheable="true">
<![CDATA[
It stores the total time spent on particular status.
]]>
<many-to-one name="wkfTracking" ref="WkfTracking" required="true"/>
<string name="status" title="Status" required="true"/>
<decimal name="totalTimeHours" title="Status time(hours)"/>
<decimal name="totalTimeDays" title="Status time(days)" />
</entity>
</domain-models>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="WkfTrackingTotal" cacheable="true">
<![CDATA[
It stores the number times a particular status used by an object.
]]>
<many-to-one name="wkfTracking" ref="WkfTracking" required="true"/>
<string name="status" title="Status" required="true"/>
<integer name="totalCount" title="Nb of passes"/>
</entity>
</domain-models>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="studio" package="com.axelor.studio.db" />
<entity name="WkfTransition" cacheable="true">
<![CDATA[
WkfTransition stores the transition information for the nodes(state) of a workflow.
It contains source and destination nodes. The transition can be done on button click or on satisfaction of some conditions.
It is used to generate the buttons and actions required to call a transition.
]]>
<string name="name" title="Name" required="true" />
<string name="xmlId" title="xmlId" />
<boolean name="isButton" title="Button" />
<string name="buttonTitle" title="Button title" />
<integer name="colSpan" title="Colspan" default="3" min="1" max="12"/>
<many-to-many name="roleSet" ref="com.axelor.auth.db.Role" title="Roles" />
<one-to-many name="conditions" ref="Filter" title="Conditions" mappedBy="wkfTransition"/>
<many-to-one name="wkf" ref="Wkf" />
<many-to-one name="source" ref="WkfNode" title="From" />
<many-to-one name="target" ref="WkfNode" title="To" />
<integer name="alertTypeSelect" title="Alert or Blocking condition" selection="studio.condition.alert.type.select" />
<string name="alertMsg" title="Message on alert or blocking" />
<string name="successMsg" title="Message on success" />
</entity>
</domain-models>

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time",,,
"AND",,,
"Action",,,
"Action builder",,,
"Action builders",,,
"Actions",,,
"Activate the hand tool",,,
"Aggregate",,,
"Aggregate On",,,
"Aggregate On type",,,
"Aggregate date type",,,
"Alert",,,
"Alert or Blocking condition",,,
"App builder",,,
"App builders",,,
"App name",,,
"Append end node",,,
"Append intermediate node",,,
"Apply if",,,
"Area",,,
"Assign value to",,,
"BPM",,,
"Background",,,
"Bar",,,
"Base model",,,
"Blocking",,,
"Boolean",,,
"Bpmn xml",,,
"Button",,,
"Button title",,,
"Can Collapse",,,
"Chart builder",,,
"Chart builders",,,
"Chart type",,,
"ChartBuilder.Group",,,
"Choose App name",,,
"Code",,,
"Collapse if",,,
"Colspan",,,
"Condition",,,
"Conditions",,,
"Configuration",,,
"Connect using transition",,,
"Context",,,
"Create",,,
"Create end node",,,
"Create intermediate node",,,
"Create start node",,,
"Custom",,,
"Custom Field",,,
"Custom Model",,,
"Custom field",,,
"Custom fields",,,
"Custom model",,,
"Custom models",,,
"Dashboard",,,
"Dashboard builder",,,
"Dashboard builders",,,
"Dashlet builder",,,
"Dashlet builder list",,,
"Dashlet builders",,,
"Data file",,,
"Date",,,
"Datetime",,,
"Day",,,
"Decimal",,,
"Default Value",,,
"Depends on",,,
"Description",,,
"Display",,,
"Display message",,,
"Display type",,,
"Do you want to reset workflow ?",,,
"Domain",,,
"Donut",,,
"Dummy",,,
"Edit Node",,,
"Edit Transition",,,
"Edit before send",,,
"Email",,,
"End node",,,
"Existing menu",,,
"Export",,,
"Extra",,,
"Field",,,
"Field for 'My menu'",,,
"Field options",,,
"Fields",,,
"Filter",,,
"Filters",,,
"First group by",,,
"From",,,
"Funnel",,,
"Gauge",,,
"Generated Actions",,,
"Generated app",,,
"Groovy",,,
"Group By",,,
"Group date type",,,
"Group on type",,,
"Groups",,,
"Help",,,
"Hidden In Grid",,,
"Hidden menu",,,
"Horizontal bar",,,
"Icon",,,
"If",,,
"If-module",,,
"Image",,,
"Import",,,
"Import BPM",,,
"Import log",,,
"Incoming",,,
"Integer",,,
"Is Json Relational Field",,,
"Is json",,,
"Is parameter",,,
"Is wkf",,,
"Javascript",,,
"Json",,,
"Json Field",,,
"Json Many To Many",,,
"Json Many To One",,,
"Json One To Many",,,
"Left menu",,,
"Line",,,
"Link",,,
"Logic operator",,,
"Many To Many",,,
"Many To One",,,
"Max Size",,,
"Menu action",,,
"Menu builder",,,
"Menu builders",,,
"MenuBuilder.Order",,,
"Message",,,
"Message on alert or blocking",,,
"Message on success",,,
"Meta Model",,,
"Meta module",,,
"MetaMenu",,,
"Min Size",,,
"Mobile menu",,,
"Model",,,
"Module",,,
"Month",,,
"Name",,,
"Name Column",,,
"Name Field",,,
"Name must not contains space",,,
"Nav Select",,,
"Nb of passes",,,
"Nb of passes per status",,,
"Node",,,
"Node type",,,
"Nodes",,,
"None",,,
"OR",,,
"Object",,,
"On Change",,,
"On Click",,,
"On New",,,
"On Save",,,
"One To Many",,,
"Only use this menu-item if the given expression is true.",,,
"Only use this menu-item if the given module is installed.",,,
"Open record",,,
"Open workflow",,,
"Operator",,,
"Outgoing",,,
"Overview",,,
"Pagination limit",,,
"Panel",,,
"Parent",,,
"Percentage(%)",,,
"Permissions",,,
"Pie Chart",,,
"Please correct the workflow diagram.",,,
"Please input value bind with single quotation.",,,
"Please provide unique code. The code '%s' is already used",,,
"Process",,,
"Process display type",,,
"Process studio",,,
"Process tracking",,,
"Properties",,,
"Radar",,,
"ReadOnly for",,,
"Record Id",,,
"Record model",,,
"Record name",,,
"Regex",,,
"Report",,,
"Reporting",,,
"Required",,,
"Required If",,,
"Roles",,,
"Scatter",,,
"Script",,,
"Script type",,,
"Second group by",,,
"Select Option",,,
"Selection",,,
"Selections",,,
"Send directly",,,
"Send option",,,
"Separator",,,
"Sequence",,,
"Show If",,,
"Show Title",,,
"Show process tracking",,,
"Simple Select",,,
"Source field",,,
"Start node",,,
"Status",,,
"Status per day",,,
"Status per month",,,
"Status time(days)",,,
"Status time(hours)",,,
"String",,,
"Studio",,,
"Sub lines",,,
"Tag count",,,
"Tag label",,,
"Tag method",,,
"Tag style",,,
"Target",,,
"Target Json Model",,,
"Target field",,,
"Target json",,,
"Target object",,,
"Target title",,,
"Target type",,,
"Task node",,,
"Template",,,
"Text",,,
"Time",,,
"Time spent",,,
"Time spent (hours/days)",,,
"Time spent per status (hours)",,,
"Time spent per status per user (hours)",,,
"Title",,,
"To",,,
"Top menu",,,
"Total time per status",,,
"Track flow",,,
"Track workflow",,,
"Tracking line",,,
"Tracking lines",,,
"Transactional",,,
"Transition",,,
"Transitions",,,
"Type",,,
"UI options",,,
"Update",,,
"User",,,
"Validation type",,,
"Value",,,
"Value expr",,,
"View",,,
"View generated",,,
"View params",,,
"Views",,,
"Widget",,,
"Wkf",,,
"Wkf field",,,
"Wkf sequence",,,
"Wkf tracking",,,
"Wkf trackings",,,
"Wkf transition",,,
"Workflow dashboard",,,
"Workflow is not saved",,,
"Year",,,
"contains",,,
"doesn't contains",,,
"equal",,,
"greater or equal",,,
"greater than",,,
"in",,,
"include",,,
"is false",,,
"is not null",,,
"is null",,,
"is true",,,
"less or equal",,,
"less than",,,
"not equal",,,
"not in",,,
"not include",,,
"value:BPM",,,
"value:Product App",,,
"xmlId",,,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time
3 AND
4 Action
5 Action builder
6 Action builders
7 Actions
8 Activate the hand tool
9 Aggregate
10 Aggregate On
11 Aggregate On type
12 Aggregate date type
13 Alert
14 Alert or Blocking condition
15 App builder
16 App builders
17 App name
18 Append end node
19 Append intermediate node
20 Apply if
21 Area
22 Assign value to
23 BPM
24 Background
25 Bar
26 Base model
27 Blocking
28 Boolean
29 Bpmn xml
30 Button
31 Button title
32 Can Collapse
33 Chart builder
34 Chart builders
35 Chart type
36 ChartBuilder.Group
37 Choose App name
38 Code
39 Collapse if
40 Colspan
41 Condition
42 Conditions
43 Configuration
44 Connect using transition
45 Context
46 Create
47 Create end node
48 Create intermediate node
49 Create start node
50 Custom
51 Custom Field
52 Custom Model
53 Custom field
54 Custom fields
55 Custom model
56 Custom models
57 Dashboard
58 Dashboard builder
59 Dashboard builders
60 Dashlet builder
61 Dashlet builder list
62 Dashlet builders
63 Data file
64 Date
65 Datetime
66 Day
67 Decimal
68 Default Value
69 Depends on
70 Description
71 Display
72 Display message
73 Display type
74 Do you want to reset workflow ?
75 Domain
76 Donut
77 Dummy
78 Edit Node
79 Edit Transition
80 Edit before send
81 Email
82 End node
83 Existing menu
84 Export
85 Extra
86 Field
87 Field for 'My menu'
88 Field options
89 Fields
90 Filter
91 Filters
92 First group by
93 From
94 Funnel
95 Gauge
96 Generated Actions
97 Generated app
98 Groovy
99 Group By
100 Group date type
101 Group on type
102 Groups
103 Help
104 Hidden In Grid
105 Hidden menu
106 Horizontal bar
107 Icon
108 If
109 If-module
110 Image
111 Import
112 Import BPM
113 Import log
114 Incoming
115 Integer
116 Is Json Relational Field
117 Is json
118 Is parameter
119 Is wkf
120 Javascript
121 Json
122 Json Field
123 Json Many To Many
124 Json Many To One
125 Json One To Many
126 Left menu
127 Line
128 Link
129 Logic operator
130 Many To Many
131 Many To One
132 Max Size
133 Menu action
134 Menu builder
135 Menu builders
136 MenuBuilder.Order
137 Message
138 Message on alert or blocking
139 Message on success
140 Meta Model
141 Meta module
142 MetaMenu
143 Min Size
144 Mobile menu
145 Model
146 Module
147 Month
148 Name
149 Name Column
150 Name Field
151 Name must not contains space
152 Nav Select
153 Nb of passes
154 Nb of passes per status
155 Node
156 Node type
157 Nodes
158 None
159 OR
160 Object
161 On Change
162 On Click
163 On New
164 On Save
165 One To Many
166 Only use this menu-item if the given expression is true.
167 Only use this menu-item if the given module is installed.
168 Open record
169 Open workflow
170 Operator
171 Outgoing
172 Overview
173 Pagination limit
174 Panel
175 Parent
176 Percentage(%)
177 Permissions
178 Pie Chart
179 Please correct the workflow diagram.
180 Please input value bind with single quotation.
181 Please provide unique code. The code '%s' is already used
182 Process
183 Process display type
184 Process studio
185 Process tracking
186 Properties
187 Radar
188 ReadOnly for
189 Record Id
190 Record model
191 Record name
192 Regex
193 Report
194 Reporting
195 Required
196 Required If
197 Roles
198 Scatter
199 Script
200 Script type
201 Second group by
202 Select Option
203 Selection
204 Selections
205 Send directly
206 Send option
207 Separator
208 Sequence
209 Show If
210 Show Title
211 Show process tracking
212 Simple Select
213 Source field
214 Start node
215 Status
216 Status per day
217 Status per month
218 Status time(days)
219 Status time(hours)
220 String
221 Studio
222 Sub lines
223 Tag count
224 Tag label
225 Tag method
226 Tag style
227 Target
228 Target Json Model
229 Target field
230 Target json
231 Target object
232 Target title
233 Target type
234 Task node
235 Template
236 Text
237 Time
238 Time spent
239 Time spent (hours/days)
240 Time spent per status (hours)
241 Time spent per status per user (hours)
242 Title
243 To
244 Top menu
245 Total time per status
246 Track flow
247 Track workflow
248 Tracking line
249 Tracking lines
250 Transactional
251 Transition
252 Transitions
253 Type
254 UI options
255 Update
256 User
257 Validation type
258 Value
259 Value expr
260 View
261 View generated
262 View params
263 Views
264 Widget
265 Wkf
266 Wkf field
267 Wkf sequence
268 Wkf tracking
269 Wkf trackings
270 Wkf transition
271 Workflow dashboard
272 Workflow is not saved
273 Year
274 contains
275 doesn't contains
276 equal
277 greater or equal
278 greater than
279 in
280 include
281 is false
282 is not null
283 is null
284 is true
285 less or equal
286 less than
287 not equal
288 not in
289 not include
290 value:BPM
291 value:Product App
292 xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Tags:</b> $user: Aktueller Benutzer, $Datum: Heutiges Datum, $Zeit: Aktuelle Zeit",,
"AND","UND",,
"Action","Aktion",,
"Action builder","Action Builder",,
"Action builders","Aktionsbauer",,
"Actions","Aktionen",,
"Activate the hand tool","Aktivieren Sie das Handwerkzeug.",,
"Aggregate","Aggregat",,
"Aggregate On","Aggregat ein",,
"Aggregate On type","Aggregat Nach Typ",,
"Aggregate date type","Datumstyp aggregieren",,
"Alert","Warnung",,
"Alert or Blocking condition","Alarm- oder Sperrbedingung",,
"App builder","App Builder",,
"App builders",,,
"App name",,,
"Append end node","Endknoten anhängen",,
"Append intermediate node","Zwischenknoten anhängen",,
"Apply if",,,
"Area","Bereich",,
"Assign value to","Wert zuweisen an",,
"BPM","BPM",,
"Background","Hintergrund",,
"Bar","Bar",,
"Base model",,,
"Blocking","Blockierung",,
"Boolean","Boolesch",,
"Bpmn xml","Bpmn xml",,
"Button","Taste",,
"Button title","Titel der Schaltfläche",,
"Can Collapse",,,
"Chart builder","Diagrammgenerator",,
"Chart builders","Diagramm-Ersteller",,
"Chart type","Diagrammtyp",,
"ChartBuilder.Group","Gruppe",,
"Choose App name",,,
"Code","Code",,
"Collapse if",,,
"Colspan","Colspan",,
"Condition","Bedingung",,
"Conditions","Bedingungen",,
"Configuration",,,
"Connect using transition","Verbindung über Übergang",,
"Context","Kontext",,
"Create","Erstellen",,
"Create end node","Endknoten anlegen",,
"Create intermediate node","Zwischenknoten anlegen",,
"Create start node","Startknoten anlegen",,
"Custom","Benutzerdefiniert",,
"Custom Field","Benutzerdefiniertes Feld",,
"Custom Model","Benutzerdefiniertes Modell",,
"Custom field","Benutzerdefiniertes Feld",,
"Custom fields","Benutzerdefinierte Felder",,
"Custom model","Benutzerdefiniertes Modell",,
"Custom models","Kundenspezifische Modelle",,
"Dashboard","Dashboard",,
"Dashboard builder","Dashboard-Builder",,
"Dashboard builders","Dashboard-Bauer",,
"Dashlet builder","Dashlet Erbauer",,
"Dashlet builder list","Liste der Dashlet-Builder",,
"Dashlet builders","Dashlet Erbauer",,
"Data file","Datendatei",,
"Date","Datum",,
"Datetime","Datum/Uhrzeit",,
"Day","Tag",,
"Decimal","Dezimal",,
"Default Value","Standardwert",,
"Depends on","Abhängig von",,
"Description","Beschreibung",,
"Display","Display",,
"Display message","Display-Meldung",,
"Display type","Anzeigeart",,
"Do you want to reset workflow ?",,,
"Domain","Domain",,
"Donut","Donut",,
"Dummy","Dummy",,
"Edit Node","Knoten bearbeiten",,
"Edit Transition","Übergang bearbeiten",,
"Edit before send","Bearbeiten vor dem Senden",,
"Email","E-Mail",,
"End node","Endknoten",,
"Existing menu","Vorhandenes Menü",,
"Export","Exportieren",,
"Extra","Extra",,
"Field","Feld",,
"Field for 'My menu'","Feld für'Mein Menü'.",,
"Field options",,,
"Fields","Felder",,
"Filter","Filter",,
"Filters","Filter",,
"First group by","Erste Gruppe nach",,
"From","Von",,
"Funnel","Trichter",,
"Gauge","Manometer",,
"Generated Actions","Generierte Aktionen",,
"Generated app","Generierte App",,
"Groovy","Groovy",,
"Group By","Gruppieren nach",,
"Group date type","Gruppendatumstyp",,
"Group on type","Gruppe nach Typ",,
"Groups","Gruppen",,
"Help","Hilfe",,
"Hidden In Grid","Im Raster versteckt",,
"Hidden menu","Verstecktes Menü",,
"Horizontal bar","Horizontale Stange",,
"Icon","Icon",,
"If","Wenn",,
"If-module","Wenn-Modul",,
"Image","Bild",,
"Import","Importieren",,
"Import BPM","BPM importieren",,
"Import log","Importprotokoll",,
"Incoming","Ankommend",,
"Integer","Ganzzahl",,
"Is Json Relational Field",,,
"Is json","Ist json",,
"Is parameter","Ist Parameter",,
"Is wkf","Ist wkf",,
"Javascript","Javascript",,
"Json","Json",,
"Json Field","Json Feld",,
"Json Many To Many","Json Viele Zu Viele Zu Viele",,
"Json Many To One","Json viele zu eins",,
"Json One To Many","Json Einer zu viele",,
"Left menu","Linkes Menü",,
"Line","Linie",,
"Link","Link",,
"Logic operator","Verknüpfungsoperator",,
"Many To Many","Viele Zu Viele Zu Viele",,
"Many To One","Viele zu einem",,
"Max Size","Maximale Größe",,
"Menu action","Menü-Aktion",,
"Menu builder","Menü-Builder",,
"Menu builders","Menü-Erstellung",,
"MenuBuilder.Order","Ordnung",,
"Message","Nachricht",,
"Message on alert or blocking","Nachricht bei Alarm oder Sperrung",,
"Message on success","Meldung über den Erfolg",,
"Meta Model","Metamodell",,
"Meta module","Metamodul",,
"MetaMenu","MetaMenü",,
"Min Size","Min. Größe",,
"Mobile menu","Mobiles Menü",,
"Model","Modell",,
"Module","Modul",,
"Month","Monat",,
"Name","Name",,
"Name Column",,,
"Name Field","Namensfeld",,
"Name must not contains space","Der Name darf kein Leerzeichen enthalten.",,
"Nav Select","Nav-Auswahl",,
"Nb of passes","Anzahl der Durchgänge",,
"Nb of passes per status","Anzahl der Durchläufe pro Status",,
"Node","Knoten",,
"Node type",,,
"Nodes","Knoten",,
"None",,,
"OR","ODER",,
"Object","Objekt",,
"On Change","Bei Änderung",,
"On Click","Auf Klick",,
"On New","Bei Neu",,
"On Save","Beim Speichern",,
"One To Many","Einer zu vielen",,
"Only use this menu-item if the given expression is true.","Verwenden Sie diesen Menüpunkt nur, wenn der angegebene Ausdruck wahr ist.",,
"Only use this menu-item if the given module is installed.","Verwenden Sie diesen Menüpunkt nur, wenn das angegebene Modul installiert ist.",,
"Open record","Datensatz öffnen",,
"Open workflow","Offener Workflow",,
"Operator","Bediener",,
"Outgoing","Ausgehend",,
"Overview","Übersicht",,
"Pagination limit","Seitenumbruchgrenze",,
"Panel","Panel",,
"Parent","Elternteil",,
"Percentage(%)","Prozentsatz(%)",,
"Permissions","Berechtigungen",,
"Pie Chart","Kreisdiagramm",,
"Please correct the workflow diagram.","Bitte korrigieren Sie das Arbeitsablaufdiagramm.",,
"Please input value bind with single quotation.","Bitte geben Sie den Wert binden mit einem einfachen Angebot ein.",,
"Please provide unique code. The code '%s' is already used","Bitte geben Sie einen eindeutigen Code an. Der Code'%s' ist bereits verwendet.",,
"Process",,,
"Process display type","Prozessanzeigetyp",,
"Process studio","Prozessstudio",,
"Process tracking","Prozessverfolgung",,
"Properties","Eigenschaften",,
"Radar","Radar",,
"ReadOnly for",,,
"Record Id","Aufzeichnungs-ID",,
"Record model","Aktenmodell",,
"Record name","Datensatzname",,
"Regex","Regex",,
"Report","Bericht",,
"Reporting",,,
"Required","Erforderlich",,
"Required If","Erforderlich bei",,
"Roles","Rollen",,
"Scatter","Streuung",,
"Script","Skript",,
"Script type","Skript-Typ",,
"Second group by","Zweite Gruppe nach",,
"Select Option","Option auswählen",,
"Selection","Auswahl",,
"Selections",,,
"Send directly","Direkt versenden",,
"Send option","Sendeoption",,
"Separator","Separator",,
"Sequence","Sequenz",,
"Show If","Anzeigen ob",,
"Show Title",,,
"Show process tracking","Prozessverfolgung anzeigen",,
"Simple Select","Einfache Auswahl",,
"Source field","Quellfeld",,
"Start node","Startknoten",,
"Status","Status",,
"Status per day","Status pro Tag",,
"Status per month","Status pro Monat",,
"Status time(days)","Statuszeit (Tage)",,
"Status time(hours)","Statuszeit (Stunden)",,
"String","Zeichenkette",,
"Studio",,,
"Sub lines","Unterzeilen",,
"Tag count","Tag-Anzahl",,
"Tag label","Tag-Etikett",,
"Tag method","Tag-Verfahren",,
"Tag style","Tag-Stil",,
"Target","Ziel",,
"Target Json Model","Ziel Json Modell",,
"Target field","Zielfeld",,
"Target json","Ziel json",,
"Target object","Zielobjekt",,
"Target title",,,
"Target type","Zielart",,
"Task node",,,
"Template","Vorlage",,
"Text","Text",,
"Time","Zeit",,
"Time spent","Zeitaufwand",,
"Time spent (hours/days)","Verweildauer (Stunden/Tage)",,
"Time spent per status (hours)","Verweildauer pro Status (Stunden)",,
"Time spent per status per user (hours)","Zeitaufwand pro Status pro Benutzer (Stunden)",,
"Title","Titel",,
"To","An",,
"Top menu","Top-Menü",,
"Total time per status","Gesamtzeit pro Status",,
"Track flow","Schienenfluss",,
"Track workflow","Verfolgung des Arbeitsablaufs",,
"Tracking line","Tracking-Linie",,
"Tracking lines","Tracking-Linien",,
"Transactional","Transaktionale",,
"Transition","Übergang",,
"Transitions","Übergänge",,
"Type","Typ",,
"UI options",,,
"Update","Update",,
"User","Benutzer",,
"Validation type","Validierungsart",,
"Value","Wert",,
"Value expr","Wert Ausdruck",,
"View","Ansicht",,
"View generated","Ansicht generiert",,
"View params","Parameter anzeigen",,
"Views","Ansichten",,
"Widget","Widget",,
"Wkf","Wkf",,
"Wkf field","Wkf-Feld",,
"Wkf sequence",,,
"Wkf tracking","Wkf-Tracking",,
"Wkf trackings","Wkf-Tracking",,
"Wkf transition","Wkf-Übergang",,
"Workflow dashboard","Workflow-Dashboard",,
"Workflow is not saved","Workflow wird nicht gespeichert",,
"Year","Jahr",,
"contains","enthält",,
"doesn't contains","enthält nicht",,
"equal","gleich",,
"greater or equal","größer oder gleich",,
"greater than","größer als",,
"in","in",,
"include","einbeziehen",,
"is false","ist falsch",,
"is not null","ist nicht Null",,
"is null","ist Null",,
"is true","ist wahr",,
"less or equal","kleiner oder gleich",,
"less than","weniger als",,
"not equal","nicht gleich",,
"not in","nicht in",,
"not include","nicht enthalten",,
"value:BPM","Wert:BPM",,
"value:Product App","Wert:Produkt-App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Tags:</b> $user: Aktueller Benutzer, $Datum: Heutiges Datum, $Zeit: Aktuelle Zeit
3 AND UND
4 Action Aktion
5 Action builder Action Builder
6 Action builders Aktionsbauer
7 Actions Aktionen
8 Activate the hand tool Aktivieren Sie das Handwerkzeug.
9 Aggregate Aggregat
10 Aggregate On Aggregat ein
11 Aggregate On type Aggregat Nach Typ
12 Aggregate date type Datumstyp aggregieren
13 Alert Warnung
14 Alert or Blocking condition Alarm- oder Sperrbedingung
15 App builder App Builder
16 App builders
17 App name
18 Append end node Endknoten anhängen
19 Append intermediate node Zwischenknoten anhängen
20 Apply if
21 Area Bereich
22 Assign value to Wert zuweisen an
23 BPM BPM
24 Background Hintergrund
25 Bar Bar
26 Base model
27 Blocking Blockierung
28 Boolean Boolesch
29 Bpmn xml Bpmn xml
30 Button Taste
31 Button title Titel der Schaltfläche
32 Can Collapse
33 Chart builder Diagrammgenerator
34 Chart builders Diagramm-Ersteller
35 Chart type Diagrammtyp
36 ChartBuilder.Group Gruppe
37 Choose App name
38 Code Code
39 Collapse if
40 Colspan Colspan
41 Condition Bedingung
42 Conditions Bedingungen
43 Configuration
44 Connect using transition Verbindung über Übergang
45 Context Kontext
46 Create Erstellen
47 Create end node Endknoten anlegen
48 Create intermediate node Zwischenknoten anlegen
49 Create start node Startknoten anlegen
50 Custom Benutzerdefiniert
51 Custom Field Benutzerdefiniertes Feld
52 Custom Model Benutzerdefiniertes Modell
53 Custom field Benutzerdefiniertes Feld
54 Custom fields Benutzerdefinierte Felder
55 Custom model Benutzerdefiniertes Modell
56 Custom models Kundenspezifische Modelle
57 Dashboard Dashboard
58 Dashboard builder Dashboard-Builder
59 Dashboard builders Dashboard-Bauer
60 Dashlet builder Dashlet Erbauer
61 Dashlet builder list Liste der Dashlet-Builder
62 Dashlet builders Dashlet Erbauer
63 Data file Datendatei
64 Date Datum
65 Datetime Datum/Uhrzeit
66 Day Tag
67 Decimal Dezimal
68 Default Value Standardwert
69 Depends on Abhängig von
70 Description Beschreibung
71 Display Display
72 Display message Display-Meldung
73 Display type Anzeigeart
74 Do you want to reset workflow ?
75 Domain Domain
76 Donut Donut
77 Dummy Dummy
78 Edit Node Knoten bearbeiten
79 Edit Transition Übergang bearbeiten
80 Edit before send Bearbeiten vor dem Senden
81 Email E-Mail
82 End node Endknoten
83 Existing menu Vorhandenes Menü
84 Export Exportieren
85 Extra Extra
86 Field Feld
87 Field for 'My menu' Feld für'Mein Menü'.
88 Field options
89 Fields Felder
90 Filter Filter
91 Filters Filter
92 First group by Erste Gruppe nach
93 From Von
94 Funnel Trichter
95 Gauge Manometer
96 Generated Actions Generierte Aktionen
97 Generated app Generierte App
98 Groovy Groovy
99 Group By Gruppieren nach
100 Group date type Gruppendatumstyp
101 Group on type Gruppe nach Typ
102 Groups Gruppen
103 Help Hilfe
104 Hidden In Grid Im Raster versteckt
105 Hidden menu Verstecktes Menü
106 Horizontal bar Horizontale Stange
107 Icon Icon
108 If Wenn
109 If-module Wenn-Modul
110 Image Bild
111 Import Importieren
112 Import BPM BPM importieren
113 Import log Importprotokoll
114 Incoming Ankommend
115 Integer Ganzzahl
116 Is Json Relational Field
117 Is json Ist json
118 Is parameter Ist Parameter
119 Is wkf Ist wkf
120 Javascript Javascript
121 Json Json
122 Json Field Json Feld
123 Json Many To Many Json Viele Zu Viele Zu Viele
124 Json Many To One Json viele zu eins
125 Json One To Many Json Einer zu viele
126 Left menu Linkes Menü
127 Line Linie
128 Link Link
129 Logic operator Verknüpfungsoperator
130 Many To Many Viele Zu Viele Zu Viele
131 Many To One Viele zu einem
132 Max Size Maximale Größe
133 Menu action Menü-Aktion
134 Menu builder Menü-Builder
135 Menu builders Menü-Erstellung
136 MenuBuilder.Order Ordnung
137 Message Nachricht
138 Message on alert or blocking Nachricht bei Alarm oder Sperrung
139 Message on success Meldung über den Erfolg
140 Meta Model Metamodell
141 Meta module Metamodul
142 MetaMenu MetaMenü
143 Min Size Min. Größe
144 Mobile menu Mobiles Menü
145 Model Modell
146 Module Modul
147 Month Monat
148 Name Name
149 Name Column
150 Name Field Namensfeld
151 Name must not contains space Der Name darf kein Leerzeichen enthalten.
152 Nav Select Nav-Auswahl
153 Nb of passes Anzahl der Durchgänge
154 Nb of passes per status Anzahl der Durchläufe pro Status
155 Node Knoten
156 Node type
157 Nodes Knoten
158 None
159 OR ODER
160 Object Objekt
161 On Change Bei Änderung
162 On Click Auf Klick
163 On New Bei Neu
164 On Save Beim Speichern
165 One To Many Einer zu vielen
166 Only use this menu-item if the given expression is true. Verwenden Sie diesen Menüpunkt nur, wenn der angegebene Ausdruck wahr ist.
167 Only use this menu-item if the given module is installed. Verwenden Sie diesen Menüpunkt nur, wenn das angegebene Modul installiert ist.
168 Open record Datensatz öffnen
169 Open workflow Offener Workflow
170 Operator Bediener
171 Outgoing Ausgehend
172 Overview Übersicht
173 Pagination limit Seitenumbruchgrenze
174 Panel Panel
175 Parent Elternteil
176 Percentage(%) Prozentsatz(%)
177 Permissions Berechtigungen
178 Pie Chart Kreisdiagramm
179 Please correct the workflow diagram. Bitte korrigieren Sie das Arbeitsablaufdiagramm.
180 Please input value bind with single quotation. Bitte geben Sie den Wert binden mit einem einfachen Angebot ein.
181 Please provide unique code. The code '%s' is already used Bitte geben Sie einen eindeutigen Code an. Der Code'%s' ist bereits verwendet.
182 Process
183 Process display type Prozessanzeigetyp
184 Process studio Prozessstudio
185 Process tracking Prozessverfolgung
186 Properties Eigenschaften
187 Radar Radar
188 ReadOnly for
189 Record Id Aufzeichnungs-ID
190 Record model Aktenmodell
191 Record name Datensatzname
192 Regex Regex
193 Report Bericht
194 Reporting
195 Required Erforderlich
196 Required If Erforderlich bei
197 Roles Rollen
198 Scatter Streuung
199 Script Skript
200 Script type Skript-Typ
201 Second group by Zweite Gruppe nach
202 Select Option Option auswählen
203 Selection Auswahl
204 Selections
205 Send directly Direkt versenden
206 Send option Sendeoption
207 Separator Separator
208 Sequence Sequenz
209 Show If Anzeigen ob
210 Show Title
211 Show process tracking Prozessverfolgung anzeigen
212 Simple Select Einfache Auswahl
213 Source field Quellfeld
214 Start node Startknoten
215 Status Status
216 Status per day Status pro Tag
217 Status per month Status pro Monat
218 Status time(days) Statuszeit (Tage)
219 Status time(hours) Statuszeit (Stunden)
220 String Zeichenkette
221 Studio
222 Sub lines Unterzeilen
223 Tag count Tag-Anzahl
224 Tag label Tag-Etikett
225 Tag method Tag-Verfahren
226 Tag style Tag-Stil
227 Target Ziel
228 Target Json Model Ziel Json Modell
229 Target field Zielfeld
230 Target json Ziel json
231 Target object Zielobjekt
232 Target title
233 Target type Zielart
234 Task node
235 Template Vorlage
236 Text Text
237 Time Zeit
238 Time spent Zeitaufwand
239 Time spent (hours/days) Verweildauer (Stunden/Tage)
240 Time spent per status (hours) Verweildauer pro Status (Stunden)
241 Time spent per status per user (hours) Zeitaufwand pro Status pro Benutzer (Stunden)
242 Title Titel
243 To An
244 Top menu Top-Menü
245 Total time per status Gesamtzeit pro Status
246 Track flow Schienenfluss
247 Track workflow Verfolgung des Arbeitsablaufs
248 Tracking line Tracking-Linie
249 Tracking lines Tracking-Linien
250 Transactional Transaktionale
251 Transition Übergang
252 Transitions Übergänge
253 Type Typ
254 UI options
255 Update Update
256 User Benutzer
257 Validation type Validierungsart
258 Value Wert
259 Value expr Wert Ausdruck
260 View Ansicht
261 View generated Ansicht generiert
262 View params Parameter anzeigen
263 Views Ansichten
264 Widget Widget
265 Wkf Wkf
266 Wkf field Wkf-Feld
267 Wkf sequence
268 Wkf tracking Wkf-Tracking
269 Wkf trackings Wkf-Tracking
270 Wkf transition Wkf-Übergang
271 Workflow dashboard Workflow-Dashboard
272 Workflow is not saved Workflow wird nicht gespeichert
273 Year Jahr
274 contains enthält
275 doesn't contains enthält nicht
276 equal gleich
277 greater or equal größer oder gleich
278 greater than größer als
279 in in
280 include einbeziehen
281 is false ist falsch
282 is not null ist nicht Null
283 is null ist Null
284 is true ist wahr
285 less or equal kleiner oder gleich
286 less than weniger als
287 not equal nicht gleich
288 not in nicht in
289 not include nicht enthalten
290 value:BPM Wert:BPM
291 value:Product App Wert:Produkt-App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time",,,
"AND",,,
"Action",,,
"Action builder",,,
"Action builders",,,
"Actions",,,
"Activate the hand tool",,,
"Aggregate",,,
"Aggregate On",,,
"Aggregate On type",,,
"Aggregate date type",,,
"Alert",,,
"Alert or Blocking condition",,,
"App builder",,,
"App builders",,,
"App name","Application",,
"Append end node",,,
"Append intermediate node",,,
"Apply if",,,
"Area",,,
"Assign value to",,,
"BPM",,,
"Background",,,
"Bar",,,
"Base model",,,
"Blocking",,,
"Boolean",,,
"Bpmn xml",,,
"Button",,,
"Button title",,,
"Can Collapse",,,
"Chart builder",,,
"Chart builders",,,
"Chart type",,,
"ChartBuilder.Group","Group",,
"Choose App name",,,
"Code",,,
"Collapse if",,,
"Colspan",,,
"Condition",,,
"Conditions",,,
"Configuration",,,
"Connect using transition",,,
"Context",,,
"Create",,,
"Create end node",,,
"Create intermediate node",,,
"Create start node",,,
"Custom",,,
"Custom Field",,,
"Custom Model",,,
"Custom field",,,
"Custom fields",,,
"Custom model",,,
"Custom models",,,
"Dashboard",,,
"Dashboard builder",,,
"Dashboard builders",,,
"Dashlet builder",,,
"Dashlet builder list",,,
"Dashlet builders",,,
"Data file",,,
"Date",,,
"Datetime",,,
"Day",,,
"Decimal",,,
"Default Value",,,
"Depends on",,,
"Description",,,
"Display",,,
"Display message",,,
"Display type",,,
"Do you want to reset workflow ?",,,
"Domain",,,
"Donut",,,
"Dummy",,,
"Edit Node",,,
"Edit Transition",,,
"Edit before send",,,
"Email",,,
"End node",,,
"Existing menu",,,
"Export",,,
"Extra",,,
"Field",,,
"Field for 'My menu'",,,
"Field options",,,
"Fields",,,
"Filter",,,
"Filters",,,
"First group by",,,
"From",,,
"Funnel",,,
"Gauge",,,
"Generated Actions",,,
"Generated app",,,
"Groovy",,,
"Group By",,,
"Group date type",,,
"Group on type",,,
"Groups",,,
"Help",,,
"Hidden In Grid",,,
"Hidden menu",,,
"Horizontal bar",,,
"Icon",,,
"If",,,
"If-module",,,
"Image",,,
"Import",,,
"Import BPM",,,
"Import log",,,
"Incoming",,,
"Integer",,,
"Is Json Relational Field",,,
"Is json",,,
"Is parameter",,,
"Is wkf",,,
"Javascript",,,
"Json",,,
"Json Field",,,
"Json Many To Many",,,
"Json Many To One",,,
"Json One To Many",,,
"Left menu",,,
"Line",,,
"Link",,,
"Logic operator",,,
"Many To Many",,,
"Many To One",,,
"Max Size",,,
"Menu action",,,
"Menu builder",,,
"Menu builders",,,
"MenuBuilder.Order","Order",,
"Message",,,
"Message on alert or blocking",,,
"Message on success",,,
"Meta Model",,,
"Meta module",,,
"MetaMenu",,,
"Min Size",,,
"Mobile menu",,,
"Model",,,
"Module",,,
"Month",,,
"Name",,,
"Name Column",,,
"Name Field",,,
"Name must not contains space",,,
"Nav Select",,,
"Nb of passes",,,
"Nb of passes per status",,,
"Node",,,
"Node type",,,
"Nodes",,,
"None",,,
"OR",,,
"Object",,,
"On Change",,,
"On Click",,,
"On New",,,
"On Save",,,
"One To Many",,,
"Only use this menu-item if the given expression is true.",,,
"Only use this menu-item if the given module is installed.",,,
"Open record",,,
"Open workflow",,,
"Operator",,,
"Outgoing",,,
"Overview",,,
"Pagination limit",,,
"Panel",,,
"Parent",,,
"Percentage(%)",,,
"Permissions",,,
"Pie Chart",,,
"Please correct the workflow diagram.",,,
"Please input value bind with single quotation.",,,
"Please provide unique code. The code '%s' is already used",,,
"Process",,,
"Process display type",,,
"Process studio",,,
"Process tracking",,,
"Properties",,,
"Radar",,,
"ReadOnly for",,,
"Record Id",,,
"Record model",,,
"Record name",,,
"Regex",,,
"Report",,,
"Reporting",,,
"Required",,,
"Required If",,,
"Roles",,,
"Scatter",,,
"Script",,,
"Script type",,,
"Second group by",,,
"Select Option",,,
"Selection",,,
"Selections",,,
"Send directly",,,
"Send option",,,
"Separator",,,
"Sequence",,,
"Show If",,,
"Show Title",,,
"Show process tracking",,,
"Simple Select",,,
"Source field",,,
"Start node",,,
"Status",,,
"Status per day",,,
"Status per month",,,
"Status time(days)",,,
"Status time(hours)",,,
"String",,,
"Studio",,,
"Sub lines",,,
"Tag count",,,
"Tag label",,,
"Tag method",,,
"Tag style",,,
"Target",,,
"Target Json Model",,,
"Target field",,,
"Target json",,,
"Target object",,,
"Target title",,,
"Target type",,,
"Task node",,,
"Template",,,
"Text",,,
"Time",,,
"Time spent",,,
"Time spent (hours/days)",,,
"Time spent per status (hours)",,,
"Time spent per status per user (hours)",,,
"Title",,,
"To",,,
"Top menu",,,
"Total time per status",,,
"Track flow",,,
"Track workflow",,,
"Tracking line",,,
"Tracking lines",,,
"Transactional",,,
"Transition",,,
"Transitions",,,
"Type",,,
"UI options",,,
"Update",,,
"User",,,
"Validation type",,,
"Value",,,
"Value expr",,,
"View",,,
"View generated",,,
"View params",,,
"Views",,,
"Widget",,,
"Wkf",,,
"Wkf field",,,
"Wkf sequence",,,
"Wkf tracking",,,
"Wkf trackings",,,
"Wkf transition",,,
"Workflow dashboard",,,
"Workflow is not saved",,,
"Year",,,
"contains",,,
"doesn't contains",,,
"equal",,,
"greater or equal",,,
"greater than",,,
"in",,,
"include",,,
"is false",,,
"is not null",,,
"is null",,,
"is true",,,
"less or equal",,,
"less than",,,
"not equal",,,
"not in",,,
"not include",,,
"value:BPM",,,
"value:Product App",,,
"xmlId",,,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time
3 AND
4 Action
5 Action builder
6 Action builders
7 Actions
8 Activate the hand tool
9 Aggregate
10 Aggregate On
11 Aggregate On type
12 Aggregate date type
13 Alert
14 Alert or Blocking condition
15 App builder
16 App builders
17 App name Application
18 Append end node
19 Append intermediate node
20 Apply if
21 Area
22 Assign value to
23 BPM
24 Background
25 Bar
26 Base model
27 Blocking
28 Boolean
29 Bpmn xml
30 Button
31 Button title
32 Can Collapse
33 Chart builder
34 Chart builders
35 Chart type
36 ChartBuilder.Group Group
37 Choose App name
38 Code
39 Collapse if
40 Colspan
41 Condition
42 Conditions
43 Configuration
44 Connect using transition
45 Context
46 Create
47 Create end node
48 Create intermediate node
49 Create start node
50 Custom
51 Custom Field
52 Custom Model
53 Custom field
54 Custom fields
55 Custom model
56 Custom models
57 Dashboard
58 Dashboard builder
59 Dashboard builders
60 Dashlet builder
61 Dashlet builder list
62 Dashlet builders
63 Data file
64 Date
65 Datetime
66 Day
67 Decimal
68 Default Value
69 Depends on
70 Description
71 Display
72 Display message
73 Display type
74 Do you want to reset workflow ?
75 Domain
76 Donut
77 Dummy
78 Edit Node
79 Edit Transition
80 Edit before send
81 Email
82 End node
83 Existing menu
84 Export
85 Extra
86 Field
87 Field for 'My menu'
88 Field options
89 Fields
90 Filter
91 Filters
92 First group by
93 From
94 Funnel
95 Gauge
96 Generated Actions
97 Generated app
98 Groovy
99 Group By
100 Group date type
101 Group on type
102 Groups
103 Help
104 Hidden In Grid
105 Hidden menu
106 Horizontal bar
107 Icon
108 If
109 If-module
110 Image
111 Import
112 Import BPM
113 Import log
114 Incoming
115 Integer
116 Is Json Relational Field
117 Is json
118 Is parameter
119 Is wkf
120 Javascript
121 Json
122 Json Field
123 Json Many To Many
124 Json Many To One
125 Json One To Many
126 Left menu
127 Line
128 Link
129 Logic operator
130 Many To Many
131 Many To One
132 Max Size
133 Menu action
134 Menu builder
135 Menu builders
136 MenuBuilder.Order Order
137 Message
138 Message on alert or blocking
139 Message on success
140 Meta Model
141 Meta module
142 MetaMenu
143 Min Size
144 Mobile menu
145 Model
146 Module
147 Month
148 Name
149 Name Column
150 Name Field
151 Name must not contains space
152 Nav Select
153 Nb of passes
154 Nb of passes per status
155 Node
156 Node type
157 Nodes
158 None
159 OR
160 Object
161 On Change
162 On Click
163 On New
164 On Save
165 One To Many
166 Only use this menu-item if the given expression is true.
167 Only use this menu-item if the given module is installed.
168 Open record
169 Open workflow
170 Operator
171 Outgoing
172 Overview
173 Pagination limit
174 Panel
175 Parent
176 Percentage(%)
177 Permissions
178 Pie Chart
179 Please correct the workflow diagram.
180 Please input value bind with single quotation.
181 Please provide unique code. The code '%s' is already used
182 Process
183 Process display type
184 Process studio
185 Process tracking
186 Properties
187 Radar
188 ReadOnly for
189 Record Id
190 Record model
191 Record name
192 Regex
193 Report
194 Reporting
195 Required
196 Required If
197 Roles
198 Scatter
199 Script
200 Script type
201 Second group by
202 Select Option
203 Selection
204 Selections
205 Send directly
206 Send option
207 Separator
208 Sequence
209 Show If
210 Show Title
211 Show process tracking
212 Simple Select
213 Source field
214 Start node
215 Status
216 Status per day
217 Status per month
218 Status time(days)
219 Status time(hours)
220 String
221 Studio
222 Sub lines
223 Tag count
224 Tag label
225 Tag method
226 Tag style
227 Target
228 Target Json Model
229 Target field
230 Target json
231 Target object
232 Target title
233 Target type
234 Task node
235 Template
236 Text
237 Time
238 Time spent
239 Time spent (hours/days)
240 Time spent per status (hours)
241 Time spent per status per user (hours)
242 Title
243 To
244 Top menu
245 Total time per status
246 Track flow
247 Track workflow
248 Tracking line
249 Tracking lines
250 Transactional
251 Transition
252 Transitions
253 Type
254 UI options
255 Update
256 User
257 Validation type
258 Value
259 Value expr
260 View
261 View generated
262 View params
263 Views
264 Widget
265 Wkf
266 Wkf field
267 Wkf sequence
268 Wkf tracking
269 Wkf trackings
270 Wkf transition
271 Workflow dashboard
272 Workflow is not saved
273 Year
274 contains
275 doesn't contains
276 equal
277 greater or equal
278 greater than
279 in
280 include
281 is false
282 is not null
283 is null
284 is true
285 less or equal
286 less than
287 not equal
288 not in
289 not include
290 value:BPM
291 value:Product App
292 xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Etiquetas:</b> $usuario: Usuario actual, $date: Fecha de hoy, $time: Hora actual",,
"AND","Y",,
"Action","Acción",,
"Action builder","Constructor de acciones",,
"Action builders","Constructores de acciones",,
"Actions","Acciones",,
"Activate the hand tool","Activar la herramienta manual",,
"Aggregate","Agregado",,
"Aggregate On","Agregado en",,
"Aggregate On type","Tipo Aggregate On",,
"Aggregate date type","Agregar clase de fecha",,
"Alert","Alerta",,
"Alert or Blocking condition","Alerta o condición de bloqueo",,
"App builder","Constructor de aplicaciones",,
"App builders",,,
"App name",,,
"Append end node","Añadir nodo final",,
"Append intermediate node","Añadir nodo intermedio",,
"Apply if",,,
"Area","Área",,
"Assign value to","Asignar valor a",,
"BPM","BPM",,
"Background","Antecedentes",,
"Bar","Bar",,
"Base model",,,
"Blocking","Bloqueo",,
"Boolean","booleano",,
"Bpmn xml","Bpmn xml",,
"Button","Botón",,
"Button title","Título del botón",,
"Can Collapse",,,
"Chart builder","Constructor de gráficos",,
"Chart builders","Constructores de cartas",,
"Chart type","Tipo de gráfico",,
"ChartBuilder.Group","Grupo",,
"Choose App name",,,
"Code","Código",,
"Collapse if",,,
"Colspan","Colspan",,
"Condition","Condición",,
"Conditions","Condiciones",,
"Configuration",,,
"Connect using transition","Conectar usando la transición",,
"Context","Contexto",,
"Create","Crear",,
"Create end node","Crear nodo final",,
"Create intermediate node","Crear nodo intermedio",,
"Create start node","Crear nodo de inicio",,
"Custom","A medida",,
"Custom Field","Campo personalizado",,
"Custom Model","Modelo personalizado",,
"Custom field","Campo personalizado",,
"Custom fields","Campos personalizados",,
"Custom model","Modelo personalizado",,
"Custom models","Modelos personalizados",,
"Dashboard","Tablero de mandos",,
"Dashboard builder","Constructor de cuadros de mando",,
"Dashboard builders","Constructores de cuadros de mando",,
"Dashlet builder","Constructor de dashlets",,
"Dashlet builder list","Lista de constructores de dashlets",,
"Dashlet builders","Constructores de dashlets",,
"Data file","Archivo de datos",,
"Date","Fecha",,
"Datetime","Fecha y hora",,
"Day","Día",,
"Decimal","Decimal",,
"Default Value","Valor de propuesta",,
"Depends on","Depende de",,
"Description","Descripción",,
"Display","Pantalla",,
"Display message","Mostrar mensaje",,
"Display type","Tipo de pantalla",,
"Do you want to reset workflow ?",,,
"Domain","Dominio",,
"Donut","Donut",,
"Dummy","Maniquí",,
"Edit Node","Tratar nodo",,
"Edit Transition","Editar transición",,
"Edit before send","Modificar antes de enviar",,
"Email","Correo electrónico",,
"End node","Nodo final",,
"Existing menu","Menú existente",,
"Export","Exportación",,
"Extra","Extra",,
"Field","Campo",,
"Field for 'My menu'","Campo para `Mi menú'.",,
"Field options",,,
"Fields","Campos",,
"Filter","Filtro",,
"Filters","Filtros",,
"First group by","Primer grupo por",,
"From","Desde",,
"Funnel","Embudo",,
"Gauge","Calibrador",,
"Generated Actions","Acciones generadas",,
"Generated app","Generado app",,
"Groovy","Groovy",,
"Group By","Agrupar por",,
"Group date type","Clase de fecha de grupo",,
"Group on type","Grupo sobre el tipo",,
"Groups","Grupos",,
"Help","Ayuda",,
"Hidden In Grid","Oculto en la cuadrícula",,
"Hidden menu","Menú oculto",,
"Horizontal bar","Barra horizontal",,
"Icon","Icono",,
"If","Si",,
"If-module","Módulo If",,
"Image","Imagen",,
"Import","Importar",,
"Import BPM","Importación BPM",,
"Import log","Log de importación",,
"Incoming","Entrante",,
"Integer","Entero",,
"Is Json Relational Field",,,
"Is json","Es json",,
"Is parameter","Es parámetro",,
"Is wkf","Es wkf",,
"Javascript","Javascript",,
"Json","Json",,
"Json Field","Campo Json",,
"Json Many To Many","Json Many To Many",,
"Json Many To One","Json Muchos a Uno",,
"Json One To Many","Json One to Many",,
"Left menu","Menú de la izquierda",,
"Line","Línea",,
"Link","Enlace",,
"Logic operator","Operador lógico",,
"Many To Many","Muchos a muchos",,
"Many To One","Muchos a uno",,
"Max Size","Tamaño Máximo",,
"Menu action","Acción del menú",,
"Menu builder","Constructor de menús",,
"Menu builders","Constructores de menús",,
"MenuBuilder.Order","Orden",,
"Message","Mensaje",,
"Message on alert or blocking","Mensaje de alerta o bloqueo",,
"Message on success","Mensaje sobre el éxito",,
"Meta Model","Meta Modelo",,
"Meta module","Meta módulo",,
"MetaMenu","MetaMenú",,
"Min Size","Tamaño mínimo",,
"Mobile menu","Menú Móvil",,
"Model","Modelo",,
"Module","Módulo",,
"Month","Mes",,
"Name","Nombre",,
"Name Column",,,
"Name Field","Nombre Campo",,
"Name must not contains space","El nombre no debe contener espacio",,
"Nav Select","Selección de Navegación",,
"Nb of passes","Número de pases",,
"Nb of passes per status","Número de pases por estado",,
"Node","Nodo",,
"Node type","Type de nœud",,
"Nodes","Nodos",,
"None",,,
"OR","O",,
"Object","Objeto",,
"On Change","Sobre el cambio",,
"On Click","En Click",,
"On New","En Nuevo",,
"On Save","En Guardar",,
"One To Many","Uno a muchos",,
"Only use this menu-item if the given expression is true.","Utilice este elemento de menú sólo si la expresión dada es verdadera.",,
"Only use this menu-item if the given module is installed.","Utilice este elemento de menú sólo si el módulo está instalado.",,
"Open record","Registro abierto",,
"Open workflow","Flujo de trabajo abierto",,
"Operator","Operador",,
"Outgoing","Saliente",,
"Overview","Panorama general",,
"Pagination limit","Límite de paginación",,
"Panel","Panel",,
"Parent","Padre",,
"Percentage(%)","Porcentaje (%)",,
"Permissions","Permisos",,
"Pie Chart","Gráfico de tarta",,
"Please correct the workflow diagram.","Por favor, corrija el diagrama de flujo de trabajo.",,
"Please input value bind with single quotation.","Por favor, introduzca el valor de encuadernar con una sola cita.",,
"Please provide unique code. The code '%s' is already used","Por favor, proporcione un código único. El código '%s' ya se utiliza",,
"Process",,,
"Process display type","Tipo de visualización del proceso",,
"Process studio","Estudio de procesos",,
"Process tracking","Seguimiento del proceso",,
"Properties","Propiedades",,
"Radar","Radar",,
"ReadOnly for","Lecture seule pour",,
"Record Id","Id. de registro",,
"Record model","Modelo de registro",,
"Record name","Nombre del registro",,
"Regex","Regex",,
"Report","Informe",,
"Reporting",,,
"Required","Requerido",,
"Required If","Requerido Si",,
"Roles","Roles",,
"Scatter","Esparcir",,
"Script","Guión",,
"Script type","Tipo de guión",,
"Second group by","Segundo grupo por",,
"Select Option","Seleccione la opción",,
"Selection","Selección",,
"Selections",,,
"Send directly","Enviar directamente",,
"Send option","Opción de envío",,
"Separator","Separador",,
"Sequence","Secuencia",,
"Show If","Mostrar Si",,
"Show Title",,,
"Show process tracking","Mostrar seguimiento de procesos",,
"Simple Select","Selección simple",,
"Source field","Campo fuente",,
"Start node","Nodo de inicio",,
"Status","Estado",,
"Status per day","Estado por día",,
"Status per month","Estado por mes",,
"Status time(days)","Tiempo de status (días)",,
"Status time(hours)","Tiempo de estado (horas)",,
"String","Cadena",,
"Studio",,,
"Sub lines","Líneas secundarias",,
"Tag count","Conteo de etiquetas",,
"Tag label","Etiqueta",,
"Tag method","Método de la etiqueta",,
"Tag style","Estilo de etiqueta",,
"Target","Objetivo",,
"Target Json Model","Modelo Json objetivo",,
"Target field","Campo de destino",,
"Target json","Objetivo json",,
"Target object","Objeto de destino",,
"Target title",,,
"Target type","Clase de destino",,
"Task node","Noeud intermédiaire",,
"Template","Plantilla",,
"Text","Texto",,
"Time","Tiempo",,
"Time spent","Tiempo de permanencia",,
"Time spent (hours/days)","Tiempo empleado (horas/días)",,
"Time spent per status (hours)","Tiempo empleado por estado (horas)",,
"Time spent per status per user (hours)","Tiempo empleado por estado por usuario (horas)",,
"Title","Título",,
"To","Para",,
"Top menu","Menú principal",,
"Total time per status","Tiempo total por status",,
"Track flow","Flujo de la pista",,
"Track workflow","Seguimiento del flujo de trabajo",,
"Tracking line","Línea de seguimiento",,
"Tracking lines","Líneas de seguimiento",,
"Transactional","Transaccional",,
"Transition","Transición",,
"Transitions","Transiciones",,
"Type","Tipo",,
"UI options",,,
"Update","Actualización",,
"User","Usuario",,
"Validation type","Tipo de validación",,
"Value","Valor",,
"Value expr","Valor Expr",,
"View","Ver",,
"View generated","Vista generada",,
"View params","Ver parámetros",,
"Views","Vistas",,
"Widget","Widget",,
"Wkf","Wkf",,
"Wkf field","Campo Wkf",,
"Wkf sequence",,,
"Wkf tracking","Seguimiento de Wkf",,
"Wkf trackings","Seguimiento de Wkf",,
"Wkf transition","Transición Wkf",,
"Workflow dashboard","Panel de control del flujo de trabajo",,
"Workflow is not saved","No se graba el workflow",,
"Year","Año",,
"contains","contiene",,
"doesn't contains","no contiene",,
"equal","idénticas",,
"greater or equal","mayor o igual",,
"greater than","mayor que",,
"in","en",,
"include","contener",,
"is false","es falso",,
"is not null","no es nula",,
"is null","es nulo",,
"is true","es cierto",,
"less or equal","menor o igual",,
"less than","menos de",,
"not equal","no es igual",,
"not in","no en",,
"not include","no incluye",,
"value:BPM","valor:BPM",,
"value:Product App","valor:Producto App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Etiquetas:</b> $usuario: Usuario actual, $date: Fecha de hoy, $time: Hora actual
3 AND Y
4 Action Acción
5 Action builder Constructor de acciones
6 Action builders Constructores de acciones
7 Actions Acciones
8 Activate the hand tool Activar la herramienta manual
9 Aggregate Agregado
10 Aggregate On Agregado en
11 Aggregate On type Tipo Aggregate On
12 Aggregate date type Agregar clase de fecha
13 Alert Alerta
14 Alert or Blocking condition Alerta o condición de bloqueo
15 App builder Constructor de aplicaciones
16 App builders
17 App name
18 Append end node Añadir nodo final
19 Append intermediate node Añadir nodo intermedio
20 Apply if
21 Area Área
22 Assign value to Asignar valor a
23 BPM BPM
24 Background Antecedentes
25 Bar Bar
26 Base model
27 Blocking Bloqueo
28 Boolean booleano
29 Bpmn xml Bpmn xml
30 Button Botón
31 Button title Título del botón
32 Can Collapse
33 Chart builder Constructor de gráficos
34 Chart builders Constructores de cartas
35 Chart type Tipo de gráfico
36 ChartBuilder.Group Grupo
37 Choose App name
38 Code Código
39 Collapse if
40 Colspan Colspan
41 Condition Condición
42 Conditions Condiciones
43 Configuration
44 Connect using transition Conectar usando la transición
45 Context Contexto
46 Create Crear
47 Create end node Crear nodo final
48 Create intermediate node Crear nodo intermedio
49 Create start node Crear nodo de inicio
50 Custom A medida
51 Custom Field Campo personalizado
52 Custom Model Modelo personalizado
53 Custom field Campo personalizado
54 Custom fields Campos personalizados
55 Custom model Modelo personalizado
56 Custom models Modelos personalizados
57 Dashboard Tablero de mandos
58 Dashboard builder Constructor de cuadros de mando
59 Dashboard builders Constructores de cuadros de mando
60 Dashlet builder Constructor de dashlets
61 Dashlet builder list Lista de constructores de dashlets
62 Dashlet builders Constructores de dashlets
63 Data file Archivo de datos
64 Date Fecha
65 Datetime Fecha y hora
66 Day Día
67 Decimal Decimal
68 Default Value Valor de propuesta
69 Depends on Depende de
70 Description Descripción
71 Display Pantalla
72 Display message Mostrar mensaje
73 Display type Tipo de pantalla
74 Do you want to reset workflow ?
75 Domain Dominio
76 Donut Donut
77 Dummy Maniquí
78 Edit Node Tratar nodo
79 Edit Transition Editar transición
80 Edit before send Modificar antes de enviar
81 Email Correo electrónico
82 End node Nodo final
83 Existing menu Menú existente
84 Export Exportación
85 Extra Extra
86 Field Campo
87 Field for 'My menu' Campo para `Mi menú'.
88 Field options
89 Fields Campos
90 Filter Filtro
91 Filters Filtros
92 First group by Primer grupo por
93 From Desde
94 Funnel Embudo
95 Gauge Calibrador
96 Generated Actions Acciones generadas
97 Generated app Generado app
98 Groovy Groovy
99 Group By Agrupar por
100 Group date type Clase de fecha de grupo
101 Group on type Grupo sobre el tipo
102 Groups Grupos
103 Help Ayuda
104 Hidden In Grid Oculto en la cuadrícula
105 Hidden menu Menú oculto
106 Horizontal bar Barra horizontal
107 Icon Icono
108 If Si
109 If-module Módulo If
110 Image Imagen
111 Import Importar
112 Import BPM Importación BPM
113 Import log Log de importación
114 Incoming Entrante
115 Integer Entero
116 Is Json Relational Field
117 Is json Es json
118 Is parameter Es parámetro
119 Is wkf Es wkf
120 Javascript Javascript
121 Json Json
122 Json Field Campo Json
123 Json Many To Many Json Many To Many
124 Json Many To One Json Muchos a Uno
125 Json One To Many Json One to Many
126 Left menu Menú de la izquierda
127 Line Línea
128 Link Enlace
129 Logic operator Operador lógico
130 Many To Many Muchos a muchos
131 Many To One Muchos a uno
132 Max Size Tamaño Máximo
133 Menu action Acción del menú
134 Menu builder Constructor de menús
135 Menu builders Constructores de menús
136 MenuBuilder.Order Orden
137 Message Mensaje
138 Message on alert or blocking Mensaje de alerta o bloqueo
139 Message on success Mensaje sobre el éxito
140 Meta Model Meta Modelo
141 Meta module Meta módulo
142 MetaMenu MetaMenú
143 Min Size Tamaño mínimo
144 Mobile menu Menú Móvil
145 Model Modelo
146 Module Módulo
147 Month Mes
148 Name Nombre
149 Name Column
150 Name Field Nombre Campo
151 Name must not contains space El nombre no debe contener espacio
152 Nav Select Selección de Navegación
153 Nb of passes Número de pases
154 Nb of passes per status Número de pases por estado
155 Node Nodo
156 Node type Type de nœud
157 Nodes Nodos
158 None
159 OR O
160 Object Objeto
161 On Change Sobre el cambio
162 On Click En Click
163 On New En Nuevo
164 On Save En Guardar
165 One To Many Uno a muchos
166 Only use this menu-item if the given expression is true. Utilice este elemento de menú sólo si la expresión dada es verdadera.
167 Only use this menu-item if the given module is installed. Utilice este elemento de menú sólo si el módulo está instalado.
168 Open record Registro abierto
169 Open workflow Flujo de trabajo abierto
170 Operator Operador
171 Outgoing Saliente
172 Overview Panorama general
173 Pagination limit Límite de paginación
174 Panel Panel
175 Parent Padre
176 Percentage(%) Porcentaje (%)
177 Permissions Permisos
178 Pie Chart Gráfico de tarta
179 Please correct the workflow diagram. Por favor, corrija el diagrama de flujo de trabajo.
180 Please input value bind with single quotation. Por favor, introduzca el valor de encuadernar con una sola cita.
181 Please provide unique code. The code '%s' is already used Por favor, proporcione un código único. El código '%s' ya se utiliza
182 Process
183 Process display type Tipo de visualización del proceso
184 Process studio Estudio de procesos
185 Process tracking Seguimiento del proceso
186 Properties Propiedades
187 Radar Radar
188 ReadOnly for Lecture seule pour
189 Record Id Id. de registro
190 Record model Modelo de registro
191 Record name Nombre del registro
192 Regex Regex
193 Report Informe
194 Reporting
195 Required Requerido
196 Required If Requerido Si
197 Roles Roles
198 Scatter Esparcir
199 Script Guión
200 Script type Tipo de guión
201 Second group by Segundo grupo por
202 Select Option Seleccione la opción
203 Selection Selección
204 Selections
205 Send directly Enviar directamente
206 Send option Opción de envío
207 Separator Separador
208 Sequence Secuencia
209 Show If Mostrar Si
210 Show Title
211 Show process tracking Mostrar seguimiento de procesos
212 Simple Select Selección simple
213 Source field Campo fuente
214 Start node Nodo de inicio
215 Status Estado
216 Status per day Estado por día
217 Status per month Estado por mes
218 Status time(days) Tiempo de status (días)
219 Status time(hours) Tiempo de estado (horas)
220 String Cadena
221 Studio
222 Sub lines Líneas secundarias
223 Tag count Conteo de etiquetas
224 Tag label Etiqueta
225 Tag method Método de la etiqueta
226 Tag style Estilo de etiqueta
227 Target Objetivo
228 Target Json Model Modelo Json objetivo
229 Target field Campo de destino
230 Target json Objetivo json
231 Target object Objeto de destino
232 Target title
233 Target type Clase de destino
234 Task node Noeud intermédiaire
235 Template Plantilla
236 Text Texto
237 Time Tiempo
238 Time spent Tiempo de permanencia
239 Time spent (hours/days) Tiempo empleado (horas/días)
240 Time spent per status (hours) Tiempo empleado por estado (horas)
241 Time spent per status per user (hours) Tiempo empleado por estado por usuario (horas)
242 Title Título
243 To Para
244 Top menu Menú principal
245 Total time per status Tiempo total por status
246 Track flow Flujo de la pista
247 Track workflow Seguimiento del flujo de trabajo
248 Tracking line Línea de seguimiento
249 Tracking lines Líneas de seguimiento
250 Transactional Transaccional
251 Transition Transición
252 Transitions Transiciones
253 Type Tipo
254 UI options
255 Update Actualización
256 User Usuario
257 Validation type Tipo de validación
258 Value Valor
259 Value expr Valor Expr
260 View Ver
261 View generated Vista generada
262 View params Ver parámetros
263 Views Vistas
264 Widget Widget
265 Wkf Wkf
266 Wkf field Campo Wkf
267 Wkf sequence
268 Wkf tracking Seguimiento de Wkf
269 Wkf trackings Seguimiento de Wkf
270 Wkf transition Transición Wkf
271 Workflow dashboard Panel de control del flujo de trabajo
272 Workflow is not saved No se graba el workflow
273 Year Año
274 contains contiene
275 doesn't contains no contiene
276 equal idénticas
277 greater or equal mayor o igual
278 greater than mayor que
279 in en
280 include contener
281 is false es falso
282 is not null no es nula
283 is null es nulo
284 is true es cierto
285 less or equal menor o igual
286 less than menos de
287 not equal no es igual
288 not in no en
289 not include no incluye
290 value:BPM valor:BPM
291 value:Product App valor:Producto App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Libellé:</b> $user: Utilisateur actuel, $date: Date d'aujourd'hui, $time: Heure actuelle",,
"AND","ET",,
"Action","Action",,
"Action builder","Constructeur d'action",,
"Action builders","Constructeurs d'action",,
"Actions","Actions",,
"Activate the hand tool","Activer l'outil manuel",,
"Aggregate","Agréger",,
"Aggregate On","Agréger sur",,
"Aggregate On type","Agréger sur un type",,
"Aggregate date type","Type de date agrégée",,
"Alert","Alerte",,
"Alert or Blocking condition","Condition d'alerte ou de blocage",,
"App builder","Constructeur d'app",,
"App builders","Constructeurs d'apps",,
"App name","Application",,
"Append end node","Ajouter un nœud terminal",,
"Append intermediate node","Ajouter un nœud intermédiaire",,
"Apply if",,,
"Area","Zone",,
"Assign value to","Affecter valeur à",,
"BPM","BPM",,
"Background","Background",,
"Bar","Bar",,
"Base model","Modèle de base",,
"Blocking","Blocage",,
"Boolean","Booléen",,
"Bpmn xml","Bpmn xml",,
"Button","Bouton",,
"Button title","Titre du bouton",,
"Can Collapse","Repliable",,
"Chart builder","Constructeur de graphique",,
"Chart builders","Constructeurs de graphiques",,
"Chart type","Type de graphique",,
"ChartBuilder.Group","Regrouper",,
"Choose App name","Choisir application",,
"Code",,,
"Collapse if","Replier si",,
"Colspan","Colspan",,
"Condition","Condition",,
"Conditions","Conditions",,
"Configuration",,,
"Connect using transition","Connecter en utilisant la transition",,
"Context","Contexte",,
"Create","Créer",,
"Create end node","Créer un nœud terminal",,
"Create intermediate node","Créer un nœud intermédiaire",,
"Create start node","Créer un nœud de départ",,
"Custom","Personnaliser",,
"Custom Field","Champ personnalisé",,
"Custom Model","Modèle personnalisé",,
"Custom field","Champ personnalisé",,
"Custom fields","Champs personnalisés",,
"Custom model","Modèle personnalisé",,
"Custom models","Modèles personnalisés",,
"Dashboard",,,
"Dashboard builder","Constructeur de tableaux de bord",,
"Dashboard builders","Constructeurs de tableaux de bord",,
"Dashlet builder","Constructeur de dashlet",,
"Dashlet builder list","Liste des constructeurs de dashlet",,
"Dashlet builders","Constructeurs de dashlet",,
"Data file","Fichier de données",,
"Date","Date",,
"Datetime","Date et heure",,
"Day","Jour",,
"Decimal","Décimal",,
"Default Value","Valeur par défaut",,
"Depends on","Dépend de",,
"Description",,,
"Display","Affichage",,
"Display message","Message affiché",,
"Display type","Type d'affichage",,
"Do you want to reset workflow ?","Voulez-vous réinitialiser le workflow ?",,
"Domain","Domaine",,
"Donut","Donut",,
"Dummy","Factice",,
"Edit Node","Modifier un nœud",,
"Edit Transition","Modifier une transition",,
"Edit before send","Editer avant denvoyer",,
"Email",,,
"End node","Nœud terminal",,
"Existing menu","Menu existant",,
"Export","Exporter",,
"Extra","Extra",,
"Field","Champ",,
"Field for 'My menu'","Champ pour 'Mon menu'",,
"Field options","Options du champ",,
"Fields","Champs",,
"Filter","Filtre",,
"Filters","Filtres",,
"First group by","Premier groupe par",,
"From","De",,
"Funnel","Entonnoir",,
"Gauge","Jauge",,
"Generated Actions","Actions générées",,
"Generated app","App générée",,
"Groovy","Groovy",,
"Group By","Regrouper par",,
"Group date type","Type de date de groupe",,
"Group on type","Regrouper sur type",,
"Groups","Groupes",,
"Help","Aide",,
"Hidden In Grid","Caché dans la grille",,
"Hidden menu","Menu caché",,
"Horizontal bar","Barre horizontale",,
"Icon","Icône",,
"If","Si",,
"If-module","Si-module",,
"Image",,,
"Import","Import",,
"Import BPM",,,
"Import log",,,
"Incoming","Entrant",,
"Integer","Nombre entier",,
"Is Json Relational Field","Champ relationnel JSON",,
"Is json","Est JSON",,
"Is parameter","Est paramètre",,
"Is wkf","Est wkf",,
"Javascript","Javascript",,
"Json",,,
"Json Field","Champ Json",,
"Json Many To Many","Json N à N",,
"Json Many To One","Json N à 1",,
"Json One To Many","Json 1 à N",,
"Left menu","Menu de gauche",,
"Line","Ligne",,
"Link","Lien",,
"Logic operator","Opérateur logique",,
"Many To Many","N à N",,
"Many To One","N à 1",,
"Max Size","Taille max",,
"Menu action","Constructeur de menu",,
"Menu builder","Constructeur de menu",,
"Menu builders","Constructeurs de menus",,
"MenuBuilder.Order","Ordre",,
"Message","Message",,
"Message on alert or blocking","Message sur les alertes ou blocages",,
"Message on success","Message de succès",,
"Meta Model","Modèle Meta",,
"Meta module",,,
"MetaMenu",,,
"Min Size","Taille min",,
"Mobile menu","Menu mobile",,
"Model","Modèle",,
"Module","Module",,
"Month","Mois",,
"Name","Nom",,
"Name Column","Colonne nominative",,
"Name Field","Champ nom",,
"Name must not contains space","Le nom ne doit pas contenir d'espace",,
"Nav Select","Nav Select",,
"Nb of passes","Nb de passages",,
"Nb of passes per status","Nb de passages par statut",,
"Node","Nœud",,
"Node type","Type de nœud",,
"Nodes","Nœuds",,
"None",,,
"OR","OU",,
"Object","Objet",,
"On Change","Au changement",,
"On Click","Au clic",,
"On New","À la création",,
"On Save","À la sauvegarde",,
"One To Many","1 à N",,
"Only use this menu-item if the given expression is true.","N'utilisez cet élément de menu que si l'expression donnée est vraie.",,
"Only use this menu-item if the given module is installed.","N'utilisez cet élément de menu que si le module concerné est installé.",,
"Open record","Ouvrir enregistrement",,
"Open workflow","Ouvrir le processus",,
"Operator","Opérateur",,
"Outgoing","Sortant",,
"Overview","Vue d'ensemble",,
"Pagination limit","Limite de pagination",,
"Panel","Panel",,
"Parent","Parent",,
"Percentage(%)","Pourcentage(%)",,
"Permissions","Permissions",,
"Pie Chart","Diagramme circulaire",,
"Please correct the workflow diagram.","Veuillez corriger le diagramme de workflow.",,
"Please input value bind with single quotation.","Veuillez entrer les valeurs liées avec une seule guillemet",,
"Please provide unique code. The code '%s' is already used","Veuillez indiquer un code unique. Le code '%s' est déjà utilisé",,
"Process",,,
"Process display type","Type d'affichage du processus",,
"Process studio","Studio Processus",,
"Process tracking","Suivi processus",,
"Properties","Propriétés",,
"Radar","Radar",,
"ReadOnly for","Lecture seule pour",,
"Record Id","Identifiant",,
"Record model","Objet",,
"Record name","Nom de l'objet",,
"Regex","Regex",,
"Report","Rapport",,
"Reporting",,,
"Required","Requis",,
"Required If","Requis si",,
"Roles","Rôles",,
"Scatter","Disperser",,
"Script","Script",,
"Script type","Type de script",,
"Second group by","Deuxième groupe par",,
"Select Option","Sélectionner option",,
"Selection","Sélection",,
"Selections","Sélections",,
"Send directly","Envoyer directement",,
"Send option","Option denvoi",,
"Separator","Séparateur",,
"Sequence","Séquence",,
"Show If","Montrer si",,
"Show Title","Montrer le titre",,
"Show process tracking","Afficher le suivi du processus",,
"Simple Select","Sélection simple",,
"Source field","Champ source",,
"Start node","Nœud de départ",,
"Status","Statut",,
"Status per day","Statut par jour",,
"Status per month","Statut par mois",,
"Status time(days)","Temps du status (en heures)",,
"Status time(hours)","Temps du status (en jours)",,
"String","Chaîne de caractères",,
"Studio",,,
"Sub lines","Sous-lignes",,
"Tag count","Compteur",,
"Tag label","Libellé du tag",,
"Tag method","Méthode de calcul",,
"Tag style","Style de tag",,
"Target","Cible",,
"Target Json Model","Modèle de cible JSON",,
"Target field","Champ cible",,
"Target json","JSON cible",,
"Target object","Objet cible",,
"Target title","Titre de la cible",,
"Target type","Type cible",,
"Task node","Noeud intermédiaire",,
"Template","Modèle",,
"Text","Texte",,
"Time","Heure",,
"Time spent","Temps passé",,
"Time spent (hours/days)","Temps passé (heures/jours)",,
"Time spent per status (hours)","Temps passé par statut (heures)",,
"Time spent per status per user (hours)","Temps passé par statut par utilisateur (heures)",,
"Title","Titre",,
"To","À",,
"Top menu","Menu supérieur",,
"Total time per status","Temps total par status",,
"Track flow","Suivi processus",,
"Track workflow","Suivre le workflow",,
"Tracking line","Suivi de la ligne",,
"Tracking lines","Suivi des lignes",,
"Transactional","Transactionnel",,
"Transition","Transition",,
"Transitions","Transitions",,
"Type","Type",,
"UI options","Options UI",,
"Update","Mise à jour",,
"User","Utilisateur",,
"Validation type","Type de validation",,
"Value","Valeur",,
"Value expr","Expression évaluée",,
"View","Vue",,
"View generated","Vue générée",,
"View params","Afficher les paramètres",,
"Views","Vues",,
"Widget","Widget",,
"Wkf","Processus",,
"Wkf field","Champ wkf",,
"Wkf sequence",,,
"Wkf tracking","Suivi wkf",,
"Wkf trackings","Suivis wkf",,
"Wkf transition","Transition wkf",,
"Workflow dashboard","Tableau de bord workflow",,
"Workflow is not saved","Le workflow n'est pas sauvegardé",,
"Year","Année",,
"contains","Contient",,
"doesn't contains","Ne contient pas",,
"equal","égal",,
"greater or equal","Supérieur ou égal à",,
"greater than","Supérieur à",,
"in","dans",,
"include","inclus",,
"is false","est faux",,
"is not null","n'est pas nul",,
"is null","est nul",,
"is true","est vrai",,
"less or equal","inférieur ou égal",,
"less than","inférieur à",,
"not equal","n'est pas égal",,
"not in","pas dans",,
"not include","n'est pas inclus",,
"value:BPM","BPM",,
"value:Product App",,,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Libellé:</b> $user: Utilisateur actuel, $date: Date d'aujourd'hui, $time: Heure actuelle
3 AND ET
4 Action Action
5 Action builder Constructeur d'action
6 Action builders Constructeurs d'action
7 Actions Actions
8 Activate the hand tool Activer l'outil manuel
9 Aggregate Agréger
10 Aggregate On Agréger sur
11 Aggregate On type Agréger sur un type
12 Aggregate date type Type de date agrégée
13 Alert Alerte
14 Alert or Blocking condition Condition d'alerte ou de blocage
15 App builder Constructeur d'app
16 App builders Constructeurs d'apps
17 App name Application
18 Append end node Ajouter un nœud terminal
19 Append intermediate node Ajouter un nœud intermédiaire
20 Apply if
21 Area Zone
22 Assign value to Affecter valeur à
23 BPM BPM
24 Background Background
25 Bar Bar
26 Base model Modèle de base
27 Blocking Blocage
28 Boolean Booléen
29 Bpmn xml Bpmn xml
30 Button Bouton
31 Button title Titre du bouton
32 Can Collapse Repliable
33 Chart builder Constructeur de graphique
34 Chart builders Constructeurs de graphiques
35 Chart type Type de graphique
36 ChartBuilder.Group Regrouper
37 Choose App name Choisir application
38 Code
39 Collapse if Replier si
40 Colspan Colspan
41 Condition Condition
42 Conditions Conditions
43 Configuration
44 Connect using transition Connecter en utilisant la transition
45 Context Contexte
46 Create Créer
47 Create end node Créer un nœud terminal
48 Create intermediate node Créer un nœud intermédiaire
49 Create start node Créer un nœud de départ
50 Custom Personnaliser
51 Custom Field Champ personnalisé
52 Custom Model Modèle personnalisé
53 Custom field Champ personnalisé
54 Custom fields Champs personnalisés
55 Custom model Modèle personnalisé
56 Custom models Modèles personnalisés
57 Dashboard
58 Dashboard builder Constructeur de tableaux de bord
59 Dashboard builders Constructeurs de tableaux de bord
60 Dashlet builder Constructeur de dashlet
61 Dashlet builder list Liste des constructeurs de dashlet
62 Dashlet builders Constructeurs de dashlet
63 Data file Fichier de données
64 Date Date
65 Datetime Date et heure
66 Day Jour
67 Decimal Décimal
68 Default Value Valeur par défaut
69 Depends on Dépend de
70 Description
71 Display Affichage
72 Display message Message affiché
73 Display type Type d'affichage
74 Do you want to reset workflow ? Voulez-vous réinitialiser le workflow ?
75 Domain Domaine
76 Donut Donut
77 Dummy Factice
78 Edit Node Modifier un nœud
79 Edit Transition Modifier une transition
80 Edit before send Editer avant d’envoyer
81 Email
82 End node Nœud terminal
83 Existing menu Menu existant
84 Export Exporter
85 Extra Extra
86 Field Champ
87 Field for 'My menu' Champ pour 'Mon menu'
88 Field options Options du champ
89 Fields Champs
90 Filter Filtre
91 Filters Filtres
92 First group by Premier groupe par
93 From De
94 Funnel Entonnoir
95 Gauge Jauge
96 Generated Actions Actions générées
97 Generated app App générée
98 Groovy Groovy
99 Group By Regrouper par
100 Group date type Type de date de groupe
101 Group on type Regrouper sur type
102 Groups Groupes
103 Help Aide
104 Hidden In Grid Caché dans la grille
105 Hidden menu Menu caché
106 Horizontal bar Barre horizontale
107 Icon Icône
108 If Si
109 If-module Si-module
110 Image
111 Import Import
112 Import BPM
113 Import log
114 Incoming Entrant
115 Integer Nombre entier
116 Is Json Relational Field Champ relationnel JSON
117 Is json Est JSON
118 Is parameter Est paramètre
119 Is wkf Est wkf
120 Javascript Javascript
121 Json
122 Json Field Champ Json
123 Json Many To Many Json N à N
124 Json Many To One Json N à 1
125 Json One To Many Json 1 à N
126 Left menu Menu de gauche
127 Line Ligne
128 Link Lien
129 Logic operator Opérateur logique
130 Many To Many N à N
131 Many To One N à 1
132 Max Size Taille max
133 Menu action Constructeur de menu
134 Menu builder Constructeur de menu
135 Menu builders Constructeurs de menus
136 MenuBuilder.Order Ordre
137 Message Message
138 Message on alert or blocking Message sur les alertes ou blocages
139 Message on success Message de succès
140 Meta Model Modèle Meta
141 Meta module
142 MetaMenu
143 Min Size Taille min
144 Mobile menu Menu mobile
145 Model Modèle
146 Module Module
147 Month Mois
148 Name Nom
149 Name Column Colonne nominative
150 Name Field Champ nom
151 Name must not contains space Le nom ne doit pas contenir d'espace
152 Nav Select Nav Select
153 Nb of passes Nb de passages
154 Nb of passes per status Nb de passages par statut
155 Node Nœud
156 Node type Type de nœud
157 Nodes Nœuds
158 None
159 OR OU
160 Object Objet
161 On Change Au changement
162 On Click Au clic
163 On New À la création
164 On Save À la sauvegarde
165 One To Many 1 à N
166 Only use this menu-item if the given expression is true. N'utilisez cet élément de menu que si l'expression donnée est vraie.
167 Only use this menu-item if the given module is installed. N'utilisez cet élément de menu que si le module concerné est installé.
168 Open record Ouvrir enregistrement
169 Open workflow Ouvrir le processus
170 Operator Opérateur
171 Outgoing Sortant
172 Overview Vue d'ensemble
173 Pagination limit Limite de pagination
174 Panel Panel
175 Parent Parent
176 Percentage(%) Pourcentage(%)
177 Permissions Permissions
178 Pie Chart Diagramme circulaire
179 Please correct the workflow diagram. Veuillez corriger le diagramme de workflow.
180 Please input value bind with single quotation. Veuillez entrer les valeurs liées avec une seule guillemet
181 Please provide unique code. The code '%s' is already used Veuillez indiquer un code unique. Le code '%s' est déjà utilisé
182 Process
183 Process display type Type d'affichage du processus
184 Process studio Studio Processus
185 Process tracking Suivi processus
186 Properties Propriétés
187 Radar Radar
188 ReadOnly for Lecture seule pour
189 Record Id Identifiant
190 Record model Objet
191 Record name Nom de l'objet
192 Regex Regex
193 Report Rapport
194 Reporting
195 Required Requis
196 Required If Requis si
197 Roles Rôles
198 Scatter Disperser
199 Script Script
200 Script type Type de script
201 Second group by Deuxième groupe par
202 Select Option Sélectionner option
203 Selection Sélection
204 Selections Sélections
205 Send directly Envoyer directement
206 Send option Option d’envoi
207 Separator Séparateur
208 Sequence Séquence
209 Show If Montrer si
210 Show Title Montrer le titre
211 Show process tracking Afficher le suivi du processus
212 Simple Select Sélection simple
213 Source field Champ source
214 Start node Nœud de départ
215 Status Statut
216 Status per day Statut par jour
217 Status per month Statut par mois
218 Status time(days) Temps du status (en heures)
219 Status time(hours) Temps du status (en jours)
220 String Chaîne de caractères
221 Studio
222 Sub lines Sous-lignes
223 Tag count Compteur
224 Tag label Libellé du tag
225 Tag method Méthode de calcul
226 Tag style Style de tag
227 Target Cible
228 Target Json Model Modèle de cible JSON
229 Target field Champ cible
230 Target json JSON cible
231 Target object Objet cible
232 Target title Titre de la cible
233 Target type Type cible
234 Task node Noeud intermédiaire
235 Template Modèle
236 Text Texte
237 Time Heure
238 Time spent Temps passé
239 Time spent (hours/days) Temps passé (heures/jours)
240 Time spent per status (hours) Temps passé par statut (heures)
241 Time spent per status per user (hours) Temps passé par statut par utilisateur (heures)
242 Title Titre
243 To À
244 Top menu Menu supérieur
245 Total time per status Temps total par status
246 Track flow Suivi processus
247 Track workflow Suivre le workflow
248 Tracking line Suivi de la ligne
249 Tracking lines Suivi des lignes
250 Transactional Transactionnel
251 Transition Transition
252 Transitions Transitions
253 Type Type
254 UI options Options UI
255 Update Mise à jour
256 User Utilisateur
257 Validation type Type de validation
258 Value Valeur
259 Value expr Expression évaluée
260 View Vue
261 View generated Vue générée
262 View params Afficher les paramètres
263 Views Vues
264 Widget Widget
265 Wkf Processus
266 Wkf field Champ wkf
267 Wkf sequence
268 Wkf tracking Suivi wkf
269 Wkf trackings Suivis wkf
270 Wkf transition Transition wkf
271 Workflow dashboard Tableau de bord workflow
272 Workflow is not saved Le workflow n'est pas sauvegardé
273 Year Année
274 contains Contient
275 doesn't contains Ne contient pas
276 equal égal
277 greater or equal Supérieur ou égal à
278 greater than Supérieur à
279 in dans
280 include inclus
281 is false est faux
282 is not null n'est pas nul
283 is null est nul
284 is true est vrai
285 less or equal inférieur ou égal
286 less than inférieur à
287 not equal n'est pas égal
288 not in pas dans
289 not include n'est pas inclus
290 value:BPM BPM
291 value:Product App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Tags:</b> $user: Utente corrente, $date: data di oggi, $time: Ora corrente",,
"AND","E",,
"Action","Azione",,
"Action builder","Costruttore di azioni",,
"Action builders","Costruttori di azioni",,
"Actions","Azioni",,
"Activate the hand tool","Attivare lo strumento manuale",,
"Aggregate","Aggregato",,
"Aggregate On","Aggregato su",,
"Aggregate On type","Aggregato Su tipo",,
"Aggregate date type","Tipo di data aggregata",,
"Alert","Allarme",,
"Alert or Blocking condition","Allarme o condizione di blocco",,
"App builder","Costruttore di applicazioni",,
"App builders",,,
"App name",,,
"Append end node","Append end nodo di fine",,
"Append intermediate node","Aggiungete un nodo intermedio",,
"Apply if",,,
"Area","Area",,
"Assign value to","Assegnare il valore a",,
"BPM","BPM",,
"Background","Sfondo",,
"Bar","Bar",,
"Base model",,,
"Blocking","Blocco",,
"Boolean","booleano",,
"Bpmn xml","Bpmn xml",,
"Button","Pulsante",,
"Button title","Titolo del pulsante",,
"Can Collapse",,,
"Chart builder","Costruttore di grafici",,
"Chart builders","Costruttori di carte nautiche",,
"Chart type","Tipo di grafico",,
"ChartBuilder.Group","Gruppo",,
"Choose App name",,,
"Code","Codice",,
"Collapse if",,,
"Colspan","Colspan",,
"Condition","Condizione",,
"Conditions","Condizioni",,
"Configuration",,,
"Connect using transition","Connettiti usando la transizione",,
"Context","Contesto",,
"Create","Creare",,
"Create end node","Crea nodo finale",,
"Create intermediate node","Creare un nodo intermedio",,
"Create start node","Crea nodo di partenza",,
"Custom","Personalizzato",,
"Custom Field","Campo personalizzato",,
"Custom Model","Modello personalizzato",,
"Custom field","Campo personalizzato",,
"Custom fields","Campi personalizzati",,
"Custom model","Modello personalizzato",,
"Custom models","Modelli personalizzati",,
"Dashboard","Cruscotto",,
"Dashboard builder","Costruttore di cruscotti",,
"Dashboard builders","Costruttori di cruscotti",,
"Dashlet builder","Costruttore di cruscotti",,
"Dashlet builder list","Elenco dei costruttori di cruscotti",,
"Dashlet builders","Costruttori di cruscotti",,
"Data file","File di dati",,
"Date","Data",,
"Datetime","Data e ora",,
"Day","Giorno",,
"Decimal","Decimale",,
"Default Value","Valore predefinito",,
"Depends on","Dipende",,
"Description","Descrizione",,
"Display","Display",,
"Display message","Messaggio sul display",,
"Display type","Tipo di display",,
"Do you want to reset workflow ?",,,
"Domain","Dominio",,
"Donut","Ciambella",,
"Dummy","Manichino",,
"Edit Node","Modifica nodo",,
"Edit Transition","Modifica Transizione",,
"Edit before send","Modifica prima dell'invio",,
"Email","Email eMail",,
"End node","Nodo finale",,
"Existing menu","Menu esistente",,
"Export","Esportazione",,
"Extra","Extra",,
"Field","Campo",,
"Field for 'My menu'","Campo per 'Il mio menu'.",,
"Field options",,,
"Fields","I campi",,
"Filter","Filtro",,
"Filters","Filtri",,
"First group by","Primo gruppo per",,
"From","Da",,
"Funnel","Imbuto",,
"Gauge","Calibro",,
"Generated Actions","Azioni generate",,
"Generated app","App generata",,
"Groovy","Groovy",,
"Group By","Gruppo per",,
"Group date type","Tipo di data di gruppo",,
"Group on type","Gruppo per tipo",,
"Groups","Gruppi",,
"Help","Aiuto",,
"Hidden In Grid","Nascosto nella griglia",,
"Hidden menu","Menu nascosto",,
"Horizontal bar","Barra orizzontale",,
"Icon","Icona",,
"If","Se",,
"If-module","Modulo If",,
"Image","Immagine",,
"Import","Importazione",,
"Import BPM","Importazione BPM",,
"Import log","Importa log",,
"Incoming","Arrivo",,
"Integer","Intero",,
"Is Json Relational Field",,,
"Is json","E' Json",,
"Is parameter","È parametro",,
"Is wkf","È wkf",,
"Javascript","Javascript",,
"Json","Json",,
"Json Field","Campo Json",,
"Json Many To Many","Json molti a molti a molti",,
"Json Many To One","Json molti a uno",,
"Json One To Many","Json uno a molti",,
"Left menu","Menu di sinistra",,
"Line","Linea",,
"Link","Collegamento",,
"Logic operator","Operatore logico",,
"Many To Many","Molti a molti a molti",,
"Many To One","Molti a uno",,
"Max Size","Dimensione massima",,
"Menu action","Azione del menu",,
"Menu builder","Costruttore di menu",,
"Menu builders","Costruttori di menu",,
"MenuBuilder.Order","Ordine",,
"Message","Messaggio",,
"Message on alert or blocking","Messaggio in caso di allarme o blocco",,
"Message on success","Messaggio sul successo",,
"Meta Model","Meta Modello",,
"Meta module","Meta modulo",,
"MetaMenu","MetaMenu",,
"Min Size","Dimensione minima",,
"Mobile menu","Menu mobile",,
"Model","Modello",,
"Module","Modulo",,
"Month","Mese",,
"Name","Nome",,
"Name Column",,,
"Name Field","Nome Campo",,
"Name must not contains space","Il nome non deve contenere spazio",,
"Nav Select","Seleziona Nav",,
"Nb of passes","Numero di passaggi",,
"Nb of passes per status","Nb di pass per stato",,
"Node","Nodo",,
"Node type",,,
"Nodes","Nodi",,
"None",,,
"OR","OPPURE",,
"Object","Oggetto",,
"On Change","In Cambia",,
"On Click","Su Click",,
"On New","Su Nuovo",,
"On Save","Su salvare",,
"One To Many","Uno a molti",,
"Only use this menu-item if the given expression is true.","Utilizzare questa voce di menu solo se l'espressione data è vera.",,
"Only use this menu-item if the given module is installed.","Utilizzare questa voce di menu solo se il modulo in questione è installato.",,
"Open record","Apri record",,
"Open workflow","Flusso di lavoro aperto",,
"Operator","Operatore",,
"Outgoing","In uscita",,
"Overview","Panoramica",,
"Pagination limit","Limite di impaginazione",,
"Panel","Pannello",,
"Parent","Genitore",,
"Percentage(%)","Percentuale (%)",,
"Permissions","Autorizzazioni",,
"Pie Chart","Grafico a torta",,
"Please correct the workflow diagram.","Si prega di correggere il diagramma del flusso di lavoro.",,
"Please input value bind with single quotation.","Si prega di inserire il valore da associare alla quotazione singola.",,
"Please provide unique code. The code '%s' is already used","Si prega di fornire un codice univoco. Il codice %s è già utilizzato",,
"Process",,,
"Process display type","Tipo di visualizzazione del processo",,
"Process studio","Studio di processo",,
"Process tracking","Tracciabilità del processo",,
"Properties","Proprietà",,
"Radar","Radar",,
"ReadOnly for",,,
"Record Id","Id record",,
"Record model","Modello di record",,
"Record name","Nome del record",,
"Regex","Regex",,
"Report","Segnala",,
"Reporting",,,
"Required","Richiesto",,
"Required If","Richiesto Se",,
"Roles","Ruoli",,
"Scatter","Spargimento",,
"Script","Sceneggiatura",,
"Script type","Tipo di script",,
"Second group by","Secondo gruppo per",,
"Select Option","Selezionare l'opzione",,
"Selection","Selezione",,
"Selections",,,
"Send directly","Inviare direttamente",,
"Send option","Opzione Invio",,
"Separator","Separatore",,
"Sequence","Sequenza",,
"Show If","Mostra se",,
"Show Title",,,
"Show process tracking","Mostra il monitoraggio del processo",,
"Simple Select","Selezione semplice",,
"Source field","Fonte Campo",,
"Start node","Nodo di partenza",,
"Status","Stato",,
"Status per day","Stato al giorno",,
"Status per month","Stato al mese",,
"Status time(days)","Tempo di stato (giorni)",,
"Status time(hours)","Tempo di stato (ore)",,
"String","Stringa",,
"Studio",,,
"Sub lines","Linee secondarie",,
"Tag count","Numero di tag",,
"Tag label","Etichetta dell'etichetta",,
"Tag method","Metodo dei tag",,
"Tag style","Stile dell'etichetta",,
"Target","Obiettivo",,
"Target Json Model","Obiettivo Json modello",,
"Target field","Campo target",,
"Target json","Json bersaglio",,
"Target object","Oggetto target",,
"Target title",,,
"Target type","Tipo di target",,
"Task node",,,
"Template","Modello",,
"Text","Testo",,
"Time","Tempo",,
"Time spent","Tempo trascorso",,
"Time spent (hours/days)","Tempo di permanenza (ore/giorni)",,
"Time spent per status (hours)","Tempo trascorso per stato (ore)",,
"Time spent per status per user (hours)","Tempo di permanenza per stato per utente (ore)",,
"Title","Titolo",,
"To","A",,
"Top menu","Menu principale",,
"Total time per status","Tempo totale per stato",,
"Track flow","Flusso della pista",,
"Track workflow","Traccia il flusso di lavoro",,
"Tracking line","Linea di monitoraggio",,
"Tracking lines","Linee di tracciamento",,
"Transactional","Transazionale",,
"Transition","Transizione",,
"Transitions","Transizioni",,
"Type","Tipo",,
"UI options",,,
"Update","Aggiorna",,
"User","Utente",,
"Validation type","Tipo di convalida",,
"Value","Valore",,
"Value expr","Valore",,
"View","Vista",,
"View generated","Vista generata",,
"View params","Visualizza i parametri",,
"Views","Viste",,
"Widget","Widget",,
"Wkf","Wkf",,
"Wkf field","Campo Wkf",,
"Wkf sequence",,,
"Wkf tracking","Inseguimento di Wkf",,
"Wkf trackings","Tracciati Wkf",,
"Wkf transition","Transizione Wkf",,
"Workflow dashboard","Flusso di lavoro cruscotto",,
"Workflow is not saved","Il flusso di lavoro non viene salvato",,
"Year","Anno",,
"contains","contiene",,
"doesn't contains","non contiene",,
"equal","paritario",,
"greater or equal","maggiore o uguale",,
"greater than","maggiore di",,
"in","in",,
"include","comprendere",,
"is false","è falso",,
"is not null","non è nullo",,
"is null","è nullo",,
"is true","è vero",,
"less or equal","inferiore o uguale",,
"less than","meno di",,
"not equal","non uguale",,
"not in","non in",,
"not include","non includere",,
"value:BPM","valore:BPM",,
"value:Product App","valore:Prodotto App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Tags:</b> $user: Utente corrente, $date: data di oggi, $time: Ora corrente
3 AND E
4 Action Azione
5 Action builder Costruttore di azioni
6 Action builders Costruttori di azioni
7 Actions Azioni
8 Activate the hand tool Attivare lo strumento manuale
9 Aggregate Aggregato
10 Aggregate On Aggregato su
11 Aggregate On type Aggregato Su tipo
12 Aggregate date type Tipo di data aggregata
13 Alert Allarme
14 Alert or Blocking condition Allarme o condizione di blocco
15 App builder Costruttore di applicazioni
16 App builders
17 App name
18 Append end node Append end nodo di fine
19 Append intermediate node Aggiungete un nodo intermedio
20 Apply if
21 Area Area
22 Assign value to Assegnare il valore a
23 BPM BPM
24 Background Sfondo
25 Bar Bar
26 Base model
27 Blocking Blocco
28 Boolean booleano
29 Bpmn xml Bpmn xml
30 Button Pulsante
31 Button title Titolo del pulsante
32 Can Collapse
33 Chart builder Costruttore di grafici
34 Chart builders Costruttori di carte nautiche
35 Chart type Tipo di grafico
36 ChartBuilder.Group Gruppo
37 Choose App name
38 Code Codice
39 Collapse if
40 Colspan Colspan
41 Condition Condizione
42 Conditions Condizioni
43 Configuration
44 Connect using transition Connettiti usando la transizione
45 Context Contesto
46 Create Creare
47 Create end node Crea nodo finale
48 Create intermediate node Creare un nodo intermedio
49 Create start node Crea nodo di partenza
50 Custom Personalizzato
51 Custom Field Campo personalizzato
52 Custom Model Modello personalizzato
53 Custom field Campo personalizzato
54 Custom fields Campi personalizzati
55 Custom model Modello personalizzato
56 Custom models Modelli personalizzati
57 Dashboard Cruscotto
58 Dashboard builder Costruttore di cruscotti
59 Dashboard builders Costruttori di cruscotti
60 Dashlet builder Costruttore di cruscotti
61 Dashlet builder list Elenco dei costruttori di cruscotti
62 Dashlet builders Costruttori di cruscotti
63 Data file File di dati
64 Date Data
65 Datetime Data e ora
66 Day Giorno
67 Decimal Decimale
68 Default Value Valore predefinito
69 Depends on Dipende
70 Description Descrizione
71 Display Display
72 Display message Messaggio sul display
73 Display type Tipo di display
74 Do you want to reset workflow ?
75 Domain Dominio
76 Donut Ciambella
77 Dummy Manichino
78 Edit Node Modifica nodo
79 Edit Transition Modifica Transizione
80 Edit before send Modifica prima dell'invio
81 Email Email eMail
82 End node Nodo finale
83 Existing menu Menu esistente
84 Export Esportazione
85 Extra Extra
86 Field Campo
87 Field for 'My menu' Campo per 'Il mio menu'.
88 Field options
89 Fields I campi
90 Filter Filtro
91 Filters Filtri
92 First group by Primo gruppo per
93 From Da
94 Funnel Imbuto
95 Gauge Calibro
96 Generated Actions Azioni generate
97 Generated app App generata
98 Groovy Groovy
99 Group By Gruppo per
100 Group date type Tipo di data di gruppo
101 Group on type Gruppo per tipo
102 Groups Gruppi
103 Help Aiuto
104 Hidden In Grid Nascosto nella griglia
105 Hidden menu Menu nascosto
106 Horizontal bar Barra orizzontale
107 Icon Icona
108 If Se
109 If-module Modulo If
110 Image Immagine
111 Import Importazione
112 Import BPM Importazione BPM
113 Import log Importa log
114 Incoming Arrivo
115 Integer Intero
116 Is Json Relational Field
117 Is json E' Json
118 Is parameter È parametro
119 Is wkf È wkf
120 Javascript Javascript
121 Json Json
122 Json Field Campo Json
123 Json Many To Many Json molti a molti a molti
124 Json Many To One Json molti a uno
125 Json One To Many Json uno a molti
126 Left menu Menu di sinistra
127 Line Linea
128 Link Collegamento
129 Logic operator Operatore logico
130 Many To Many Molti a molti a molti
131 Many To One Molti a uno
132 Max Size Dimensione massima
133 Menu action Azione del menu
134 Menu builder Costruttore di menu
135 Menu builders Costruttori di menu
136 MenuBuilder.Order Ordine
137 Message Messaggio
138 Message on alert or blocking Messaggio in caso di allarme o blocco
139 Message on success Messaggio sul successo
140 Meta Model Meta Modello
141 Meta module Meta modulo
142 MetaMenu MetaMenu
143 Min Size Dimensione minima
144 Mobile menu Menu mobile
145 Model Modello
146 Module Modulo
147 Month Mese
148 Name Nome
149 Name Column
150 Name Field Nome Campo
151 Name must not contains space Il nome non deve contenere spazio
152 Nav Select Seleziona Nav
153 Nb of passes Numero di passaggi
154 Nb of passes per status Nb di pass per stato
155 Node Nodo
156 Node type
157 Nodes Nodi
158 None
159 OR OPPURE
160 Object Oggetto
161 On Change In Cambia
162 On Click Su Click
163 On New Su Nuovo
164 On Save Su salvare
165 One To Many Uno a molti
166 Only use this menu-item if the given expression is true. Utilizzare questa voce di menu solo se l'espressione data è vera.
167 Only use this menu-item if the given module is installed. Utilizzare questa voce di menu solo se il modulo in questione è installato.
168 Open record Apri record
169 Open workflow Flusso di lavoro aperto
170 Operator Operatore
171 Outgoing In uscita
172 Overview Panoramica
173 Pagination limit Limite di impaginazione
174 Panel Pannello
175 Parent Genitore
176 Percentage(%) Percentuale (%)
177 Permissions Autorizzazioni
178 Pie Chart Grafico a torta
179 Please correct the workflow diagram. Si prega di correggere il diagramma del flusso di lavoro.
180 Please input value bind with single quotation. Si prega di inserire il valore da associare alla quotazione singola.
181 Please provide unique code. The code '%s' is already used Si prega di fornire un codice univoco. Il codice %s è già utilizzato
182 Process
183 Process display type Tipo di visualizzazione del processo
184 Process studio Studio di processo
185 Process tracking Tracciabilità del processo
186 Properties Proprietà
187 Radar Radar
188 ReadOnly for
189 Record Id Id record
190 Record model Modello di record
191 Record name Nome del record
192 Regex Regex
193 Report Segnala
194 Reporting
195 Required Richiesto
196 Required If Richiesto Se
197 Roles Ruoli
198 Scatter Spargimento
199 Script Sceneggiatura
200 Script type Tipo di script
201 Second group by Secondo gruppo per
202 Select Option Selezionare l'opzione
203 Selection Selezione
204 Selections
205 Send directly Inviare direttamente
206 Send option Opzione Invio
207 Separator Separatore
208 Sequence Sequenza
209 Show If Mostra se
210 Show Title
211 Show process tracking Mostra il monitoraggio del processo
212 Simple Select Selezione semplice
213 Source field Fonte Campo
214 Start node Nodo di partenza
215 Status Stato
216 Status per day Stato al giorno
217 Status per month Stato al mese
218 Status time(days) Tempo di stato (giorni)
219 Status time(hours) Tempo di stato (ore)
220 String Stringa
221 Studio
222 Sub lines Linee secondarie
223 Tag count Numero di tag
224 Tag label Etichetta dell'etichetta
225 Tag method Metodo dei tag
226 Tag style Stile dell'etichetta
227 Target Obiettivo
228 Target Json Model Obiettivo Json modello
229 Target field Campo target
230 Target json Json bersaglio
231 Target object Oggetto target
232 Target title
233 Target type Tipo di target
234 Task node
235 Template Modello
236 Text Testo
237 Time Tempo
238 Time spent Tempo trascorso
239 Time spent (hours/days) Tempo di permanenza (ore/giorni)
240 Time spent per status (hours) Tempo trascorso per stato (ore)
241 Time spent per status per user (hours) Tempo di permanenza per stato per utente (ore)
242 Title Titolo
243 To A
244 Top menu Menu principale
245 Total time per status Tempo totale per stato
246 Track flow Flusso della pista
247 Track workflow Traccia il flusso di lavoro
248 Tracking line Linea di monitoraggio
249 Tracking lines Linee di tracciamento
250 Transactional Transazionale
251 Transition Transizione
252 Transitions Transizioni
253 Type Tipo
254 UI options
255 Update Aggiorna
256 User Utente
257 Validation type Tipo di convalida
258 Value Valore
259 Value expr Valore
260 View Vista
261 View generated Vista generata
262 View params Visualizza i parametri
263 Views Viste
264 Widget Widget
265 Wkf Wkf
266 Wkf field Campo Wkf
267 Wkf sequence
268 Wkf tracking Inseguimento di Wkf
269 Wkf trackings Tracciati Wkf
270 Wkf transition Transizione Wkf
271 Workflow dashboard Flusso di lavoro cruscotto
272 Workflow is not saved Il flusso di lavoro non viene salvato
273 Year Anno
274 contains contiene
275 doesn't contains non contiene
276 equal paritario
277 greater or equal maggiore o uguale
278 greater than maggiore di
279 in in
280 include comprendere
281 is false è falso
282 is not null non è nullo
283 is null è nullo
284 is true è vero
285 less or equal inferiore o uguale
286 less than meno di
287 not equal non uguale
288 not in non in
289 not include non includere
290 value:BPM valore:BPM
291 value:Product App valore:Prodotto App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Tags:</b> $user: Huidige gebruiker, $date: datum van vandaag, $time: Huidige tijd",,
"AND","EN",,
"Action","Actie",,
"Action builder","Actie bouwer",,
"Action builders","Actiebouwers",,
"Actions","Acties",,
"Activate the hand tool","Activeer het handgereedschap",,
"Aggregate","Geaggregeerd",,
"Aggregate On","Geaggregeerd op",,
"Aggregate On type","Geaggregeerd Op type",,
"Aggregate date type","Geaggregeerde datum type",,
"Alert","Alarm",,
"Alert or Blocking condition","Waarschuwing of blokkeringstoestand",,
"App builder","App bouwer",,
"App builders",,,
"App name",,,
"Append end node","Eindknooppunt toevoegen",,
"Append intermediate node","Voeg tussenliggende knoop toe",,
"Apply if",,,
"Area","Gebied",,
"Assign value to","Wijs waarde toe aan",,
"BPM","BPM",,
"Background","Achtergrond",,
"Bar","Bar",,
"Base model",,,
"Blocking","Blokkeren",,
"Boolean","Booleaans",,
"Bpmn xml","Bpmn xml",,
"Button","Knop",,
"Button title","Titel van de knop",,
"Can Collapse",,,
"Chart builder","Grafiekbouwer",,
"Chart builders","Grafiekbouwers",,
"Chart type","Grafiektype",,
"ChartBuilder.Group","Groep",,
"Choose App name",,,
"Code","Code",,
"Collapse if",,,
"Colspan","Colspan",,
"Condition","Voorwaarde",,
"Conditions","Voorwaarden",,
"Configuration",,,
"Connect using transition","Aansluiten met behulp van de overgang",,
"Context","Context",,
"Create","Creëer",,
"Create end node","Eindknoop maken",,
"Create intermediate node","Creëer tussenliggende knoop",,
"Create start node","Startknooppunt maken",,
"Custom","Douane",,
"Custom Field","Aangepast veld",,
"Custom Model","Aangepast model",,
"Custom field","Aangepast veld",,
"Custom fields","Aangepaste velden",,
"Custom model","Aangepast model",,
"Custom models","Aangepaste modellen",,
"Dashboard","Dashboard",,
"Dashboard builder","Dashboard bouwer",,
"Dashboard builders","Dashboard bouwers",,
"Dashlet builder","Dashlet bouwer",,
"Dashlet builder list","Dashlet bouwer lijst",,
"Dashlet builders","Dashlet bouwers",,
"Data file","Gegevensbestand",,
"Date","Datum",,
"Datetime","Datetime",,
"Day","Dag",,
"Decimal","Decimaal",,
"Default Value","Standaardwaarde",,
"Depends on","Afhankelijk van",,
"Description","Beschrijving",,
"Display","Vertoning",,
"Display message","Weergave bericht",,
"Display type","Type display",,
"Do you want to reset workflow ?",,,
"Domain","Domein",,
"Donut","Donut",,
"Dummy","Dummy",,
"Edit Node","Knooppunt bewerken",,
"Edit Transition","Overgang bewerken",,
"Edit before send","Bewerken voor verzending",,
"Email","E-mail",,
"End node","Eindknoop",,
"Existing menu","Bestaand menu",,
"Export","Exporteren",,
"Extra","Extra",,
"Field","Veld",,
"Field for 'My menu'","Veld voor 'Mijn menu'",,
"Field options",,,
"Fields","Velden",,
"Filter","Filter",,
"Filters","Filters",,
"First group by","Eerste groep door",,
"From","Van",,
"Funnel","Trechter",,
"Gauge","Meter",,
"Generated Actions","Gegenereerde acties",,
"Generated app","Gegenereerde app",,
"Groovy","Groovy",,
"Group By","Groep Per",,
"Group date type","Groepsdatum type",,
"Group on type","Groep op type",,
"Groups","Groepen",,
"Help","Hulp",,
"Hidden In Grid","Verborgen in raster",,
"Hidden menu","Verborgen menu",,
"Horizontal bar","Horizontale balk",,
"Icon","Pictogram",,
"If","Indien",,
"If-module","Als-module",,
"Image","Beeld",,
"Import","Importeren",,
"Import BPM","Importeren BPM",,
"Import log","Logboek importeren",,
"Incoming","Inkomend",,
"Integer","Geheel getal",,
"Is Json Relational Field",,,
"Is json","Is json",,
"Is parameter","Is parameter",,
"Is wkf","Is wkf",,
"Javascript","Javascript",,
"Json","Json",,
"Json Field","Json veld",,
"Json Many To Many","Json veel te veel voor veel",,
"Json Many To One","Json Vele aan Één",,
"Json One To Many","Json een voor veel",,
"Left menu","Menu links",,
"Line","Lijn",,
"Link","Link",,
"Logic operator","Logische operator",,
"Many To Many","Veel te veel voor veel",,
"Many To One","Veel naar een",,
"Max Size","Maximum Grootte",,
"Menu action","Menu actie",,
"Menu builder","Menu bouwer",,
"Menu builders","Menu bouwers",,
"MenuBuilder.Order","Orde",,
"Message","Bericht",,
"Message on alert or blocking","Bericht over waarschuwing of blokkering",,
"Message on success","Bericht over succes",,
"Meta Model","Metamodel",,
"Meta module","Metamodule",,
"MetaMenu","MetaMenu",,
"Min Size","Min. grootte",,
"Mobile menu","Mobiel menu",,
"Model","Model",,
"Module","Module",,
"Month","Maand",,
"Name","Naam",,
"Name Column",,,
"Name Field","Naam Veld",,
"Name must not contains space","Naam mag geen ruimte bevatten",,
"Nav Select","Navigatie Kiezen",,
"Nb of passes","Aantal passen",,
"Nb of passes per status","Aantal passen per status",,
"Node","Knooppunt",,
"Node type","Type de nœud",,
"Nodes","Knooppunten",,
"None",,,
"OR","OF",,
"Object","Voorwerp",,
"On Change","Over verandering",,
"On Click","Op Klik",,
"On New","Op Nieuw",,
"On Save","Op Opslaan",,
"One To Many","Een naar veel",,
"Only use this menu-item if the given expression is true.","Gebruik dit menu-item alleen als de gegeven uitdrukking waar is.",,
"Only use this menu-item if the given module is installed.","Gebruik dit menu-item alleen als de gegeven module is geïnstalleerd.",,
"Open record","Open record",,
"Open workflow","Open workflow",,
"Operator","Exploitant",,
"Outgoing","Uitgaand",,
"Overview","Overzicht",,
"Pagination limit","Paginatiegrens",,
"Panel","Paneel",,
"Parent","Ouder",,
"Percentage(%)","Percentage (%)",,
"Permissions","Toestemmingen",,
"Pie Chart","Taartdiagram",,
"Please correct the workflow diagram.","Corrigeer het workflow diagram.",,
"Please input value bind with single quotation.","Gelieve de invoerwaarde te binden met één offerte.",,
"Please provide unique code. The code '%s' is already used","Geef een unieke code op. De code %s wordt reeds gebruikt",,
"Process",,,
"Process display type","Type procesweergave",,
"Process studio","Processtudio",,
"Process tracking","Proces het volgen",,
"Properties","Eigenschappen",,
"Radar","Radar",,
"ReadOnly for","Lecture seule pour",,
"Record Id","Verslag Id",,
"Record model","Record model",,
"Record name","Naam record",,
"Regex","Regex",,
"Report","Verslag",,
"Reporting",,,
"Required","Vereist",,
"Required If","Vereist indien",,
"Roles","Rollen",,
"Scatter","Verstrooien",,
"Script","Script",,
"Script type","Scripttype",,
"Second group by","Tweede groep door",,
"Select Option","Selecteer optie",,
"Selection","Selectie",,
"Selections",,,
"Send directly","Direct verzenden",,
"Send option","Verzend optie",,
"Separator","Scheider",,
"Sequence","Volgorde",,
"Show If","Toon als",,
"Show Title",,,
"Show process tracking","Toon procesvolgsysteem",,
"Simple Select","Eenvoudig selecteren",,
"Source field","Bronveld",,
"Start node","Startknoop",,
"Status","Status",,
"Status per day","Status per dag",,
"Status per month","Status per maand",,
"Status time(days)","Status tijd (dagen)",,
"Status time(hours)","Status tijd (uren)",,
"String","Snaar",,
"Studio",,,
"Sub lines","Onderlijnen",,
"Tag count","Tagtelling",,
"Tag label","Markeringsetiket",,
"Tag method","Tag methode",,
"Tag style","Tag stijl",,
"Target","Doel",,
"Target Json Model","Doel Json Model",,
"Target field","Doelveld",,
"Target json","Doelgroep json",,
"Target object","Doelobject",,
"Target title",,,
"Target type","Doeltype",,
"Task node","Noeud intermédiaire",,
"Template","Sjabloon",,
"Text","Tekst",,
"Time","Tijd",,
"Time spent","Doorgebrachte tijd",,
"Time spent (hours/days)","bestede tijd (uren/dagen)",,
"Time spent per status (hours)","bestede tijd per status (uren)",,
"Time spent per status per user (hours)","bestede tijd per status per gebruiker (uren)",,
"Title","Titel",,
"To","Naar",,
"Top menu","Hoofdmenu",,
"Total time per status","Totale tijd per status",,
"Track flow","Spoorstroom",,
"Track workflow","Traceer de workflow",,
"Tracking line","Het volgen van lijn",,
"Tracking lines","Het volgen van lijnen",,
"Transactional","Transactioneel",,
"Transition","Overgang",,
"Transitions","Overgangen",,
"Type","Type",,
"UI options",,,
"Update","Update",,
"User","Gebruiker",,
"Validation type","Type validatie",,
"Value","Waarde",,
"Value expr",,,
"View","Bekijk",,
"View generated","Weergave gegenereerd",,
"View params","Bekijk params",,
"Views","Uitzicht",,
"Widget","Widget",,
"Wkf","Wkf",,
"Wkf field","Wkf veld",,
"Wkf sequence",,,
"Wkf tracking","Wkf het volgen",,
"Wkf trackings","Wkf rupsbanden",,
"Wkf transition","Wkf overgang",,
"Workflow dashboard","Workflow dashboard",,
"Workflow is not saved","Workflow wordt niet opgeslagen",,
"Year","Jaar",,
"contains","bevat",,
"doesn't contains","bevat niet",,
"equal","gelijk",,
"greater or equal","groter of gelijk",,
"greater than","groter dan",,
"in","naar binnen",,
"include","behelzen",,
"is false","vals is",,
"is not null","niet ongeldig is",,
"is null","is ongeldig",,
"is true","waar is",,
"less or equal","minder of gelijk",,
"less than","minder dan",,
"not equal","niet gelijk",,
"not in","niet in",,
"not include","niet omvatten",,
"value:BPM","waarde: BPM",,
"value:Product App","waarde: Product App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Tags:</b> $user: Huidige gebruiker, $date: datum van vandaag, $time: Huidige tijd
3 AND EN
4 Action Actie
5 Action builder Actie bouwer
6 Action builders Actiebouwers
7 Actions Acties
8 Activate the hand tool Activeer het handgereedschap
9 Aggregate Geaggregeerd
10 Aggregate On Geaggregeerd op
11 Aggregate On type Geaggregeerd Op type
12 Aggregate date type Geaggregeerde datum type
13 Alert Alarm
14 Alert or Blocking condition Waarschuwing of blokkeringstoestand
15 App builder App bouwer
16 App builders
17 App name
18 Append end node Eindknooppunt toevoegen
19 Append intermediate node Voeg tussenliggende knoop toe
20 Apply if
21 Area Gebied
22 Assign value to Wijs waarde toe aan
23 BPM BPM
24 Background Achtergrond
25 Bar Bar
26 Base model
27 Blocking Blokkeren
28 Boolean Booleaans
29 Bpmn xml Bpmn xml
30 Button Knop
31 Button title Titel van de knop
32 Can Collapse
33 Chart builder Grafiekbouwer
34 Chart builders Grafiekbouwers
35 Chart type Grafiektype
36 ChartBuilder.Group Groep
37 Choose App name
38 Code Code
39 Collapse if
40 Colspan Colspan
41 Condition Voorwaarde
42 Conditions Voorwaarden
43 Configuration
44 Connect using transition Aansluiten met behulp van de overgang
45 Context Context
46 Create Creëer
47 Create end node Eindknoop maken
48 Create intermediate node Creëer tussenliggende knoop
49 Create start node Startknooppunt maken
50 Custom Douane
51 Custom Field Aangepast veld
52 Custom Model Aangepast model
53 Custom field Aangepast veld
54 Custom fields Aangepaste velden
55 Custom model Aangepast model
56 Custom models Aangepaste modellen
57 Dashboard Dashboard
58 Dashboard builder Dashboard bouwer
59 Dashboard builders Dashboard bouwers
60 Dashlet builder Dashlet bouwer
61 Dashlet builder list Dashlet bouwer lijst
62 Dashlet builders Dashlet bouwers
63 Data file Gegevensbestand
64 Date Datum
65 Datetime Datetime
66 Day Dag
67 Decimal Decimaal
68 Default Value Standaardwaarde
69 Depends on Afhankelijk van
70 Description Beschrijving
71 Display Vertoning
72 Display message Weergave bericht
73 Display type Type display
74 Do you want to reset workflow ?
75 Domain Domein
76 Donut Donut
77 Dummy Dummy
78 Edit Node Knooppunt bewerken
79 Edit Transition Overgang bewerken
80 Edit before send Bewerken voor verzending
81 Email E-mail
82 End node Eindknoop
83 Existing menu Bestaand menu
84 Export Exporteren
85 Extra Extra
86 Field Veld
87 Field for 'My menu' Veld voor 'Mijn menu'
88 Field options
89 Fields Velden
90 Filter Filter
91 Filters Filters
92 First group by Eerste groep door
93 From Van
94 Funnel Trechter
95 Gauge Meter
96 Generated Actions Gegenereerde acties
97 Generated app Gegenereerde app
98 Groovy Groovy
99 Group By Groep Per
100 Group date type Groepsdatum type
101 Group on type Groep op type
102 Groups Groepen
103 Help Hulp
104 Hidden In Grid Verborgen in raster
105 Hidden menu Verborgen menu
106 Horizontal bar Horizontale balk
107 Icon Pictogram
108 If Indien
109 If-module Als-module
110 Image Beeld
111 Import Importeren
112 Import BPM Importeren BPM
113 Import log Logboek importeren
114 Incoming Inkomend
115 Integer Geheel getal
116 Is Json Relational Field
117 Is json Is json
118 Is parameter Is parameter
119 Is wkf Is wkf
120 Javascript Javascript
121 Json Json
122 Json Field Json veld
123 Json Many To Many Json veel te veel voor veel
124 Json Many To One Json Vele aan Één
125 Json One To Many Json een voor veel
126 Left menu Menu links
127 Line Lijn
128 Link Link
129 Logic operator Logische operator
130 Many To Many Veel te veel voor veel
131 Many To One Veel naar een
132 Max Size Maximum Grootte
133 Menu action Menu actie
134 Menu builder Menu bouwer
135 Menu builders Menu bouwers
136 MenuBuilder.Order Orde
137 Message Bericht
138 Message on alert or blocking Bericht over waarschuwing of blokkering
139 Message on success Bericht over succes
140 Meta Model Metamodel
141 Meta module Metamodule
142 MetaMenu MetaMenu
143 Min Size Min. grootte
144 Mobile menu Mobiel menu
145 Model Model
146 Module Module
147 Month Maand
148 Name Naam
149 Name Column
150 Name Field Naam Veld
151 Name must not contains space Naam mag geen ruimte bevatten
152 Nav Select Navigatie Kiezen
153 Nb of passes Aantal passen
154 Nb of passes per status Aantal passen per status
155 Node Knooppunt
156 Node type Type de nœud
157 Nodes Knooppunten
158 None
159 OR OF
160 Object Voorwerp
161 On Change Over verandering
162 On Click Op Klik
163 On New Op Nieuw
164 On Save Op Opslaan
165 One To Many Een naar veel
166 Only use this menu-item if the given expression is true. Gebruik dit menu-item alleen als de gegeven uitdrukking waar is.
167 Only use this menu-item if the given module is installed. Gebruik dit menu-item alleen als de gegeven module is geïnstalleerd.
168 Open record Open record
169 Open workflow Open workflow
170 Operator Exploitant
171 Outgoing Uitgaand
172 Overview Overzicht
173 Pagination limit Paginatiegrens
174 Panel Paneel
175 Parent Ouder
176 Percentage(%) Percentage (%)
177 Permissions Toestemmingen
178 Pie Chart Taartdiagram
179 Please correct the workflow diagram. Corrigeer het workflow diagram.
180 Please input value bind with single quotation. Gelieve de invoerwaarde te binden met één offerte.
181 Please provide unique code. The code '%s' is already used Geef een unieke code op. De code %s wordt reeds gebruikt
182 Process
183 Process display type Type procesweergave
184 Process studio Processtudio
185 Process tracking Proces het volgen
186 Properties Eigenschappen
187 Radar Radar
188 ReadOnly for Lecture seule pour
189 Record Id Verslag Id
190 Record model Record model
191 Record name Naam record
192 Regex Regex
193 Report Verslag
194 Reporting
195 Required Vereist
196 Required If Vereist indien
197 Roles Rollen
198 Scatter Verstrooien
199 Script Script
200 Script type Scripttype
201 Second group by Tweede groep door
202 Select Option Selecteer optie
203 Selection Selectie
204 Selections
205 Send directly Direct verzenden
206 Send option Verzend optie
207 Separator Scheider
208 Sequence Volgorde
209 Show If Toon als
210 Show Title
211 Show process tracking Toon procesvolgsysteem
212 Simple Select Eenvoudig selecteren
213 Source field Bronveld
214 Start node Startknoop
215 Status Status
216 Status per day Status per dag
217 Status per month Status per maand
218 Status time(days) Status tijd (dagen)
219 Status time(hours) Status tijd (uren)
220 String Snaar
221 Studio
222 Sub lines Onderlijnen
223 Tag count Tagtelling
224 Tag label Markeringsetiket
225 Tag method Tag methode
226 Tag style Tag stijl
227 Target Doel
228 Target Json Model Doel Json Model
229 Target field Doelveld
230 Target json Doelgroep json
231 Target object Doelobject
232 Target title
233 Target type Doeltype
234 Task node Noeud intermédiaire
235 Template Sjabloon
236 Text Tekst
237 Time Tijd
238 Time spent Doorgebrachte tijd
239 Time spent (hours/days) bestede tijd (uren/dagen)
240 Time spent per status (hours) bestede tijd per status (uren)
241 Time spent per status per user (hours) bestede tijd per status per gebruiker (uren)
242 Title Titel
243 To Naar
244 Top menu Hoofdmenu
245 Total time per status Totale tijd per status
246 Track flow Spoorstroom
247 Track workflow Traceer de workflow
248 Tracking line Het volgen van lijn
249 Tracking lines Het volgen van lijnen
250 Transactional Transactioneel
251 Transition Overgang
252 Transitions Overgangen
253 Type Type
254 UI options
255 Update Update
256 User Gebruiker
257 Validation type Type validatie
258 Value Waarde
259 Value expr
260 View Bekijk
261 View generated Weergave gegenereerd
262 View params Bekijk params
263 Views Uitzicht
264 Widget Widget
265 Wkf Wkf
266 Wkf field Wkf veld
267 Wkf sequence
268 Wkf tracking Wkf het volgen
269 Wkf trackings Wkf rupsbanden
270 Wkf transition Wkf overgang
271 Workflow dashboard Workflow dashboard
272 Workflow is not saved Workflow wordt niet opgeslagen
273 Year Jaar
274 contains bevat
275 doesn't contains bevat niet
276 equal gelijk
277 greater or equal groter of gelijk
278 greater than groter dan
279 in naar binnen
280 include behelzen
281 is false vals is
282 is not null niet ongeldig is
283 is null is ongeldig
284 is true waar is
285 less or equal minder of gelijk
286 less than minder dan
287 not equal niet gelijk
288 not in niet in
289 not include niet omvatten
290 value:BPM waarde: BPM
291 value:Product App waarde: Product App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Tagi:</b> $user: Aktualny użytkownik, $date: Dzisiejsza data, $time: Czas bieżący.",,
"AND","ORAZ",,
"Action","Działanie",,
"Action builder","Kreator działań",,
"Action builders","Osoby budujące działania",,
"Actions","Działania",,
"Activate the hand tool","Aktywuj narzędzie ręczne",,
"Aggregate","Agregat",,
"Aggregate On","Aggregate On",,
"Aggregate On type","Agregat na typ",,
"Aggregate date type","Typ daty zbiorczej",,
"Alert","Alert",,
"Alert or Blocking condition","Stan alarmu lub blokady",,
"App builder","Konstruktor aplikacji",,
"App builders",,,
"App name",,,
"Append end node","Dodaj węzeł końcowy",,
"Append intermediate node","Dodaj węzeł pośredni",,
"Apply if",,,
"Area","Powierzchnia",,
"Assign value to","Przypisz wartość do",,
"BPM","BPM",,
"Background","Kontekst",,
"Bar","Bar",,
"Base model",,,
"Blocking","Blokowanie",,
"Boolean","luksemburski",,
"Bpmn xml","Bpmn xml",,
"Button","Przycisk",,
"Button title","Tytuł przycisku",,
"Can Collapse",,,
"Chart builder","Konstruktor wykresów",,
"Chart builders","Producenci wykresów",,
"Chart type","Typ wykresu",,
"ChartBuilder.Group","Grupa",,
"Choose App name",,,
"Code","Kod",,
"Collapse if",,,
"Colspan","Kolspan",,
"Condition","Warunek",,
"Conditions","Warunki",,
"Configuration",,,
"Connect using transition","Łączenie przy użyciu przejścia",,
"Context","Kontekst",,
"Create","Utworzyć",,
"Create end node","Utwórz węzeł końcowy",,
"Create intermediate node","Utwórz węzeł pośredni",,
"Create start node","Utwórz węzeł startowy",,
"Custom","Niestandardowe",,
"Custom Field","Pole niestandardowe",,
"Custom Model","Model niestandardowy",,
"Custom field","Pole niestandardowe",,
"Custom fields","Pola niestandardowe",,
"Custom model","Model niestandardowy",,
"Custom models","Modele niestandardowe",,
"Dashboard","Tablica rozdzielcza",,
"Dashboard builder","Konstruktor deski rozdzielczej",,
"Dashboard builders","Producenci desek rozdzielczych",,
"Dashlet builder","Konstruktor desek rozdzielczych",,
"Dashlet builder list","Lista konstruktorów kreski",,
"Dashlet builders","Producenci desek rozdzielczych",,
"Data file","Plik danych",,
"Date","Data",,
"Datetime","Okres przydatności do spożycia",,
"Day","Dzień",,
"Decimal","dziesiętny",,
"Default Value","Wartość domyślna",,
"Depends on","W zależności od",,
"Description","Opis",,
"Display","Wyświetlacz",,
"Display message","Wyświetlanie komunikatu",,
"Display type","Typ wyświetlacza",,
"Do you want to reset workflow ?",,,
"Domain","Dziedzina",,
"Donut","Pączek",,
"Dummy","Dumia",,
"Edit Node","Edytuj węzeł",,
"Edit Transition","Edycja Przejścia",,
"Edit before send","Edytuj przed wysłaniem",,
"Email","Poczta elektroniczna",,
"End node","Węzeł końcowy",,
"Existing menu","Istniejące menu",,
"Export","Eksportowanie",,
"Extra","Ekstra",,
"Field","Pole",,
"Field for 'My menu'","Pole Moje menu",,
"Field options",,,
"Fields","Pola",,
"Filter","Filtr",,
"Filters","Filtry",,
"First group by","Pierwsza grupa przez",,
"From","Od",,
"Funnel","Lejek",,
"Gauge","Manometr",,
"Generated Actions","Działania wygenerowane",,
"Generated app","Generowana aplikacja",,
"Groovy","Groovy",,
"Group By","Grupa Według",,
"Group date type","Typ daty grupy",,
"Group on type","Grupa na typie",,
"Groups","Grupy",,
"Help","Pomoc",,
"Hidden In Grid","Ukryte w siatce",,
"Hidden menu","Ukryte menu",,
"Horizontal bar","Listwa pozioma",,
"Icon","Ikona",,
"If","Jeżeli",,
"If-module","Moduł If",,
"Image","Obrazek",,
"Import","Przywóz",,
"Import BPM","Przywóz BPM",,
"Import log","Dziennik przywozowy",,
"Incoming","Incoming",,
"Integer","Integer",,
"Is Json Relational Field",,,
"Is json","Jest json",,
"Is parameter","Parametr jest parametrem",,
"Is wkf","Jest fajerwerkiem",,
"Javascript","JavaScript",,
"Json","Json",,
"Json Field","Pole Jsona",,
"Json Many To Many","Json wielu do wielu",,
"Json Many To One","Json Many To One",,
"Json One To Many","Json Jeden do wielu",,
"Left menu","Menu lewe",,
"Line","Linia",,
"Link","Łącze",,
"Logic operator","Operator logiczny",,
"Many To Many","Wiele do wielu",,
"Many To One","Wiele do jednego",,
"Max Size","Maksymalna wielkość",,
"Menu action","Akcja menu",,
"Menu builder","Konstruktor menu",,
"Menu builders","Konstruktorzy menu",,
"MenuBuilder.Order",,,
"Message","Wiadomość",,
"Message on alert or blocking","Komunikat w sprawie alarmu lub blokady",,
"Message on success","Przesłanie o sukcesie",,
"Meta Model","Model meta",,
"Meta module","Moduł Meta",,
"MetaMenu","MetaMenu",,
"Min Size","Rozmiar min.",,
"Mobile menu","Menu mobilne",,
"Model","Model",,
"Module","Moduł",,
"Month","Miesiąc",,
"Name","Nazwa",,
"Name Column",,,
"Name Field","Nazwa Nazwa Pole",,
"Name must not contains space","Nazwa nie może zawierać spacji",,
"Nav Select","Wybierz nawigację nawigację",,
"Nb of passes","Nb przepustek",,
"Nb of passes per status","Nb przepustek na status",,
"Node","Węzeł",,
"Node type",,,
"Nodes","Węzły",,
"None",,,
"OR","LUB",,
"Object","Obiekt",,
"On Change","W sprawie zmian",,
"On Click","Kliknij na Click",,
"On New","Na temat nowego",,
"On Save","świeci się Zapisz.",,
"One To Many","Jeden do wielu",,
"Only use this menu-item if the given expression is true.","Używaj tego menu-punktu menu tylko wtedy, gdy dane wyrażenie jest prawdziwe.",,
"Only use this menu-item if the given module is installed.","Z tego menu - punktu menu należy korzystać tylko wtedy, gdy dany moduł jest zainstalowany.",,
"Open record","Otwarty rekord",,
"Open workflow","Otwarty przepływ pracy",,
"Operator","Operator",,
"Outgoing","Wychodzący",,
"Overview","Przegląd",,
"Pagination limit","Granica numerowania stron",,
"Panel","Panel",,
"Parent","Rodzic",,
"Percentage(%)","Procent (%)",,
"Permissions","Pozwolenia",,
"Pie Chart","Wykres kołowy",,
"Please correct the workflow diagram.","Proszę skorygować diagram przepływu pracy.",,
"Please input value bind with single quotation.","Proszę wpisać wartość powiązaną z pojedynczym cudzysłowem.",,
"Please provide unique code. The code '%s' is already used","Proszę podać niepowtarzalny kod. Kod %s jest już stosowany",,
"Process",,,
"Process display type","Typ wyświetlania procesu",,
"Process studio","Studio procesowe",,
"Process tracking","Śledzenie procesu",,
"Properties","Właściwości",,
"Radar","radar",,
"ReadOnly for",,,
"Record Id","Numer rekordu",,
"Record model","Model rekordu",,
"Record name","Nazwa rekordu",,
"Regex","Regex",,
"Report","Sprawozdanie",,
"Reporting",,,
"Required","Wymagane",,
"Required If","Wymagane, jeżeli",,
"Roles","Role",,
"Scatter","Rozproszenie",,
"Script","Skrypt",,
"Script type","Typ skryptu",,
"Second group by","Druga grupa przez",,
"Select Option","Wybór opcji",,
"Selection","Wybór",,
"Selections",,,
"Send directly","Wyślij bezpośrednio",,
"Send option","Opcja wysyłania",,
"Separator","Separator",,
"Sequence","Kolejność",,
"Show If","Pokaż, jeśli",,
"Show Title",,,
"Show process tracking","Wyświetlanie śledzenia procesu",,
"Simple Select","Prosty wybór",,
"Source field","Źródło: Pole źródłowe",,
"Start node","Węzeł startowy",,
"Status","Status",,
"Status per day","Status na dzień",,
"Status per month","Status miesięcznie",,
"Status time(days)","Czas statusu (dni)",,
"Status time(hours)","Czas statusu (godziny)",,
"String","String",,
"Studio",,,
"Sub lines","Podlinie",,
"Tag count","Liczba znaczników",,
"Tag label","Etykieta znacznika",,
"Tag method","Metoda znacznikowa",,
"Tag style","Styl Tagów",,
"Target","Cel",,
"Target Json Model","Model Target Jsona",,
"Target field","Pole docelowe",,
"Target json","Cel json docelowy",,
"Target object","Obiekt docelowy",,
"Target title",,,
"Target type","Typ celu",,
"Task node",,,
"Template","Szablon",,
"Text","Tekst",,
"Time","Czas",,
"Time spent","Czas spędzony na pracy",,
"Time spent (hours/days)","Czas spędzony (godziny/dni)",,
"Time spent per status (hours)","Czas spędzony na statusie (godziny)",,
"Time spent per status per user (hours)","Czas spędzony na statusie na użytkownika (godziny)",,
"Title","Tytuł",,
"To","Do",,
"Top menu","Menu górne",,
"Total time per status","Łączny czas na status",,
"Track flow","Przepływ po torze",,
"Track workflow","Ścieżka przepływu pracy",,
"Tracking line","Linia monitorowania",,
"Tracking lines","Linie śledzące",,
"Transactional","Transakcyjny",,
"Transition","Przejście do nowego systemu",,
"Transitions","Transformacje",,
"Type","Typ",,
"UI options",,,
"Update","Aktualizacja",,
"User","Użytkownik",,
"Validation type","Typ walidacji",,
"Value","Wartość",,
"Value expr","Wyrażenie wartości",,
"View","Widok",,
"View generated","Wygenerowany widok",,
"View params","Przeglądaj paramy",,
"Views","Widoki",,
"Widget","Widżet",,
"Wkf","Wkf",,
"Wkf field","Pole fajerwerków",,
"Wkf sequence",,,
"Wkf tracking","Śledzenie chmur punktów na sekundę",,
"Wkf trackings","Śledzenie chmur punktów",,
"Wkf transition","Przejście na żakiety",,
"Workflow dashboard","Deska rozdzielcza przepływu pracy",,
"Workflow is not saved","Przepływ pracy nie jest zapisywany",,
"Year","Rok",,
"contains","zawiera",,
"doesn't contains","nie zawiera",,
"equal","jednakowy",,
"greater or equal","większy lub równy",,
"greater than","więcej niż",,
"in","na miejscu",,
"include","zawierać",,
"is false","jest nieprawdziwy",,
"is not null","nie jest nieważny",,
"is null","jest nieważny",,
"is true","jest prawdą",,
"less or equal","mniejsza lub równa",,
"less than","mniej niż",,
"not equal","nierówny",,
"not in","nie wewnątrz",,
"not include","nie obejmują",,
"value:BPM","wartość: BPM",,
"value:Product App","wartość: Produkt App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Tagi:</b> $user: Aktualny użytkownik, $date: Dzisiejsza data, $time: Czas bieżący.
3 AND ORAZ
4 Action Działanie
5 Action builder Kreator działań
6 Action builders Osoby budujące działania
7 Actions Działania
8 Activate the hand tool Aktywuj narzędzie ręczne
9 Aggregate Agregat
10 Aggregate On Aggregate On
11 Aggregate On type Agregat na typ
12 Aggregate date type Typ daty zbiorczej
13 Alert Alert
14 Alert or Blocking condition Stan alarmu lub blokady
15 App builder Konstruktor aplikacji
16 App builders
17 App name
18 Append end node Dodaj węzeł końcowy
19 Append intermediate node Dodaj węzeł pośredni
20 Apply if
21 Area Powierzchnia
22 Assign value to Przypisz wartość do
23 BPM BPM
24 Background Kontekst
25 Bar Bar
26 Base model
27 Blocking Blokowanie
28 Boolean luksemburski
29 Bpmn xml Bpmn xml
30 Button Przycisk
31 Button title Tytuł przycisku
32 Can Collapse
33 Chart builder Konstruktor wykresów
34 Chart builders Producenci wykresów
35 Chart type Typ wykresu
36 ChartBuilder.Group Grupa
37 Choose App name
38 Code Kod
39 Collapse if
40 Colspan Kolspan
41 Condition Warunek
42 Conditions Warunki
43 Configuration
44 Connect using transition Łączenie przy użyciu przejścia
45 Context Kontekst
46 Create Utworzyć
47 Create end node Utwórz węzeł końcowy
48 Create intermediate node Utwórz węzeł pośredni
49 Create start node Utwórz węzeł startowy
50 Custom Niestandardowe
51 Custom Field Pole niestandardowe
52 Custom Model Model niestandardowy
53 Custom field Pole niestandardowe
54 Custom fields Pola niestandardowe
55 Custom model Model niestandardowy
56 Custom models Modele niestandardowe
57 Dashboard Tablica rozdzielcza
58 Dashboard builder Konstruktor deski rozdzielczej
59 Dashboard builders Producenci desek rozdzielczych
60 Dashlet builder Konstruktor desek rozdzielczych
61 Dashlet builder list Lista konstruktorów kreski
62 Dashlet builders Producenci desek rozdzielczych
63 Data file Plik danych
64 Date Data
65 Datetime Okres przydatności do spożycia
66 Day Dzień
67 Decimal dziesiętny
68 Default Value Wartość domyślna
69 Depends on W zależności od
70 Description Opis
71 Display Wyświetlacz
72 Display message Wyświetlanie komunikatu
73 Display type Typ wyświetlacza
74 Do you want to reset workflow ?
75 Domain Dziedzina
76 Donut Pączek
77 Dummy Dumia
78 Edit Node Edytuj węzeł
79 Edit Transition Edycja Przejścia
80 Edit before send Edytuj przed wysłaniem
81 Email Poczta elektroniczna
82 End node Węzeł końcowy
83 Existing menu Istniejące menu
84 Export Eksportowanie
85 Extra Ekstra
86 Field Pole
87 Field for 'My menu' Pole Moje menu
88 Field options
89 Fields Pola
90 Filter Filtr
91 Filters Filtry
92 First group by Pierwsza grupa przez
93 From Od
94 Funnel Lejek
95 Gauge Manometr
96 Generated Actions Działania wygenerowane
97 Generated app Generowana aplikacja
98 Groovy Groovy
99 Group By Grupa Według
100 Group date type Typ daty grupy
101 Group on type Grupa na typie
102 Groups Grupy
103 Help Pomoc
104 Hidden In Grid Ukryte w siatce
105 Hidden menu Ukryte menu
106 Horizontal bar Listwa pozioma
107 Icon Ikona
108 If Jeżeli
109 If-module Moduł If
110 Image Obrazek
111 Import Przywóz
112 Import BPM Przywóz BPM
113 Import log Dziennik przywozowy
114 Incoming Incoming
115 Integer Integer
116 Is Json Relational Field
117 Is json Jest json
118 Is parameter Parametr jest parametrem
119 Is wkf Jest fajerwerkiem
120 Javascript JavaScript
121 Json Json
122 Json Field Pole Jsona
123 Json Many To Many Json wielu do wielu
124 Json Many To One Json Many To One
125 Json One To Many Json Jeden do wielu
126 Left menu Menu lewe
127 Line Linia
128 Link Łącze
129 Logic operator Operator logiczny
130 Many To Many Wiele do wielu
131 Many To One Wiele do jednego
132 Max Size Maksymalna wielkość
133 Menu action Akcja menu
134 Menu builder Konstruktor menu
135 Menu builders Konstruktorzy menu
136 MenuBuilder.Order
137 Message Wiadomość
138 Message on alert or blocking Komunikat w sprawie alarmu lub blokady
139 Message on success Przesłanie o sukcesie
140 Meta Model Model meta
141 Meta module Moduł Meta
142 MetaMenu MetaMenu
143 Min Size Rozmiar min.
144 Mobile menu Menu mobilne
145 Model Model
146 Module Moduł
147 Month Miesiąc
148 Name Nazwa
149 Name Column
150 Name Field Nazwa Nazwa Pole
151 Name must not contains space Nazwa nie może zawierać spacji
152 Nav Select Wybierz nawigację nawigację
153 Nb of passes Nb przepustek
154 Nb of passes per status Nb przepustek na status
155 Node Węzeł
156 Node type
157 Nodes Węzły
158 None
159 OR LUB
160 Object Obiekt
161 On Change W sprawie zmian
162 On Click Kliknij na Click
163 On New Na temat nowego
164 On Save świeci się Zapisz.
165 One To Many Jeden do wielu
166 Only use this menu-item if the given expression is true. Używaj tego menu-punktu menu tylko wtedy, gdy dane wyrażenie jest prawdziwe.
167 Only use this menu-item if the given module is installed. Z tego menu - punktu menu należy korzystać tylko wtedy, gdy dany moduł jest zainstalowany.
168 Open record Otwarty rekord
169 Open workflow Otwarty przepływ pracy
170 Operator Operator
171 Outgoing Wychodzący
172 Overview Przegląd
173 Pagination limit Granica numerowania stron
174 Panel Panel
175 Parent Rodzic
176 Percentage(%) Procent (%)
177 Permissions Pozwolenia
178 Pie Chart Wykres kołowy
179 Please correct the workflow diagram. Proszę skorygować diagram przepływu pracy.
180 Please input value bind with single quotation. Proszę wpisać wartość powiązaną z pojedynczym cudzysłowem.
181 Please provide unique code. The code '%s' is already used Proszę podać niepowtarzalny kod. Kod %s jest już stosowany
182 Process
183 Process display type Typ wyświetlania procesu
184 Process studio Studio procesowe
185 Process tracking Śledzenie procesu
186 Properties Właściwości
187 Radar radar
188 ReadOnly for
189 Record Id Numer rekordu
190 Record model Model rekordu
191 Record name Nazwa rekordu
192 Regex Regex
193 Report Sprawozdanie
194 Reporting
195 Required Wymagane
196 Required If Wymagane, jeżeli
197 Roles Role
198 Scatter Rozproszenie
199 Script Skrypt
200 Script type Typ skryptu
201 Second group by Druga grupa przez
202 Select Option Wybór opcji
203 Selection Wybór
204 Selections
205 Send directly Wyślij bezpośrednio
206 Send option Opcja wysyłania
207 Separator Separator
208 Sequence Kolejność
209 Show If Pokaż, jeśli
210 Show Title
211 Show process tracking Wyświetlanie śledzenia procesu
212 Simple Select Prosty wybór
213 Source field Źródło: Pole źródłowe
214 Start node Węzeł startowy
215 Status Status
216 Status per day Status na dzień
217 Status per month Status miesięcznie
218 Status time(days) Czas statusu (dni)
219 Status time(hours) Czas statusu (godziny)
220 String String
221 Studio
222 Sub lines Podlinie
223 Tag count Liczba znaczników
224 Tag label Etykieta znacznika
225 Tag method Metoda znacznikowa
226 Tag style Styl Tagów
227 Target Cel
228 Target Json Model Model Target Jsona
229 Target field Pole docelowe
230 Target json Cel json docelowy
231 Target object Obiekt docelowy
232 Target title
233 Target type Typ celu
234 Task node
235 Template Szablon
236 Text Tekst
237 Time Czas
238 Time spent Czas spędzony na pracy
239 Time spent (hours/days) Czas spędzony (godziny/dni)
240 Time spent per status (hours) Czas spędzony na statusie (godziny)
241 Time spent per status per user (hours) Czas spędzony na statusie na użytkownika (godziny)
242 Title Tytuł
243 To Do
244 Top menu Menu górne
245 Total time per status Łączny czas na status
246 Track flow Przepływ po torze
247 Track workflow Ścieżka przepływu pracy
248 Tracking line Linia monitorowania
249 Tracking lines Linie śledzące
250 Transactional Transakcyjny
251 Transition Przejście do nowego systemu
252 Transitions Transformacje
253 Type Typ
254 UI options
255 Update Aktualizacja
256 User Użytkownik
257 Validation type Typ walidacji
258 Value Wartość
259 Value expr Wyrażenie wartości
260 View Widok
261 View generated Wygenerowany widok
262 View params Przeglądaj paramy
263 Views Widoki
264 Widget Widżet
265 Wkf Wkf
266 Wkf field Pole fajerwerków
267 Wkf sequence
268 Wkf tracking Śledzenie chmur punktów na sekundę
269 Wkf trackings Śledzenie chmur punktów
270 Wkf transition Przejście na żakiety
271 Workflow dashboard Deska rozdzielcza przepływu pracy
272 Workflow is not saved Przepływ pracy nie jest zapisywany
273 Year Rok
274 contains zawiera
275 doesn't contains nie zawiera
276 equal jednakowy
277 greater or equal większy lub równy
278 greater than więcej niż
279 in na miejscu
280 include zawierać
281 is false jest nieprawdziwy
282 is not null nie jest nieważny
283 is null jest nieważny
284 is true jest prawdą
285 less or equal mniejsza lub równa
286 less than mniej niż
287 not equal nierówny
288 not in nie wewnątrz
289 not include nie obejmują
290 value:BPM wartość: BPM
291 value:Product App wartość: Produkt App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","B>Tags:<b>Tags:</b> $user: Usuário atual, $date: Data de hoje, $time: Hora atual.",,
"AND","E",,
"Action","Ação",,
"Action builder","Construtor de ações",,
"Action builders","Construtores de acções",,
"Actions","Ações",,
"Activate the hand tool","Ativar a ferramenta manual",,
"Aggregate","Agregado",,
"Aggregate On","Agregar em",,
"Aggregate On type","Agregar no tipo",,
"Aggregate date type","Tipo de data agregada",,
"Alert","Alerta",,
"Alert or Blocking condition","Alerta ou condição de bloqueio",,
"App builder","Construtor de aplicações",,
"App builders",,,
"App name",,,
"Append end node","Anexar nó final",,
"Append intermediate node","Anexar nó intermediário",,
"Apply if",,,
"Area","Área",,
"Assign value to","Atribuir valor a",,
"BPM","BPM",,
"Background","Antecedentes",,
"Bar","Bar",,
"Base model",,,
"Blocking","Bloqueio",,
"Boolean","booleano",,
"Bpmn xml","Bpmn xml",,
"Button","Botão",,
"Button title","Título do botão",,
"Can Collapse",,,
"Chart builder","Construtor de gráficos",,
"Chart builders","Construtores de gráficos",,
"Chart type","Tipo de gráfico",,
"ChartBuilder.Group","Grupo (Grupo)",,
"Choose App name",,,
"Code","Código",,
"Collapse if",,,
"Colspan","Colspan",,
"Condition","Condição",,
"Conditions","Condições de utilização",,
"Configuration",,,
"Connect using transition","Conectar-se usando a transição",,
"Context","Contexto",,
"Create","Criar",,
"Create end node","Criar nó final",,
"Create intermediate node","Criar nó intermediário",,
"Create start node","Criar nó inicial",,
"Custom","Personalizado",,
"Custom Field","Campo personalizado",,
"Custom Model","Modelo Personalizado",,
"Custom field","Campo personalizado",,
"Custom fields","Campos personalizados",,
"Custom model","Modelo personalizado",,
"Custom models","Modelos personalizados",,
"Dashboard","Painel de instrumentos",,
"Dashboard builder","Construtor de painéis de instrumentos",,
"Dashboard builders","Construtores de painéis de instrumentos",,
"Dashlet builder","Construtor de Dashlet",,
"Dashlet builder list","Lista de construtores de Dashlet",,
"Dashlet builders","Construtores de Dashlet",,
"Data file","Arquivo de dados",,
"Date","Data",,
"Datetime","Data/hora",,
"Day","Dia da semana",,
"Decimal","Decimal",,
"Default Value","Valor proposto",,
"Depends on","Depende de",,
"Description","Descrição do produto",,
"Display","Exibição",,
"Display message","Exibir mensagem",,
"Display type","Tipo de exibição",,
"Do you want to reset workflow ?",,,
"Domain","Domínios",,
"Donut","Donut",,
"Dummy","Dummy",,
"Edit Node","Editar nó",,
"Edit Transition","Editar Transição",,
"Edit before send","Editar antes de enviar",,
"Email","Email",,
"End node","Nó final",,
"Existing menu","Menu Existente",,
"Export","Exportação",,
"Extra","Extra",,
"Field","Campo",,
"Field for 'My menu'","Campo para 'Meu menu",,
"Field options",,,
"Fields","Campos",,
"Filter","Filtro",,
"Filters","Filtros",,
"First group by","Primeiro grupo por",,
"From","De",,
"Funnel","Funil",,
"Gauge","Bitola",,
"Generated Actions","Ações geradas",,
"Generated app","Aplicativo gerado",,
"Groovy","Groovy",,
"Group By","Agrupar por",,
"Group date type","Tipo de data de grupo",,
"Group on type","Grupo por tipo",,
"Groups","Grupos",,
"Help","Ajudar",,
"Hidden In Grid","Escondido na Grelha",,
"Hidden menu","Menu oculto",,
"Horizontal bar","Barra horizontal",,
"Icon","Ícone",,
"If","Se",,
"If-module","Se-módulo",,
"Image","Imagem",,
"Import","Importação",,
"Import BPM","Importar BPM",,
"Import log","Log de importação",,
"Incoming","Incoming",,
"Integer","Inteiro",,
"Is Json Relational Field",,,
"Is json","É o Json.",,
"Is parameter","É parâmetro",,
"Is wkf","É wkf",,
"Javascript","Javascript",,
"Json","Json",,
"Json Field","Campo de Json",,
"Json Many To Many","Json Muitos para muitos",,
"Json Many To One","Json Muitos para um",,
"Json One To Many","Json um para muitos",,
"Left menu","Menu esquerdo",,
"Line","Linha",,
"Link","Link",,
"Logic operator","Operador lógico",,
"Many To Many","Muitos para muitos",,
"Many To One","Muitos para um",,
"Max Size","Tamanho máximo",,
"Menu action","Ação do menu",,
"Menu builder","Construtor de menus",,
"Menu builders","Construtores de menus",,
"MenuBuilder.Order","Ordem",,
"Message","Mensagem",,
"Message on alert or blocking","Mensagem em alerta ou bloqueio",,
"Message on success","Mensagem sobre o sucesso",,
"Meta Model","Meta Modelo",,
"Meta module","Meta módulo",,
"MetaMenu","MetaMenu",,
"Min Size","Tamanho Mínimo",,
"Mobile menu","Menu móvel",,
"Model","Modelo",,
"Module","Módulo",,
"Month","Mês",,
"Name","Nome e Sobrenome",,
"Name Column",,,
"Name Field","Nome Campo",,
"Name must not contains space","O nome não deve conter espaço",,
"Nav Select","Selecção do Nav",,
"Nb of passes","Nb de passagens",,
"Nb of passes per status","Nb de passes por status",,
"Node","",,
"Node type","Type de nœud",,
"Nodes","Nós",,
"None",,,
"OR","OU",,
"Object","Objeto",,
"On Change","Em Mudança",,
"On Click","Clicar em",,
"On New","Em Novo",,
"On Save","Em Salvar",,
"One To Many","De um para muitos",,
"Only use this menu-item if the given expression is true.","Só use este item de menu se a expressão dada for verdadeira.",,
"Only use this menu-item if the given module is installed.","Utilize este menu apenas se o módulo em questão estiver instalado.",,
"Open record","Abrir registro",,
"Open workflow","Fluxo de trabalho aberto",,
"Operator","Operador",,
"Outgoing","Saída",,
"Overview","Visão Geral",,
"Pagination limit","Limite de Paginação",,
"Panel","Painel",,
"Parent","Pais",,
"Percentage(%)","Porcentagem (%)",,
"Permissions","Permissões",,
"Pie Chart","Gráfico de Pizza",,
"Please correct the workflow diagram.","Por favor, corrija o diagrama de fluxo de trabalho.",,
"Please input value bind with single quotation.","Por favor, introduza um valor de encadernação com uma única cotação.",,
"Please provide unique code. The code '%s' is already used","Por favor, forneça um código único. O código %s já é utilizado",,
"Process",,,
"Process display type","Tipo de exibição do processo",,
"Process studio","Estúdio de processo",,
"Process tracking","Acompanhamento do processo",,
"Properties","Imóveis",,
"Radar","Radar",,
"ReadOnly for","Lecture seule pour",,
"Record Id","Registrar Id",,
"Record model","Modelo de registro",,
"Record name","Nome do registro",,
"Regex","Regex",,
"Report","Relatório",,
"Reporting",,,
"Required","Necessário",,
"Required If","Necessário se",,
"Roles","Funções",,
"Scatter","Dispersão",,
"Script","Roteiro",,
"Script type","Tipo de script",,
"Second group by","Segundo grupo por",,
"Select Option","Selecione Opção",,
"Selection","Selecção",,
"Selections",,,
"Send directly","Enviar diretamente",,
"Send option","Enviar opção",,
"Separator","Separador",,
"Sequence","Seqüência",,
"Show If","Mostrar se",,
"Show Title",,,
"Show process tracking","Mostrar acompanhamento do processo",,
"Simple Select","Seleção simples",,
"Source field","Campo de origem",,
"Start node","Nó inicial",,
"Status","Estado",,
"Status per day","Status por dia",,
"Status per month","Status por mês",,
"Status time(days)","Tempo de status (dias)",,
"Status time(hours)","Tempo de status (horas)",,
"String","Corda",,
"Studio",,,
"Sub lines","Sub-linhas",,
"Tag count","Contagem de tags",,
"Tag label","Etiqueta de etiqueta",,
"Tag method","Método Tag",,
"Tag style","Estilo de etiqueta",,
"Target","Alvo",,
"Target Json Model","Modelo Target Json",,
"Target field","Campo de destino",,
"Target json","Alvo json",,
"Target object","Objeto de destino",,
"Target title",,,
"Target type","Tipo de destino",,
"Task node","Noeud intermédiaire",,
"Template","Modelo",,
"Text","Texto",,
"Time","Tempo",,
"Time spent","Tempo gasto",,
"Time spent (hours/days)","Tempo gasto (horas/dia)",,
"Time spent per status (hours)","Tempo gasto por status (horas)",,
"Time spent per status per user (hours)","Tempo gasto por status por usuário (horas)",,
"Title","Título",,
"To","Para",,
"Top menu","Menu superior",,
"Total time per status","Tempo total por status",,
"Track flow","Fluxo da via",,
"Track workflow","Acompanhe o fluxo de trabalho",,
"Tracking line","Linha de rastreamento",,
"Tracking lines","Linhas de rastreamento",,
"Transactional","Transaccional",,
"Transition","Transição",,
"Transitions","Transições",,
"Type","Tipo de",,
"UI options",,,
"Update","Atualização",,
"User","Usuário",,
"Validation type","Tipo de validação",,
"Value","Valor",,
"Value expr","Valor Expr",,
"View","Ver",,
"View generated","Visualização gerada",,
"View params","Ver parâmetros",,
"Views","Vistas",,
"Widget","Widget",,
"Wkf","Wkf",,
"Wkf field","Campo Wkf",,
"Wkf sequence",,,
"Wkf tracking","Tracking Wkf",,
"Wkf trackings","Rastreamentos Wkf",,
"Wkf transition","Transição de Wkf",,
"Workflow dashboard","Painel de fluxo de trabalho",,
"Workflow is not saved","Workflow não é gravado",,
"Year","Ano",,
"contains","contém",,
"doesn't contains","não contém",,
"equal","igualitária",,
"greater or equal","maior ou igual",,
"greater than","superior a",,
"in","em",,
"include","incluir",,
"is false","é falso",,
"is not null","não é nulo",,
"is null","é nulo",,
"is true","é verdade",,
"less or equal","menor ou igual",,
"less than","inferior a",,
"not equal","não igual",,
"not in","não em",,
"not include","não incluir",,
"value:BPM","valor:BPM",,
"value:Product App","value:Produto App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time B>Tags:<b>Tags:</b> $user: Usuário atual, $date: Data de hoje, $time: Hora atual.
3 AND E
4 Action Ação
5 Action builder Construtor de ações
6 Action builders Construtores de acções
7 Actions Ações
8 Activate the hand tool Ativar a ferramenta manual
9 Aggregate Agregado
10 Aggregate On Agregar em
11 Aggregate On type Agregar no tipo
12 Aggregate date type Tipo de data agregada
13 Alert Alerta
14 Alert or Blocking condition Alerta ou condição de bloqueio
15 App builder Construtor de aplicações
16 App builders
17 App name
18 Append end node Anexar nó final
19 Append intermediate node Anexar nó intermediário
20 Apply if
21 Area Área
22 Assign value to Atribuir valor a
23 BPM BPM
24 Background Antecedentes
25 Bar Bar
26 Base model
27 Blocking Bloqueio
28 Boolean booleano
29 Bpmn xml Bpmn xml
30 Button Botão
31 Button title Título do botão
32 Can Collapse
33 Chart builder Construtor de gráficos
34 Chart builders Construtores de gráficos
35 Chart type Tipo de gráfico
36 ChartBuilder.Group Grupo (Grupo)
37 Choose App name
38 Code Código
39 Collapse if
40 Colspan Colspan
41 Condition Condição
42 Conditions Condições de utilização
43 Configuration
44 Connect using transition Conectar-se usando a transição
45 Context Contexto
46 Create Criar
47 Create end node Criar nó final
48 Create intermediate node Criar nó intermediário
49 Create start node Criar nó inicial
50 Custom Personalizado
51 Custom Field Campo personalizado
52 Custom Model Modelo Personalizado
53 Custom field Campo personalizado
54 Custom fields Campos personalizados
55 Custom model Modelo personalizado
56 Custom models Modelos personalizados
57 Dashboard Painel de instrumentos
58 Dashboard builder Construtor de painéis de instrumentos
59 Dashboard builders Construtores de painéis de instrumentos
60 Dashlet builder Construtor de Dashlet
61 Dashlet builder list Lista de construtores de Dashlet
62 Dashlet builders Construtores de Dashlet
63 Data file Arquivo de dados
64 Date Data
65 Datetime Data/hora
66 Day Dia da semana
67 Decimal Decimal
68 Default Value Valor proposto
69 Depends on Depende de
70 Description Descrição do produto
71 Display Exibição
72 Display message Exibir mensagem
73 Display type Tipo de exibição
74 Do you want to reset workflow ?
75 Domain Domínios
76 Donut Donut
77 Dummy Dummy
78 Edit Node Editar nó
79 Edit Transition Editar Transição
80 Edit before send Editar antes de enviar
81 Email Email
82 End node Nó final
83 Existing menu Menu Existente
84 Export Exportação
85 Extra Extra
86 Field Campo
87 Field for 'My menu' Campo para 'Meu menu
88 Field options
89 Fields Campos
90 Filter Filtro
91 Filters Filtros
92 First group by Primeiro grupo por
93 From De
94 Funnel Funil
95 Gauge Bitola
96 Generated Actions Ações geradas
97 Generated app Aplicativo gerado
98 Groovy Groovy
99 Group By Agrupar por
100 Group date type Tipo de data de grupo
101 Group on type Grupo por tipo
102 Groups Grupos
103 Help Ajudar
104 Hidden In Grid Escondido na Grelha
105 Hidden menu Menu oculto
106 Horizontal bar Barra horizontal
107 Icon Ícone
108 If Se
109 If-module Se-módulo
110 Image Imagem
111 Import Importação
112 Import BPM Importar BPM
113 Import log Log de importação
114 Incoming Incoming
115 Integer Inteiro
116 Is Json Relational Field
117 Is json É o Json.
118 Is parameter É parâmetro
119 Is wkf É wkf
120 Javascript Javascript
121 Json Json
122 Json Field Campo de Json
123 Json Many To Many Json Muitos para muitos
124 Json Many To One Json Muitos para um
125 Json One To Many Json um para muitos
126 Left menu Menu esquerdo
127 Line Linha
128 Link Link
129 Logic operator Operador lógico
130 Many To Many Muitos para muitos
131 Many To One Muitos para um
132 Max Size Tamanho máximo
133 Menu action Ação do menu
134 Menu builder Construtor de menus
135 Menu builders Construtores de menus
136 MenuBuilder.Order Ordem
137 Message Mensagem
138 Message on alert or blocking Mensagem em alerta ou bloqueio
139 Message on success Mensagem sobre o sucesso
140 Meta Model Meta Modelo
141 Meta module Meta módulo
142 MetaMenu MetaMenu
143 Min Size Tamanho Mínimo
144 Mobile menu Menu móvel
145 Model Modelo
146 Module Módulo
147 Month Mês
148 Name Nome e Sobrenome
149 Name Column
150 Name Field Nome Campo
151 Name must not contains space O nome não deve conter espaço
152 Nav Select Selecção do Nav
153 Nb of passes Nb de passagens
154 Nb of passes per status Nb de passes por status
155 Node
156 Node type Type de nœud
157 Nodes Nós
158 None
159 OR OU
160 Object Objeto
161 On Change Em Mudança
162 On Click Clicar em
163 On New Em Novo
164 On Save Em Salvar
165 One To Many De um para muitos
166 Only use this menu-item if the given expression is true. Só use este item de menu se a expressão dada for verdadeira.
167 Only use this menu-item if the given module is installed. Utilize este menu apenas se o módulo em questão estiver instalado.
168 Open record Abrir registro
169 Open workflow Fluxo de trabalho aberto
170 Operator Operador
171 Outgoing Saída
172 Overview Visão Geral
173 Pagination limit Limite de Paginação
174 Panel Painel
175 Parent Pais
176 Percentage(%) Porcentagem (%)
177 Permissions Permissões
178 Pie Chart Gráfico de Pizza
179 Please correct the workflow diagram. Por favor, corrija o diagrama de fluxo de trabalho.
180 Please input value bind with single quotation. Por favor, introduza um valor de encadernação com uma única cotação.
181 Please provide unique code. The code '%s' is already used Por favor, forneça um código único. O código %s já é utilizado
182 Process
183 Process display type Tipo de exibição do processo
184 Process studio Estúdio de processo
185 Process tracking Acompanhamento do processo
186 Properties Imóveis
187 Radar Radar
188 ReadOnly for Lecture seule pour
189 Record Id Registrar Id
190 Record model Modelo de registro
191 Record name Nome do registro
192 Regex Regex
193 Report Relatório
194 Reporting
195 Required Necessário
196 Required If Necessário se
197 Roles Funções
198 Scatter Dispersão
199 Script Roteiro
200 Script type Tipo de script
201 Second group by Segundo grupo por
202 Select Option Selecione Opção
203 Selection Selecção
204 Selections
205 Send directly Enviar diretamente
206 Send option Enviar opção
207 Separator Separador
208 Sequence Seqüência
209 Show If Mostrar se
210 Show Title
211 Show process tracking Mostrar acompanhamento do processo
212 Simple Select Seleção simples
213 Source field Campo de origem
214 Start node Nó inicial
215 Status Estado
216 Status per day Status por dia
217 Status per month Status por mês
218 Status time(days) Tempo de status (dias)
219 Status time(hours) Tempo de status (horas)
220 String Corda
221 Studio
222 Sub lines Sub-linhas
223 Tag count Contagem de tags
224 Tag label Etiqueta de etiqueta
225 Tag method Método Tag
226 Tag style Estilo de etiqueta
227 Target Alvo
228 Target Json Model Modelo Target Json
229 Target field Campo de destino
230 Target json Alvo json
231 Target object Objeto de destino
232 Target title
233 Target type Tipo de destino
234 Task node Noeud intermédiaire
235 Template Modelo
236 Text Texto
237 Time Tempo
238 Time spent Tempo gasto
239 Time spent (hours/days) Tempo gasto (horas/dia)
240 Time spent per status (hours) Tempo gasto por status (horas)
241 Time spent per status per user (hours) Tempo gasto por status por usuário (horas)
242 Title Título
243 To Para
244 Top menu Menu superior
245 Total time per status Tempo total por status
246 Track flow Fluxo da via
247 Track workflow Acompanhe o fluxo de trabalho
248 Tracking line Linha de rastreamento
249 Tracking lines Linhas de rastreamento
250 Transactional Transaccional
251 Transition Transição
252 Transitions Transições
253 Type Tipo de
254 UI options
255 Update Atualização
256 User Usuário
257 Validation type Tipo de validação
258 Value Valor
259 Value expr Valor Expr
260 View Ver
261 View generated Visualização gerada
262 View params Ver parâmetros
263 Views Vistas
264 Widget Widget
265 Wkf Wkf
266 Wkf field Campo Wkf
267 Wkf sequence
268 Wkf tracking Tracking Wkf
269 Wkf trackings Rastreamentos Wkf
270 Wkf transition Transição de Wkf
271 Workflow dashboard Painel de fluxo de trabalho
272 Workflow is not saved Workflow não é gravado
273 Year Ano
274 contains contém
275 doesn't contains não contém
276 equal igualitária
277 greater or equal maior ou igual
278 greater than superior a
279 in em
280 include incluir
281 is false é falso
282 is not null não é nulo
283 is null é nulo
284 is true é verdade
285 less or equal menor ou igual
286 less than inferior a
287 not equal não igual
288 not in não em
289 not include não incluir
290 value:BPM valor:BPM
291 value:Product App value:Produto App
292 xmlId xmlId

View File

@ -0,0 +1,292 @@
"key","message","comment","context"
"<b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time","<b>Тэги:</b>Пользователь. Текущий пользователь, $date: Текущая дата, $time: Текущее время",,
"AND","И",,
"Action","Действие",,
"Action builder","Строитель боев",,
"Action builders","Строители боев",,
"Actions","Действия",,
"Activate the hand tool","Активировать ручной инструмент",,
"Aggregate","Совокупность",,
"Aggregate On","Агрегировать Вкл.",,
"Aggregate On type","Агрегировать по типу Вкл.",,
"Aggregate date type","Тип агрегированной даты",,
"Alert","Тревога",,
"Alert or Blocking condition","Предупреждение или состояние блокировки",,
"App builder","Создатель приложений",,
"App builders",,,
"App name",,,
"Append end node","Добавить конечный узел",,
"Append intermediate node","Добавить промежуточный узел",,
"Apply if",,,
"Area","Площадь",,
"Assign value to","Присвоить значение",,
"BPM","BPM",,
"Background","Предыстория",,
"Bar","Бар",,
"Base model",,,
"Blocking","Блокировка",,
"Boolean","булев",,
"Bpmn xml","Bpmn xml",,
"Button","Кнопка",,
"Button title","Название кнопки",,
"Can Collapse",,,
"Chart builder","Создатель диаграмм",,
"Chart builders","Составители карт",,
"Chart type","Тип графика",,
"ChartBuilder.Group","Группа",,
"Choose App name",,,
"Code","Код",,
"Collapse if",,,
"Colspan","Колспан",,
"Condition","Условие",,
"Conditions","Условия",,
"Configuration",,,
"Connect using transition","Подключение с помощью перехода",,
"Context","Контекст",,
"Create","Создать",,
"Create end node","Создать конечный узел",,
"Create intermediate node","Создать промежуточный узел",,
"Create start node","Создать стартовый узел",,
"Custom","Пользовательский",,
"Custom Field","Настраиваемое поле",,
"Custom Model","Пользовательская модель",,
"Custom field","Настраиваемое поле",,
"Custom fields","Дополнительные поля",,
"Custom model","Индивидуальная модель",,
"Custom models","Индивидуальные модели",,
"Dashboard","Приборная панель",,
"Dashboard builder","Изготовитель приборной панели",,
"Dashboard builders","Производители приборных панелей",,
"Dashlet builder","Изготовитель приборных панелей",,
"Dashlet builder list","Список разработчиков черточек",,
"Dashlet builders","Производители приборов Dashlet",,
"Data file","Файл данных",,
"Date","Дата",,
"Datetime","Дата",,
"Day","День",,
"Decimal","Десятичная дробь",,
"Default Value","Значение по умолчанию",,
"Depends on","Зависит от",,
"Description","Описание",,
"Display","дисплей",,
"Display message","Отобразить сообщение",,
"Display type","Тип дисплея",,
"Do you want to reset workflow ?",,,
"Domain","Домен",,
"Donut","пончик",,
"Dummy","Кукла",,
"Edit Node","Редактировать узел",,
"Edit Transition","Редактирование перехода",,
"Edit before send","Изменить перед отправкой",,
"Email","Электронная почта",,
"End node","Конечный узел",,
"Existing menu","Существующее меню",,
"Export","Экспорт",,
"Extra","Дополнительная информация",,
"Field","Поле",,
"Field for 'My menu'","Поле для Мое меню.",,
"Field options",,,
"Fields","Поля",,
"Filter","Фильтр",,
"Filters","Фильтры",,
"First group by","Первая группа по",,
"From","От",,
"Funnel","Воронка",,
"Gauge","Измеритель",,
"Generated Actions","Сгенерированные действия",,
"Generated app","Созданное приложение",,
"Groovy","Клёвый",,
"Group By","Сгруппировать по",,
"Group date type","Тип даты группы",,
"Group on type","Группа по типу",,
"Groups","Группы",,
"Help","Помощь",,
"Hidden In Grid","Скрытые в сети",,
"Hidden menu","Скрытое меню",,
"Horizontal bar","Горизонтальная полоса",,
"Icon","Икона",,
"If","Если",,
"If-module","Если-модуль",,
"Image","Изображение",,
"Import","Импорт",,
"Import BPM","Импорт BPM",,
"Import log","Импорт журнала",,
"Incoming","Прибыль",,
"Integer","Целостный",,
"Is Json Relational Field",,,
"Is json","Джсон",,
"Is parameter","Есть параметр",,
"Is wkf","Wkf",,
"Javascript","Javascript",,
"Json","Джсон",,
"Json Field","Джсон Филд",,
"Json Many To Many","Json Many To many To many",,
"Json Many To One","Json Many To One",,
"Json One To Many","Json One To many",,
"Left menu","Левое меню",,
"Line","Линия",,
"Link","Связь",,
"Logic operator","Логический оператор",,
"Many To Many","Много-много-многом",,
"Many To One","Многие к одному",,
"Max Size","Максимальный размер",,
"Menu action","Действие меню",,
"Menu builder","Создатель меню",,
"Menu builders","Создатели меню",,
"MenuBuilder.Order","поря́док",,
"Message","Сообщение",,
"Message on alert or blocking","Сообщение о тревоге или блокировке",,
"Message on success","Сообщение об успехе",,
"Meta Model","Мета модель",,
"Meta module","Мета-модуль",,
"MetaMenu","Мета-меню",,
"Min Size","Мин Размер",,
"Mobile menu","Мобильное меню",,
"Model","Модель",,
"Module","Модуль",,
"Month","Месяц",,
"Name","Имя",,
"Name Column",,,
"Name Field","Поле имени",,
"Name must not contains space","Имя не должно содержать пробелов.",,
"Nav Select","Навигация Выбрать",,
"Nb of passes","Nb пропусков",,
"Nb of passes per status","Nb пропусков на статус",,
"Node","Узел",,
"Node type",,,
"Nodes","Узлы",,
"None",,,
"OR","ИЛИ",,
"Object","Объект",,
"On Change","О Изменениях",,
"On Click","Нажать кнопку",,
"On New","На Новом",,
"On Save","На Сохранить",,
"One To Many","Один ко многим",,
"Only use this menu-item if the given expression is true.","Используйте этот пункт меню только в том случае, если данное выражение соответствует истине.",,
"Only use this menu-item if the given module is installed.","Данный пункт меню используется только в том случае, если данный модуль установлен.",,
"Open record","Открытая запись",,
"Open workflow","Открытый документооборот",,
"Operator","Оператор",,
"Outgoing","Отбывающий",,
"Overview","Обзор",,
"Pagination limit","Ограничение по количеству страниц",,
"Panel","Панель",,
"Parent","Родитель",,
"Percentage(%)","Процент(%)",,
"Permissions","Разрешения",,
"Pie Chart","Круговая диаграмма",,
"Please correct the workflow diagram.","Пожалуйста, исправьте схему рабочего процесса.",,
"Please input value bind with single quotation.","Пожалуйста, свяжите вводимое значение с одной кавычкой.",,
"Please provide unique code. The code '%s' is already used","Пожалуйста, предоставьте уникальный код. Код '%s' уже используется.",,
"Process",,,
"Process display type","Тип отображения процесса",,
"Process studio","Студия процессов",,
"Process tracking","Отслеживание процесса",,
"Properties","Свойства",,
"Radar","Радар",,
"ReadOnly for",,,
"Record Id","Ид записи",,
"Record model","Модель записи",,
"Record name","Имя записи",,
"Regex","Регекс",,
"Report","Доклад",,
"Reporting",,,
"Required","Требуется",,
"Required If","Требуется Если",,
"Roles","Роли",,
"Scatter","Рассеивание",,
"Script","Сценарий",,
"Script type","Тип сценария",,
"Second group by","Вторая группа по",,
"Select Option","Выберите Параметр",,
"Selection","Выбор",,
"Selections",,,
"Send directly","Отправить непосредственно",,
"Send option","Отправить вариант",,
"Separator","Сепаратор",,
"Sequence","Последовательность",,
"Show If","Показать Если",,
"Show Title",,,
"Show process tracking","Показать отслеживание процесса",,
"Simple Select","Простой выбор",,
"Source field","Исходное поле",,
"Start node","Запустить узел",,
"Status","Статус",,
"Status per day","Статус в день",,
"Status per month","Статус в месяц",,
"Status time(days)","Время статуса (дни)",,
"Status time(hours)","Время статуса (часы)",,
"String","Стринг",,
"Studio",,,
"Sub lines","Подлинии",,
"Tag count","Количество меток",,
"Tag label","Метка",,
"Tag method","Метод тегов",,
"Tag style","Стиль тегов",,
"Target","Цель",,
"Target Json Model","Цель - Джсон Модель.",,
"Target field","Целевое поле",,
"Target json","Цель - Джсон.",,
"Target object","Объект съемки",,
"Target title",,,
"Target type","Тип цели",,
"Task node",,,
"Template","Шаблон",,
"Text","Текст",,
"Time","Время",,
"Time spent","Время, проведённое",,
"Time spent (hours/days)","Время, затраченное (часы/дни)",,
"Time spent per status (hours)","Время, потраченное на статус (в часах)",,
"Time spent per status per user (hours)","Время, потраченное на статус одного пользователя (в часах)",,
"Title","Название",,
"To","К",,
"Top menu","Верхнее меню",,
"Total time per status","Общее время по статусу",,
"Track flow","Гусеничный поток",,
"Track workflow","Отслеживание рабочего процесса",,
"Tracking line","Линия слежения",,
"Tracking lines","Линии слежения",,
"Transactional","Транзакционный",,
"Transition","Переход",,
"Transitions","Переходы",,
"Type","Тип",,
"UI options",,,
"Update","Обновить",,
"User","Пользователь",,
"Validation type","Тип валидации",,
"Value","Значение",,
"Value expr","Значение Expr",,
"View","Просмотр",,
"View generated","Сгенерированный вид",,
"View params","Просмотреть параметры",,
"Views","Виды",,
"Widget","Виджет",,
"Wkf","Wkf",,
"Wkf field","поле Wkf",,
"Wkf sequence",,,
"Wkf tracking","Отслеживание Wkf",,
"Wkf trackings","Отслеживание Wkf",,
"Wkf transition","переход Wkf",,
"Workflow dashboard","Приборная панель управления рабочим процессом",,
"Workflow is not saved","Процесс работы не сохраняется",,
"Year","Год",,
"contains","содержит",,
"doesn't contains","не содержит",,
"equal","равноценный",,
"greater or equal","больше или равны",,
"greater than","нечто большее",,
"in","в пределах",,
"include","включать",,
"is false","это ложь",,
"is not null","не является нулевым",,
"is null","равняется нулю",,
"is true","это правда",,
"less or equal","менее или равный",,
"less than","не особо",,
"not equal","не равный",,
"not in","не в",,
"not include","не включает",,
"value:BPM","ценность:BPM",,
"value:Product App","ценность:Продукт App",,
"xmlId","xmlId",,
1 key message comment context
2 <b>Tags:</b> $user: Current user, $date: Today's date, $time: Current time <b>Тэги:</b>Пользователь. Текущий пользователь, $date: Текущая дата, $time: Текущее время
3 AND И
4 Action Действие
5 Action builder Строитель боев
6 Action builders Строители боев
7 Actions Действия
8 Activate the hand tool Активировать ручной инструмент
9 Aggregate Совокупность
10 Aggregate On Агрегировать Вкл.
11 Aggregate On type Агрегировать по типу Вкл.
12 Aggregate date type Тип агрегированной даты
13 Alert Тревога
14 Alert or Blocking condition Предупреждение или состояние блокировки
15 App builder Создатель приложений
16 App builders
17 App name
18 Append end node Добавить конечный узел
19 Append intermediate node Добавить промежуточный узел
20 Apply if
21 Area Площадь
22 Assign value to Присвоить значение
23 BPM BPM
24 Background Предыстория
25 Bar Бар
26 Base model
27 Blocking Блокировка
28 Boolean булев
29 Bpmn xml Bpmn xml
30 Button Кнопка
31 Button title Название кнопки
32 Can Collapse
33 Chart builder Создатель диаграмм
34 Chart builders Составители карт
35 Chart type Тип графика
36 ChartBuilder.Group Группа
37 Choose App name
38 Code Код
39 Collapse if
40 Colspan Колспан
41 Condition Условие
42 Conditions Условия
43 Configuration
44 Connect using transition Подключение с помощью перехода
45 Context Контекст
46 Create Создать
47 Create end node Создать конечный узел
48 Create intermediate node Создать промежуточный узел
49 Create start node Создать стартовый узел
50 Custom Пользовательский
51 Custom Field Настраиваемое поле
52 Custom Model Пользовательская модель
53 Custom field Настраиваемое поле
54 Custom fields Дополнительные поля
55 Custom model Индивидуальная модель
56 Custom models Индивидуальные модели
57 Dashboard Приборная панель
58 Dashboard builder Изготовитель приборной панели
59 Dashboard builders Производители приборных панелей
60 Dashlet builder Изготовитель приборных панелей
61 Dashlet builder list Список разработчиков черточек
62 Dashlet builders Производители приборов Dashlet
63 Data file Файл данных
64 Date Дата
65 Datetime Дата
66 Day День
67 Decimal Десятичная дробь
68 Default Value Значение по умолчанию
69 Depends on Зависит от
70 Description Описание
71 Display дисплей
72 Display message Отобразить сообщение
73 Display type Тип дисплея
74 Do you want to reset workflow ?
75 Domain Домен
76 Donut пончик
77 Dummy Кукла
78 Edit Node Редактировать узел
79 Edit Transition Редактирование перехода
80 Edit before send Изменить перед отправкой
81 Email Электронная почта
82 End node Конечный узел
83 Existing menu Существующее меню
84 Export Экспорт
85 Extra Дополнительная информация
86 Field Поле
87 Field for 'My menu' Поле для Мое меню.
88 Field options
89 Fields Поля
90 Filter Фильтр
91 Filters Фильтры
92 First group by Первая группа по
93 From От
94 Funnel Воронка
95 Gauge Измеритель
96 Generated Actions Сгенерированные действия
97 Generated app Созданное приложение
98 Groovy Клёвый
99 Group By Сгруппировать по
100 Group date type Тип даты группы
101 Group on type Группа по типу
102 Groups Группы
103 Help Помощь
104 Hidden In Grid Скрытые в сети
105 Hidden menu Скрытое меню
106 Horizontal bar Горизонтальная полоса
107 Icon Икона
108 If Если
109 If-module Если-модуль
110 Image Изображение
111 Import Импорт
112 Import BPM Импорт BPM
113 Import log Импорт журнала
114 Incoming Прибыль
115 Integer Целостный
116 Is Json Relational Field
117 Is json Джсон
118 Is parameter Есть параметр
119 Is wkf Wkf
120 Javascript Javascript
121 Json Джсон
122 Json Field Джсон Филд
123 Json Many To Many Json Many To many To many
124 Json Many To One Json Many To One
125 Json One To Many Json One To many
126 Left menu Левое меню
127 Line Линия
128 Link Связь
129 Logic operator Логический оператор
130 Many To Many Много-много-многом
131 Many To One Многие к одному
132 Max Size Максимальный размер
133 Menu action Действие меню
134 Menu builder Создатель меню
135 Menu builders Создатели меню
136 MenuBuilder.Order поря́док
137 Message Сообщение
138 Message on alert or blocking Сообщение о тревоге или блокировке
139 Message on success Сообщение об успехе
140 Meta Model Мета модель
141 Meta module Мета-модуль
142 MetaMenu Мета-меню
143 Min Size Мин Размер
144 Mobile menu Мобильное меню
145 Model Модель
146 Module Модуль
147 Month Месяц
148 Name Имя
149 Name Column
150 Name Field Поле имени
151 Name must not contains space Имя не должно содержать пробелов.
152 Nav Select Навигация Выбрать
153 Nb of passes Nb пропусков
154 Nb of passes per status Nb пропусков на статус
155 Node Узел
156 Node type
157 Nodes Узлы
158 None
159 OR ИЛИ
160 Object Объект
161 On Change О Изменениях
162 On Click Нажать кнопку
163 On New На Новом
164 On Save На Сохранить
165 One To Many Один ко многим
166 Only use this menu-item if the given expression is true. Используйте этот пункт меню только в том случае, если данное выражение соответствует истине.
167 Only use this menu-item if the given module is installed. Данный пункт меню используется только в том случае, если данный модуль установлен.
168 Open record Открытая запись
169 Open workflow Открытый документооборот
170 Operator Оператор
171 Outgoing Отбывающий
172 Overview Обзор
173 Pagination limit Ограничение по количеству страниц
174 Panel Панель
175 Parent Родитель
176 Percentage(%) Процент(%)
177 Permissions Разрешения
178 Pie Chart Круговая диаграмма
179 Please correct the workflow diagram. Пожалуйста, исправьте схему рабочего процесса.
180 Please input value bind with single quotation. Пожалуйста, свяжите вводимое значение с одной кавычкой.
181 Please provide unique code. The code '%s' is already used Пожалуйста, предоставьте уникальный код. Код '%s' уже используется.
182 Process
183 Process display type Тип отображения процесса
184 Process studio Студия процессов
185 Process tracking Отслеживание процесса
186 Properties Свойства
187 Radar Радар
188 ReadOnly for
189 Record Id Ид записи
190 Record model Модель записи
191 Record name Имя записи
192 Regex Регекс
193 Report Доклад
194 Reporting
195 Required Требуется
196 Required If Требуется Если
197 Roles Роли
198 Scatter Рассеивание
199 Script Сценарий
200 Script type Тип сценария
201 Second group by Вторая группа по
202 Select Option Выберите Параметр
203 Selection Выбор
204 Selections
205 Send directly Отправить непосредственно
206 Send option Отправить вариант
207 Separator Сепаратор
208 Sequence Последовательность
209 Show If Показать Если
210 Show Title
211 Show process tracking Показать отслеживание процесса
212 Simple Select Простой выбор
213 Source field Исходное поле
214 Start node Запустить узел
215 Status Статус
216 Status per day Статус в день
217 Status per month Статус в месяц
218 Status time(days) Время статуса (дни)
219 Status time(hours) Время статуса (часы)
220 String Стринг
221 Studio
222 Sub lines Подлинии
223 Tag count Количество меток
224 Tag label Метка
225 Tag method Метод тегов
226 Tag style Стиль тегов
227 Target Цель
228 Target Json Model Цель - Джсон Модель.
229 Target field Целевое поле
230 Target json Цель - Джсон.
231 Target object Объект съемки
232 Target title
233 Target type Тип цели
234 Task node
235 Template Шаблон
236 Text Текст
237 Time Время
238 Time spent Время, проведённое
239 Time spent (hours/days) Время, затраченное (часы/дни)
240 Time spent per status (hours) Время, потраченное на статус (в часах)
241 Time spent per status per user (hours) Время, потраченное на статус одного пользователя (в часах)
242 Title Название
243 To К
244 Top menu Верхнее меню
245 Total time per status Общее время по статусу
246 Track flow Гусеничный поток
247 Track workflow Отслеживание рабочего процесса
248 Tracking line Линия слежения
249 Tracking lines Линии слежения
250 Transactional Транзакционный
251 Transition Переход
252 Transitions Переходы
253 Type Тип
254 UI options
255 Update Обновить
256 User Пользователь
257 Validation type Тип валидации
258 Value Значение
259 Value expr Значение Expr
260 View Просмотр
261 View generated Сгенерированный вид
262 View params Просмотреть параметры
263 Views Виды
264 Widget Виджет
265 Wkf Wkf
266 Wkf field поле Wkf
267 Wkf sequence
268 Wkf tracking Отслеживание Wkf
269 Wkf trackings Отслеживание Wkf
270 Wkf transition переход Wkf
271 Workflow dashboard Приборная панель управления рабочим процессом
272 Workflow is not saved Процесс работы не сохраняется
273 Year Год
274 contains содержит
275 doesn't contains не содержит
276 equal равноценный
277 greater or equal больше или равны
278 greater than нечто большее
279 in в пределах
280 include включать
281 is false это ложь
282 is not null не является нулевым
283 is null равняется нулю
284 is true это правда
285 less or equal менее или равный
286 less than не особо
287 not equal не равный
288 not in не в
289 not include не включает
290 value:BPM ценность:BPM
291 value:Product App ценность:Продукт App
292 xmlId xmlId

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<csv-inputs xmlns="http://axelor.com/xml/ns/data-import"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/data-import http://axelor.com/xml/ns/data-import/data-import_5.2.xsd">
<input file="bpm_role.csv" separator=";" type="com.axelor.auth.db.Role" search="self.name = :name"/>
<input file="bpm_permission.csv" separator=";" type="com.axelor.auth.db.Permission" search="self.name = :name" call="com.axelor.csv.script.ImportPermission:importPermissionToRole">
<bind to="canRead" eval="can_read == 'x' ? 'true' : 'false'"/>
<bind to="canWrite" eval="can_write == 'x' ? 'true' : 'false'"/>
<bind to="canCreate" eval="can_create == 'x' ? 'true' : 'false'"/>
<bind to="canRemove" eval="can_remove == 'x' ? 'true' : 'false'"/>
<bind to="canExport" eval="can_export == 'x' ? 'true' : 'false'"/>
</input>
<input file="bpm_metaMenu.csv" separator=";" type="com.axelor.meta.db.MetaMenu" search="self.name = :name" update="true">
<bind column="roles" to="roles" search="self.name in :roles" eval="roles.split('\\|') as List"/>
</input>
</csv-inputs>

View File

@ -0,0 +1,15 @@
"name";"roles"
"app-builder-root";"BPM Manager|BPM User|BPM Read"
"app-builder-models-views";"BPM Manager|BPM User|BPM Read"
"app-builder-models-views-model-studio";"BPM Manager|BPM User|BPM Read"
"app-builder-models-views-custom-models";"BPM Manager|BPM User|BPM Read"
"app-builder-models-views-custom-fields";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-process-studio";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-process-tracking";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-actions-reporting";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-actions-reporting-chart-builders";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-actions-reporting-dashboard-builders";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-actions-reporting-action-builders";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-actions-reporting-menu-builders";"BPM Manager|BPM User|BPM Read"
"app-builder-bpm-apps-configurator";"BPM Manager|BPM User|BPM Read"
1 name roles
2 app-builder-root BPM Manager|BPM User|BPM Read
3 app-builder-models-views BPM Manager|BPM User|BPM Read
4 app-builder-models-views-model-studio BPM Manager|BPM User|BPM Read
5 app-builder-models-views-custom-models BPM Manager|BPM User|BPM Read
6 app-builder-models-views-custom-fields BPM Manager|BPM User|BPM Read
7 app-builder-bpm BPM Manager|BPM User|BPM Read
8 app-builder-bpm-process-studio BPM Manager|BPM User|BPM Read
9 app-builder-bpm-process-tracking BPM Manager|BPM User|BPM Read
10 app-builder-bpm-actions-reporting BPM Manager|BPM User|BPM Read
11 app-builder-bpm-actions-reporting-chart-builders BPM Manager|BPM User|BPM Read
12 app-builder-bpm-actions-reporting-dashboard-builders BPM Manager|BPM User|BPM Read
13 app-builder-bpm-actions-reporting-action-builders BPM Manager|BPM User|BPM Read
14 app-builder-bpm-actions-reporting-menu-builders BPM Manager|BPM User|BPM Read
15 app-builder-bpm-apps-configurator BPM Manager|BPM User|BPM Read

View File

@ -0,0 +1,49 @@
"name";"object";"can_read";"can_write";"can_create";"can_remove";"can_export";"condition";"conditionParams";"roleName"
"perm.studio.DashletBuilder.r";"com.axelor.studio.db.DashletBuilder";"x";;;;;;;"BPM Read"
"perm.studio.AppBuilder.r";"com.axelor.studio.db.AppBuilder";"x";;;;;;;"BPM Read"
"perm.studio.Wkf.r";"com.axelor.studio.db.Wkf";"x";;;;;;;"BPM Read"
"perm.studio.WkfTrackingTime.r";"com.axelor.studio.db.WkfTrackingTime";"x";;;;;;;"BPM Read"
"perm.studio.DashboardBuilder.r";"com.axelor.studio.db.DashboardBuilder";"x";;;;;;;"BPM Read"
"perm.studio.ActionBuilderLine.r";"com.axelor.studio.db.ActionBuilderLine";"x";;;;;;;"BPM Read"
"perm.studio.WkfTransition.r";"com.axelor.studio.db.WkfTransition";"x";;;;;;;"BPM Read"
"perm.studio.WkfNode.r";"com.axelor.studio.db.WkfNode";"x";;;;;;;"BPM Read"
"perm.studio.WkfTrackingTotal.r";"com.axelor.studio.db.WkfTrackingTotal";"x";;;;;;;"BPM Read"
"perm.studio.ChartBuilder.r";"com.axelor.studio.db.ChartBuilder";"x";;;;;;;"BPM Read"
"perm.studio.WkfTracking.r";"com.axelor.studio.db.WkfTracking";"x";;;;;;;"BPM Read"
"perm.studio.WkfTrackingLine.r";"com.axelor.studio.db.WkfTrackingLine";"x";;;;;;;"BPM Read"
"perm.studio.ActionBuilderView.r";"com.axelor.studio.db.ActionBuilderView";"x";;;;;;;"BPM Read"
"perm.studio.ActionBuilder.r";"com.axelor.studio.db.ActionBuilder";"x";;;;;;;"BPM Read"
"perm.studio.MenuBuilder.r";"com.axelor.studio.db.MenuBuilder";"x";;;;;;;"BPM Read"
"perm.studio.Filter.r";"com.axelor.studio.db.Filter";"x";;;;;;;"BPM Read"
"perm.studio.DashletBuilder.rwc";"com.axelor.studio.db.DashletBuilder";"x";"x";"x";;;;;"BPM User"
"perm.studio.AppBuilder.rwc";"com.axelor.studio.db.AppBuilder";"x";"x";"x";;;;;"BPM User"
"perm.studio.Wkf.rwc";"com.axelor.studio.db.Wkf";"x";"x";"x";;;;;"BPM User"
"perm.studio.WkfTrackingTime.rwc";"com.axelor.studio.db.WkfTrackingTime";"x";"x";"x";;;;;"BPM User"
"perm.studio.DashboardBuilder.rwc";"com.axelor.studio.db.DashboardBuilder";"x";"x";"x";;;;;"BPM User"
"perm.studio.ActionBuilderLine.rwc";"com.axelor.studio.db.ActionBuilderLine";"x";"x";"x";;;;;"BPM User"
"perm.studio.WkfTransition.rwc";"com.axelor.studio.db.WkfTransition";"x";"x";"x";;;;;"BPM User"
"perm.studio.WkfNode.rwc";"com.axelor.studio.db.WkfNode";"x";"x";"x";;;;;"BPM User"
"perm.studio.WkfTrackingTotal.rwc";"com.axelor.studio.db.WkfTrackingTotal";"x";"x";"x";;;;;"BPM User"
"perm.studio.ChartBuilder.rwc";"com.axelor.studio.db.ChartBuilder";"x";"x";"x";;;;;"BPM User"
"perm.studio.WkfTracking.rwc";"com.axelor.studio.db.WkfTracking";"x";"x";"x";;;;;"BPM User"
"perm.studio.WkfTrackingLine.rwc";"com.axelor.studio.db.WkfTrackingLine";"x";"x";"x";;;;;"BPM User"
"perm.studio.ActionBuilderView.rwc";"com.axelor.studio.db.ActionBuilderView";"x";"x";"x";;;;;"BPM User"
"perm.studio.ActionBuilder.rwc";"com.axelor.studio.db.ActionBuilder";"x";"x";"x";;;;;"BPM User"
"perm.studio.MenuBuilder.rwc";"com.axelor.studio.db.MenuBuilder";"x";"x";"x";;;;;"BPM User"
"perm.studio.Filter.rwc";"com.axelor.studio.db.Filter";"x";"x";"x";;;;;"BPM User"
"perm.studio.DashletBuilder.rwcde";"com.axelor.studio.db.DashletBuilder";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.AppBuilder.rwcde";"com.axelor.studio.db.AppBuilder";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.Wkf.rwcde";"com.axelor.studio.db.Wkf";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.WkfTrackingTime.rwcde";"com.axelor.studio.db.WkfTrackingTime";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.DashboardBuilder.rwcde";"com.axelor.studio.db.DashboardBuilder";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.ActionBuilderLine.rwcde";"com.axelor.studio.db.ActionBuilderLine";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.WkfTransition.rwcde";"com.axelor.studio.db.WkfTransition";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.WkfNode.rwcde";"com.axelor.studio.db.WkfNode";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.WkfTrackingTotal.rwcde";"com.axelor.studio.db.WkfTrackingTotal";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.ChartBuilder.rwcde";"com.axelor.studio.db.ChartBuilder";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.WkfTracking.rwcde";"com.axelor.studio.db.WkfTracking";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.WkfTrackingLine.rwcde";"com.axelor.studio.db.WkfTrackingLine";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.ActionBuilderView.rwcde";"com.axelor.studio.db.ActionBuilderView";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.ActionBuilder.rwcde";"com.axelor.studio.db.ActionBuilder";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.MenuBuilder.rwcde";"com.axelor.studio.db.MenuBuilder";"x";"x";"x";"x";"x";;;"BPM Manager"
"perm.studio.Filter.rwcde";"com.axelor.studio.db.Filter";"x";"x";"x";"x";"x";;;"BPM Manager"
1 name object can_read can_write can_create can_remove can_export condition conditionParams roleName
2 perm.studio.DashletBuilder.r com.axelor.studio.db.DashletBuilder x BPM Read
3 perm.studio.AppBuilder.r com.axelor.studio.db.AppBuilder x BPM Read
4 perm.studio.Wkf.r com.axelor.studio.db.Wkf x BPM Read
5 perm.studio.WkfTrackingTime.r com.axelor.studio.db.WkfTrackingTime x BPM Read
6 perm.studio.DashboardBuilder.r com.axelor.studio.db.DashboardBuilder x BPM Read
7 perm.studio.ActionBuilderLine.r com.axelor.studio.db.ActionBuilderLine x BPM Read
8 perm.studio.WkfTransition.r com.axelor.studio.db.WkfTransition x BPM Read
9 perm.studio.WkfNode.r com.axelor.studio.db.WkfNode x BPM Read
10 perm.studio.WkfTrackingTotal.r com.axelor.studio.db.WkfTrackingTotal x BPM Read
11 perm.studio.ChartBuilder.r com.axelor.studio.db.ChartBuilder x BPM Read
12 perm.studio.WkfTracking.r com.axelor.studio.db.WkfTracking x BPM Read
13 perm.studio.WkfTrackingLine.r com.axelor.studio.db.WkfTrackingLine x BPM Read
14 perm.studio.ActionBuilderView.r com.axelor.studio.db.ActionBuilderView x BPM Read
15 perm.studio.ActionBuilder.r com.axelor.studio.db.ActionBuilder x BPM Read
16 perm.studio.MenuBuilder.r com.axelor.studio.db.MenuBuilder x BPM Read
17 perm.studio.Filter.r com.axelor.studio.db.Filter x BPM Read
18 perm.studio.DashletBuilder.rwc com.axelor.studio.db.DashletBuilder x x x BPM User
19 perm.studio.AppBuilder.rwc com.axelor.studio.db.AppBuilder x x x BPM User
20 perm.studio.Wkf.rwc com.axelor.studio.db.Wkf x x x BPM User
21 perm.studio.WkfTrackingTime.rwc com.axelor.studio.db.WkfTrackingTime x x x BPM User
22 perm.studio.DashboardBuilder.rwc com.axelor.studio.db.DashboardBuilder x x x BPM User
23 perm.studio.ActionBuilderLine.rwc com.axelor.studio.db.ActionBuilderLine x x x BPM User
24 perm.studio.WkfTransition.rwc com.axelor.studio.db.WkfTransition x x x BPM User
25 perm.studio.WkfNode.rwc com.axelor.studio.db.WkfNode x x x BPM User
26 perm.studio.WkfTrackingTotal.rwc com.axelor.studio.db.WkfTrackingTotal x x x BPM User
27 perm.studio.ChartBuilder.rwc com.axelor.studio.db.ChartBuilder x x x BPM User
28 perm.studio.WkfTracking.rwc com.axelor.studio.db.WkfTracking x x x BPM User
29 perm.studio.WkfTrackingLine.rwc com.axelor.studio.db.WkfTrackingLine x x x BPM User
30 perm.studio.ActionBuilderView.rwc com.axelor.studio.db.ActionBuilderView x x x BPM User
31 perm.studio.ActionBuilder.rwc com.axelor.studio.db.ActionBuilder x x x BPM User
32 perm.studio.MenuBuilder.rwc com.axelor.studio.db.MenuBuilder x x x BPM User
33 perm.studio.Filter.rwc com.axelor.studio.db.Filter x x x BPM User
34 perm.studio.DashletBuilder.rwcde com.axelor.studio.db.DashletBuilder x x x x x BPM Manager
35 perm.studio.AppBuilder.rwcde com.axelor.studio.db.AppBuilder x x x x x BPM Manager
36 perm.studio.Wkf.rwcde com.axelor.studio.db.Wkf x x x x x BPM Manager
37 perm.studio.WkfTrackingTime.rwcde com.axelor.studio.db.WkfTrackingTime x x x x x BPM Manager
38 perm.studio.DashboardBuilder.rwcde com.axelor.studio.db.DashboardBuilder x x x x x BPM Manager
39 perm.studio.ActionBuilderLine.rwcde com.axelor.studio.db.ActionBuilderLine x x x x x BPM Manager
40 perm.studio.WkfTransition.rwcde com.axelor.studio.db.WkfTransition x x x x x BPM Manager
41 perm.studio.WkfNode.rwcde com.axelor.studio.db.WkfNode x x x x x BPM Manager
42 perm.studio.WkfTrackingTotal.rwcde com.axelor.studio.db.WkfTrackingTotal x x x x x BPM Manager
43 perm.studio.ChartBuilder.rwcde com.axelor.studio.db.ChartBuilder x x x x x BPM Manager
44 perm.studio.WkfTracking.rwcde com.axelor.studio.db.WkfTracking x x x x x BPM Manager
45 perm.studio.WkfTrackingLine.rwcde com.axelor.studio.db.WkfTrackingLine x x x x x BPM Manager
46 perm.studio.ActionBuilderView.rwcde com.axelor.studio.db.ActionBuilderView x x x x x BPM Manager
47 perm.studio.ActionBuilder.rwcde com.axelor.studio.db.ActionBuilder x x x x x BPM Manager
48 perm.studio.MenuBuilder.rwcde com.axelor.studio.db.MenuBuilder x x x x x BPM Manager
49 perm.studio.Filter.rwcde com.axelor.studio.db.Filter x x x x x BPM Manager

View File

@ -0,0 +1,4 @@
"name";"description"
"BPM Read";
"BPM User";
"BPM Manager";
1 name description
2 BPM Read
3 BPM User
4 BPM Manager

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<object-views xmlns="http://axelor.com/xml/ns/object-views"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
<grid name="action-builder-grid" title="Action builder" model="com.axelor.studio.db.ActionBuilder">
<field name="name" />
<field name="model" />
<field name="typeSelect" />
<field name="appBuilder" grid-view="app-builder-grid" form-view="app-builder-form"/>
</grid>
<form name="action-builder-form" title="Action builder" model="com.axelor.studio.db.ActionBuilder" width="large">
<panel name="mainPanel">
<field name="isJson" onChange="action-action-builder-method-set-views,action-action-builder-type-select-change" colSpan="2"/>
<field name="appBuilder" grid-view="app-builder-grid" form-view="app-builder-form"/>
<field name="name" colSpan="9" required="true"/>
<field name="typeSelect" onChange="action-action-builder-type-select-change" colSpan="3"/>
<panel name="modelPanel" colSpan="6" itemSpan="12">
<field name="model" widget="ref-text" x-target-name="name" x-target="com.axelor.meta.db.MetaJsonModel"
requiredIf="(typeSelect &lt; 2 || typeSelect == 4) &amp;&amp; isJson"
hideIf="typeSelect == 2 || !isJson"
onChange="action-action-builder-method-set-views,action-action-builder-attrs-model-change" />
<field name="model" hideIf="typeSelect == 2 || isJson"
requiredIf="(typeSelect &lt; 2 || typeSelect == 4) &amp;&amp; !isJson"
widget="ref-text" x-target-name="fullName" x-target="com.axelor.meta.db.MetaModel"
onChange="action-action-builder-method-set-views,action-action-builder-attrs-model-change" />
</panel>
<panel name="emailSendOptionSelectPanel" colSpan="6" showIf="typeSelect == 4">
<field name="emailSendOptionSelect" requiredIf="typeSelect == 4"/>
</panel>
<panel name="targetModelPanel" colSpan="6" itemSpan="12">
<field name="targetModel" requiredIf="typeSelect == 0 &amp;&amp; isJson" showIf="typeSelect == 0 &amp;&amp; isJson" widget="ref-text"
x-target-name="name" x-target="com.axelor.meta.db.MetaJsonModel"/>
<field name="targetModel" requiredIf="typeSelect == 0 &amp;&amp; !isJson" showIf="typeSelect == 0 &amp;&amp; !isJson" widget="ref-text"
x-target-name="fullName" x-target="com.axelor.meta.db.MetaModel"/>
</panel>
<field name="openRecord" showIf="typeSelect == 0" colSpan="4" />
<field name="displayMsg" showIf="typeSelect == 0" colSpan="8"/>
<field name="title" colSpan="12" showIf="typeSelect == 3" requiredIf="typeSelect == 3"/>
<field name="actionBuilderViews" showIf="typeSelect == 3" colSpan="12">
<editor>
<field name="viewType" colSpan="3" />
<field name="viewName" colSpan="5" widget="ref-text" x-target="com.axelor.meta.db.MetaView" x-target-name="name" onSelect="action-action-builder-view-name-domain"/>
<field name="viewConditionToCheck" colSpan="4"/>
</editor>
</field>
<field name="lines" title="Context" hideIf="typeSelect != 3" colSpan="12">
<editor>
<field name="name" title="Name" colSpan="4" />
<field name="value" colSpan="8"/>
</editor>
</field>
<field name="viewParams" title="View params" hideIf="typeSelect != 3" colSpan="12">
<editor>
<field name="name" title="Name" colSpan="4" />
<field name="value" title="Value" colSpan="8"/>
</editor>
</field>
<field name="domainCondition" showIf="typeSelect == 3" colSpan="12" />
<panel-related name="linesPanel" field="lines" colSpan="12" hideIf="typeSelect &gt; 1" grid-view="action-builder-line-grid" form-view="action-builder-line-form" />
<panel name="scriptPanel" showIf="typeSelect == 2" colSpan="12" >
<field name="scriptType" />
<field name="transactional" />
<field name="scriptText" widget="CodeEditor" x-code-syntax="javascript" colSpan="12" />
</panel>
<panel name="emailTemplatePanel" colSpan="12">
<field name="scriptText" widget="html" title="Template" colSpan="12" showIf="typeSelect == 5"/>
<field name="emailTemplate" onSelect="action-action-builder-attrs-template-domain" requiredIf="typeSelect == 4" grid-view="template-grid" form-view="template-form" showIf="typeSelect == 4"/>
</panel>
</panel>
</form>
<action-record name="action-action-builder-type-select-change" model="com.axelor.studio.db.ActionBuilder">
<field name="model" expr="eval:null"/>
<field name="targetModel" expr="eval:null"/>
</action-record>
<action-record name="action-action-builder-attrs-model-change" model="com.axelor.studio.db.ActionBuilder">
<field name="emailTemplate" expr="eval:null"/>
</action-record>
<action-attrs name="action-action-builder-view-name-domain">
<attribute name="domain" for="viewName" expr="eval:&quot;self.type = '${viewType}' &quot;" if="viewType == 'dashboard'"/>
<attribute name="domain" for="viewName" expr="eval:&quot;self.type = '${viewType}' and self.model = 'com.axelor.meta.db.MetaJsonRecord' and self.name = 'custom-model-${_parent.model}-${viewType}' &quot;" if="_parent.isJson &amp;&amp; viewType != 'dashboard'"/>
<attribute name="domain" for="viewName" expr="eval:&quot;self.type = '${viewType}' and self.model = '${_parent.model}'&quot;" if="!_parent.isJson &amp;&amp; viewType != 'dashboard'"/>
</action-attrs>
<action-attrs name="action-action-builder-attrs-template-domain">
<attribute name="domain" for="emailTemplate" expr="eval:(model != null) ? &quot; self.metaModel.fullName = '${model}' AND self.isJson = '${isJson}' &quot; : &quot; self.isJson = '${isJson}' &quot;" if="!isJson"/>
<attribute name="domain" for="emailTemplate" expr="eval:(model != null) ? &quot; self.metaJsonModel.name = '${model}' AND self.isJson = '${isJson}' &quot; : &quot; self.isJson = '${isJson}' &quot;" if="isJson"/>
</action-attrs>
<action-method name="action-action-builder-method-set-views">
<call class="com.axelor.studio.web.ActionBuilderController" method="setViews" if="typeSelect == 3"/>
</action-method>
</object-views>

Some files were not shown because too many files have changed in this diff Show More