svn commit: r1780683 [1/3] - in /ofbiz/trunk/plugins/birt: ./ config/ data/ groovyScripts/report/ minilang/ servicedef/ src/main/java/org/apache/ofbiz/birt/ src/main/java/org/apache/ofbiz/birt/flexible/ src/main/java/org/apache/ofbiz/birt/report/servle...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1780683 [1/3] - in /ofbiz/trunk/plugins/birt: ./ config/ data/ groovyScripts/report/ minilang/ servicedef/ src/main/java/org/apache/ofbiz/birt/ src/main/java/org/apache/ofbiz/birt/flexible/ src/main/java/org/apache/ofbiz/birt/report/servle...

nmalin
Author: nmalin
Date: Sat Jan 28 13:22:55 2017
New Revision: 1780683

URL: http://svn.apache.org/viewvc?rev=1780683&view=rev
Log:
Implemented: Birt Report Builder: an enhancement of the Birt component. Easier user possibility of report creation. (OFBIZ-6919)

The concept, you define a report domain related to an entity or a service through a master content (master report) and a master search form.
When a high level user create a report on a configured domain, OFBiz prepare an instantiation of the master content (flexible report) that permit
to surcharge the search form (recorded dynamically on the content as ElectronicText) and prepare a rptDesign skeleton.
The high level user can download the rptDesign to edit it trhough the birt editor, with all fields that ofbiz will be load as dataset and when is finish upload the result on the content instantiation.
For the end user, he selected the instantiation report, OFBiz display the report search from the content instantiation and the submission call birt with the search parameters and the linked rptDesign.

The rptDesign file is drive by OFBiz to build the data set by two methods :
 * call the performFind if the domain is related to an entity
 * call the a custom service if the domain is related to a service.
For the last case we need two services, a first who prepare and list available fields for search and display. And a second who realize the search.
By convention currently the first service as the same name that the second service suffixed by 'PrepareFields'

This commit contains :
 * useful UI to create a new content instance from a master content. List, edit, remove a content instance and a simple drop-down to list all instance published (ready to use by end user)
 * all services (with the work flexibleReport) to manage a flexible report, prepare the rptDesign skeleton, reanalyze the rptDesign uploaded, prepare the search form
 * Services interface to define you own search custom method
 * Two examples, one on the entity Exemple and one with the service flexibleReportTurnOver. Warning ! there are raw example without a beautiful rptDesign so you need to update the rptDesign with the birt editor to display something.
Thanks: François Wurmser for initialize this improvement, Jacques and Gil for their time to analyze, document and refactor the code

Added:
    ofbiz/trunk/plugins/birt/config/BirtErrorUiLabels.xml
    ofbiz/trunk/plugins/birt/data/BirtMasterData.xml
    ofbiz/trunk/plugins/birt/data/BirtSecurityGroupDemoData.xml
    ofbiz/trunk/plugins/birt/data/BirtTypeData.xml
    ofbiz/trunk/plugins/birt/groovyScripts/report/
    ofbiz/trunk/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy
    ofbiz/trunk/plugins/birt/minilang/
    ofbiz/trunk/plugins/birt/minilang/BirtPermissionServices.xml
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtServices.java
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtUtil.java
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/ReportDesignGenerator.java
    ofbiz/trunk/plugins/birt/widget/birt/BirtMasterForms.xml
Modified:
    ofbiz/trunk/plugins/birt/config/BirtUiLabels.xml
    ofbiz/trunk/plugins/birt/ofbiz-component.xml
    ofbiz/trunk/plugins/birt/servicedef/services.xml
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtEngineServlet.java
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/report/servlet/BirtViewerServlet.java
    ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/webapp/view/BirtViewHandler.java
    ofbiz/trunk/plugins/birt/webapp/birt/WEB-INF/controller.xml
    ofbiz/trunk/plugins/birt/widget/birt/BirtForms.xml
    ofbiz/trunk/plugins/birt/widget/birt/BirtMenus.xml
    ofbiz/trunk/plugins/birt/widget/birt/BirtScreens.xml

Added: ofbiz/trunk/plugins/birt/config/BirtErrorUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/config/BirtErrorUiLabels.xml?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/config/BirtErrorUiLabels.xml (added)
+++ ofbiz/trunk/plugins/birt/config/BirtErrorUiLabels.xml Sat Jan 28 13:22:55 2017
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-properties.xsd">
+    <property key="BirtErrorCannotDetermineDataSource">
+        <value xml:lang="en">Failed to determine data source for report</value>
+        <value xml:lang="fr">La détermination de la source de données à échoué</value>
+    </property>
+    <property key="BirtErrorCannotFindUploadedFile">
+        <value xml:lang="en">Could not find uploaded file</value>
+        <value xml:lang="fr">Impossible de trouver le fichier uploadé</value>
+    </property>
+    <property key="BirtErrorCannotLocateReportFile">
+        <value xml:lang="en">Report file cannot be located. It does not exist in specified directory.</value>
+        <value xml:lang="fr">Le fichier de rapport n'a pas pu être localisé. Il n'existe pas dans le dossier spécifié.</value>
+    </property>
+    <property key="BirtErrorCannotLocateReportFolder">
+        <value xml:lang="en">Report folder cannot be located. Are you sure you configured correctly birt.properties for the report folder path?</value>
+        <value xml:lang="fr">Le dossier de stockage des rapports n'a pu être localisé. Êtes-vous sûr d'avoir bien configuré birt.properties pour le chemin du dossier ?</value>
+    </property>
+    <property key="BirtErrorConversionFieldToBirtFailed">
+        <value xml:lang="en">Failed to convert fieldType to birtType</value>
+        <value xml:lang="fr">Conversion du type de champ en type birt échouée</value>
+    </property>
+    <property key="BirtErrorCreatingDefaultSearchForm">
+        <value xml:lang="en">An error happened while creating the display of current form.</value>
+        <value xml:lang="fr">Erreur à la création de l'affichage du formulaire actuel</value>
+    </property>
+    <property key="BirtErrorCreatingFlexibleReport">
+        <value xml:lang="en">Error while generating report</value>
+        <value xml:lang="fr">Erreur lors de la création du rapport</value>
+    </property>
+    <property key="BirtErrorEntityViewNotExist">
+        <value xml:lang="en">This entity/view name is not valid</value>
+        <value xml:lang="fr">Ce nom de vue/entité n'est pas valide</value>
+    </property>
+    <property key="BirtErrorEntityViewNotFound">
+        <value xml:lang="en">No view entity name found</value>
+        <value xml:lang="fr">Aucun nom de vue/entité n'a été trouvé</value>
+    </property>
+    <property key="BirtErrorNoAttributeFound">
+        <value xml:lang="en">Master workflow attribute not found</value>
+        <value xml:lang="fr">L'attribut de workflow du master n'as pas pu être trouvé</value>
+    </property>
+    <property key="BirtErrorNoFlexibleReportToDelete">
+        <value xml:lang="en">No report to delete</value>
+        <value xml:lang="fr">Aucun rapport à supprimer</value>
+    </property>
+    <property key="BirtErrorRetrievingTurnOver">
+        <value xml:lang="en">Error while retrieving turnover informations</value>
+        <value xml:lang="fr">Erreur lors de l'accès aux informations liées au chiffre d'affaire</value>
+    </property>
+    <property key="BirtErrorRunningPerformFind">
+        <value xml:lang="en">Error running performFind</value>
+        <value xml:lang="fr">Erreur lors de l'exécution du performFind</value>
+    </property>
+    <property key="BirtErrorUnauthorisedCharacter">
+        <value xml:lang="en">Form refused: unauthorised character detected</value>
+        <value xml:lang="fr">Formulaire refusé : caractère non autorisé</value>
+    </property>
+    <property key="BirtErrorUnexpectedNumberReportToDelete">
+        <value xml:lang="en">Unexpected number of reports selected for deletion</value>
+        <value xml:lang="fr">Tentative de suppression d'un nombre inattendu de rapports</value>
+    </property>
+</resource>
\ No newline at end of file

Modified: ofbiz/trunk/plugins/birt/config/BirtUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/config/BirtUiLabels.xml?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/config/BirtUiLabels.xml (original)
+++ ofbiz/trunk/plugins/birt/config/BirtUiLabels.xml Sat Jan 28 13:22:55 2017
@@ -21,6 +21,7 @@
 <resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-properties.xsd">
     <property key="BirtApplication">
         <value xml:lang="en">Eclipse BIRT Application</value>
+        <value xml:lang="fr">Application Eclipse Birt</value>
         <value xml:lang="ja">Eclipse BIRT 業務</value>
         <value xml:lang="th">Eclipse BIRT Application</value>
         <value xml:lang="zh">Eclipse BIRT应用程序</value>
@@ -41,6 +42,22 @@
         <value xml:lang="zh">开源软件OFBiz的组成部分</value>
         <value xml:lang="zh-TW">開源軟體OFBiz的組成部分</value>
     </property>
+    <property key="BirtConfirmDeleteFlexibleReports">
+        <value xml:lang="en">Are you sure you want to delete all reports?</value>
+        <value xml:lang="fr">Voulez-vous vraiment supprimer tous les rapports ?</value>
+    </property>
+    <property key="BirtDeleteFlexibeReports">
+        <value xml:lang="en">Delete all reports</value>
+        <value xml:lang="fr">Supprimer tous les rapports</value>
+    </property>
+    <property key="BirtDownloadRptDesign">
+        <value xml:lang="en">Download rptdesign file</value>
+        <value xml:lang="fr">Télécharger le fichier rptdesign</value>
+    </property>
+    <property key="BirtEditFlexibleReport">
+        <value xml:lang="en">Edit report</value>
+        <value xml:lang="fr">Modification du rapport</value>
+    </property>
     <property key="BirtErrorFOPRenderingAttachmentForEmail">
         <value xml:lang="en">Error FOP rendering ${birtContentType} attachment for email: ${errorString}</value>
     </property>
@@ -88,6 +105,66 @@
         <value xml:lang="fr">Ruptures de stock, pour le nombre de derniers mois : </value>
         <value xml:lang="zh">上月脱销的数量</value>
     </property>
+    <property key="BirtFindCompareOperator">
+        <value xml:lang="en"> - Operator - </value>
+        <value xml:lang="fr"> - Opérateur - </value>
+    </property>
+    <property key="BirtFindFieldOptionValue0">
+        <value xml:lang="en"> - Lower bound or equal - </value>
+        <value xml:lang="fr"> - Borne basse ou égal - </value>
+    </property>
+    <property key="BirtFindFieldOptionValue1">
+        <value xml:lang="en"> - Higher bound  - </value>
+        <value xml:lang="fr"> - Borne haute - </value>
+    </property>
+    <property key="BirtFilteringParameters">
+        <value xml:lang="en">Filtering parameters</value>
+        <value xml:lang="fr">Paramètres de filtrage</value>
+    </property>
+    <property key="BirtFlexibleReport">
+        <value xml:lang="en">Flexible Report</value>
+        <value xml:lang="fr">Rapport configurable</value>
+    </property>
+    <property key="BirtFlexibleReportGeneration">
+        <value xml:lang="en">Generate report</value>
+        <value xml:lang="fr">Générer un rapport</value>
+    </property>
+    <property key="BirtFlexibleReportInformation">
+        <value xml:lang="en">Report information</value>
+        <value xml:lang="fr">Informations du rapport</value>
+    </property>
+    <property key="BirtFlexibleReportManagement">
+        <value xml:lang="en">Reports management</value>
+        <value xml:lang="fr">Gestion des rapports</value>
+    </property>
+    <property key="BirtFlexibleReportSuccessfullyDeleted">
+        <value xml:lang="en">The report has been successfully deleted</value>
+        <value xml:lang="fr">Le rapport a été supprimé avec succès</value>
+    </property>
+    <property key="BirtFlexibleReportsSuccessfullyDeleted">
+        <value xml:lang="en">All reports have been successfully deleted</value>
+        <value xml:lang="fr">Tous les rapports ont été supprimés avec succès</value>
+    </property>
+    <property key="BirtFlexibleReportSuccessfullyGenerated">
+        <value xml:lang="en">Report has been successfully generated under the name: </value>
+        <value xml:lang="fr">Le rapport a été généré avec succès sous le nom : </value>
+    </property>
+    <property key="BirtFlexibleRptDesignSuccessfullyUploaded">
+        <value xml:lang="en">Report file successfully uploaded</value>
+        <value xml:lang="fr">Le fichier de rapport a été uploadé avec succès</value>
+    </property>
+    <property key="BirtGenericReport">
+        <value xml:lang="en">Use a report</value>
+        <value xml:lang="fr">Utiliser un rapport</value>
+    </property>
+    <property key="BirtManageReports">
+        <value xml:lang="en">Manage reports</value>
+        <value xml:lang="fr">Gérer les rapports</value>
+    </property>
+    <property key="BirtNoKnownFlexibleReport">
+        <value xml:lang="en">You have no report yet</value>
+        <value xml:lang="fr">Vous n'avez aucun rapport pour l'instant</value>
+    </property>
     <property key="BirtOrderReportAllOrderItemsWithDiscountCode">
         <value xml:lang="en">All order items with discount code</value>
         <value xml:lang="fr">Tous les lignes de commandes ayant des codes promotionels</value>
@@ -138,6 +215,26 @@
         <value xml:lang="fr">Quatre tableau créés par Birt (Ventes des 3 derniers mois, Ventes, Ventes par codes promotionels, Demandes par produit) nécessitent d'alimenter la base de données d'Inform. décis. (notez aussi la nécessaire màj du fichier bi.properties après septembre 2023). Ensuite seules les commandes nouvellement approuvées seront prises en compte.</value>
         <value xml:lang="zh">4个Birt报告(最近3个月销售、销售、销售订单折扣优惠码、产品需求)要求提供BI数据库(注意:bi.properites文件需要在2023å¹´9月后进行更新)。只会统计新批准的那些订单。</value>
     </property>
+    <property key="BirtPermissionError">
+        <value xml:lang="en">Birt Permission Error</value>
+        <value xml:lang="fr">Erreur d'autorisation sur le composant Birt</value>
+    </property>
+    <property key="BirtSearchFormSuccessfullyOverridde">
+        <value xml:lang="en">The form has been successfully updated</value>
+        <value xml:lang="fr">Le formulaire a bien été mis à jour</value>
+    </property>
+    <property key="BirtSelectFlexibleReport">
+        <value xml:lang="en">Report choice</value>
+        <value xml:lang="fr">Choix du rapport</value>
+    </property>
+    <property key="BirtSelectMasterFlexibleReport">
+        <value xml:lang="en">Choose report topic</value>
+        <value xml:lang="fr">Choix du sujet du rapport</value>
+    </property>
+    <property key="BirtUploadRptDesign">
+        <value xml:lang="en">Upload rptdesign file</value>
+        <value xml:lang="fr">Importer le fichier rptdesign</value>
+    </property>
     <property key="ExampleBirtChartReport">
         <value xml:lang="en">HTML chart report</value>
         <value xml:lang="fr">Graphiques HTML</value>
@@ -154,6 +251,7 @@
     </property>
     <property key="ExampleBirtExamples">
         <value xml:lang="en">BIRT Examples</value>
+        <value xml:lang="fr">Exemples BIRT</value>
         <value xml:lang="ja">BIRT サンプル</value>
         <value xml:lang="th">ตัวอย่าง BIRT</value>
         <value xml:lang="zh">BIRT样例</value>
@@ -161,18 +259,27 @@
     </property>
     <property key="ExampleBirtMail">
         <value xml:lang="en">Send any format through Mail</value>
+        <value xml:lang="fr">Envoyer différents formats par mail</value>
         <value xml:lang="ja">任意の書式をメールで送信する</value>
         <value xml:lang="zh">通过邮件发送任一格式</value>
         <value xml:lang="zh-TW">通過郵件發送任一格式</value>
     </property>
     <property key="ExampleBirtReport">
         <value xml:lang="en">HTML</value>
-        <value xml:lang="zh">HTML</value>
-        <value xml:lang="zh-TW">HTML</value>
     </property>
     <property key="ExampleBirtViewHandler">
         <value xml:lang="en">PDF</value>
-        <value xml:lang="zh">PDF</value>
-        <value xml:lang="zh-TW">PDF</value>
+    </property>
+    <property key="FormFieldTitle_birtContentType">
+        <value xml:lang="en">Birt export format</value>
+        <value xml:lang="fr">Format d'export Birt</value>
+    </property>
+    <property key="FormFieldTitle_reportName">
+        <value xml:lang="en">Report name</value>
+        <value xml:lang="fr">Nom du rapport</value>
+    </property>
+    <property key="FormFieldTitle_writeFilters">
+        <value xml:lang="en">Generate filters in design</value>
+        <value xml:lang="fr">Générer les filtres dans le design</value>
     </property>
 </resource>

Added: ofbiz/trunk/plugins/birt/data/BirtMasterData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/data/BirtMasterData.xml?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/data/BirtMasterData.xml (added)
+++ ofbiz/trunk/plugins/birt/data/BirtMasterData.xml Sat Jan 28 13:22:55 2017
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<entity-engine-xml>
+    <DataResource dataResourceId="DR_MASTER_EXAMPLE" dataResourceTypeId="ELECTRONIC_TEXT" dataTemplateTypeId="FORM_COMBINED" />
+    <ElectronicText dataResourceId="DR_MASTER_EXAMPLE">
+        <textData><![CDATA[<!--default domain form-->
+<form name="${masterContentId}_${contentId}" type="single" extends="${masterContentId}" extends-resource="component://birt/widget/birt/BirtMasterForms.xml">
+</form>]]>
+        </textData>
+    </ElectronicText>
+    <Content contentId="CTNT_MASTER_EXAMPLE" contentTypeId="REPORT_MASTER"  dataResourceId="DR_MASTER_EXAMPLE" statusId="CTNT_PUBLISHED" contentName="Example" description="Master Content for Example" />
+    <!-- Data retrieval will be done using perform find on entity Example-->
+    <ContentAttribute contentId="CTNT_MASTER_EXAMPLE" attrName="Entity" attrValue="Example"/>
+
+    <CustomMethod customMethodId="CM_FB_TURNOVER" customMethodTypeId="FLEXIBLE_BIRT" customMethodName="flexibleReportTurnOver" description="service to resolve invoice for turnover report domain"/>
+    <DataResource dataResourceId="DR_MASTER_TURNOVER" dataResourceTypeId="ELECTRONIC_TEXT" dataTemplateTypeId="FORM_COMBINED" />
+    <ElectronicText dataResourceId="DR_MASTER_TURNOVER">
+        <textData><![CDATA[<!--default domain form-->
+<form name="${masterContentId}_${contentId}" type="single" extends="${masterContentId}" extends-resource="component://birt/widget/birt/BirtMasterForms.xml">
+</form>]]>
+        </textData>
+    </ElectronicText>
+    <Content contentId="CTNT_MASTER_TURNOVER" customMethodId="CM_FB_TURNOVER" contentTypeId="REPORT_MASTER" dataResourceId="DR_MASTER_TURNOVER" statusId="CTNT_PUBLISHED" contentName="Turnover" description="Master Content for TURNOVER domain" />
+    <!-- Data retrieval will be done using two service call. First the contentAttribute Service give the service that will define which data and label will be retrieved,
+    and which filter and label are supported by the report design (default value will call the second service with "prepareField" suffix).
+    Second, the custom method give the service to retrieve all data in the report design.
+    Here : flexibleReportTurnOverPrepareFields (customMethodName + "prepareFields") then flexibleReportTurnOver-->
+    <ContentAttribute contentId="CTNT_MASTER_TURNOVER" attrName="Service" attrValue="default"/>
+
+</entity-engine-xml>
\ No newline at end of file

Added: ofbiz/trunk/plugins/birt/data/BirtSecurityGroupDemoData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/data/BirtSecurityGroupDemoData.xml?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/data/BirtSecurityGroupDemoData.xml (added)
+++ ofbiz/trunk/plugins/birt/data/BirtSecurityGroupDemoData.xml Sat Jan 28 13:22:55 2017
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<entity-engine-xml>
+    <SecurityPermission permissionId="BIRT_ADMIN" description="ALL Birt component operations"/>
+    <SecurityPermission permissionId="BIRT_CREATE" description="Create report from master"/>
+    <SecurityPermission permissionId="BIRT_UPDATE" description="Update operations for reports"/>
+    <SecurityPermission permissionId="BIRT_DELETE" description="Delete reports"/>
+    <SecurityPermission permissionId="BIRT_VIEW" description="View and use all birt reports"/>
+
+    <SecurityGroup groupId="BIRTADMIN" description="Birt - admin"/>
+    <SecurityGroup groupId="BIRTUSER" description="Birt - user"/>
+
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_CREATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_UPDATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_DELETE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="BIRT_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="OFBTOOLS_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_ROLE_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_ROLE_CREATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_CREATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_ROLE_UPDATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_UPDATE"/>
+    <SecurityGroupPermission groupId="BIRTADMIN" permissionId="CONTENTMGR_DELETE"/>
+
+    <SecurityGroupPermission groupId="BIRTUSER" permissionId="BIRT_VIEW"/>
+    <SecurityGroupPermission groupId="BIRTUSER" permissionId="OFBTOOLS_VIEW"/>
+
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_CREATE"/>
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_UPDATE"/>
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_DELETE"/>
+    <SecurityGroupPermission groupId="FULLADMIN" permissionId="BIRT_VIEW"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_CREATE"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_UPDATE"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_DELETE"/>
+    <SecurityGroupPermission groupId="FLEXADMIN" permissionId="BIRT_VIEW"/>
+</entity-engine-xml>
\ No newline at end of file

Added: ofbiz/trunk/plugins/birt/data/BirtTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/data/BirtTypeData.xml?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/data/BirtTypeData.xml (added)
+++ ofbiz/trunk/plugins/birt/data/BirtTypeData.xml Sat Jan 28 13:22:55 2017
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<entity-engine-xml>
+    <ContentType contentTypeId="REPORT_MASTER" description="Report Master" />
+    <ContentType contentTypeId="FLEXIBLE_REPORT" description="Report" />
+    <ContentType contentTypeId="RPTDESIGN" description="Birt report (.rptDesign) file" />
+    <DataTemplateType dataTemplateTypeId="FORM_COMBINED" description="Form widget" extension="xml" />
+
+    <CustomMethodType customMethodTypeId="FLEXIBLE_BIRT" description="Service calling from a birt rptDesign file to populate the data source"/>
+    <CustomMethod customMethodId="CM_FB_PERFORM_FIND" customMethodTypeId="FLEXIBLE_BIRT" customMethodName="callPerformFindFromBirt" description="Generic service to call the standard performFind service from birt rptDesign file"/>
+
+    <EnumerationType enumTypeId="FLEXIBLE_BIRT" description="Mime Type Format available for flexible birt system"/>
+
+    <Enumeration enumId="FB_ODS" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.oasis.opendocument.spreadsheet" sequenceId="01" enumCode="LibreOffice Calc (.ods)"/>
+    <Enumeration enumId="FB_ODT" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.oasis.opendocument.text" sequenceId="02" enumCode="LibreOffice Writer (.odt)"/>
+    <Enumeration enumId="FB_ODP" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.oasis.opendocument.presentation" sequenceId="03" enumCode="LibreOffice Impress (.odp)"/>
+    <Enumeration enumId="FB_PDF" enumTypeId="FLEXIBLE_BIRT" description="application/pdf" sequenceId="04" enumCode="Pdf (.pdf)"/>
+    <Enumeration enumId="FB_PS" enumTypeId="FLEXIBLE_BIRT" description="application/postscript" sequenceId="05" enumCode="Postscript (.ps)"/>
+    <Enumeration enumId="FB_HTML" enumTypeId="FLEXIBLE_BIRT" description="text/html" sequenceId="06" enumCode="Text (.html)"/>
+    <Enumeration enumId="FB_XSLX" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" sequenceId="07" enumCode="Excel (.xlsx)"/>
+    <Enumeration enumId="FB_DOCX" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.openxmlformats-officedocument.wordprocessingml.document" sequenceId="08" enumCode="Word (.docx)"/>
+    <Enumeration enumId="FB_PPTX" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.openxmlformats-officedocument.presentationml.presentation" sequenceId="09" enumCode="Powerpoint (.pptx)"/>
+    <Enumeration enumId="FB_XLS" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.ms-excel" sequenceId="10" enumCode="Excel (.xls)"/>
+    <Enumeration enumId="FB_DOC" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.ms-word" sequenceId="11" enumCode="Word (.doc)"/>
+    <Enumeration enumId="FB_PPT" enumTypeId="FLEXIBLE_BIRT" description="application/vnd.ms-powerpoint" sequenceId="12" enumCode="Powerpoint (.ppt)"/>
+</entity-engine-xml>
\ No newline at end of file

Added: ofbiz/trunk/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy (added)
+++ ofbiz/trunk/plugins/birt/groovyScripts/report/PrepareBirtCall.groovy Sat Jan 28 13:22:55 2017
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+def birtParameters = [:];
+
+birtParameters.parameters = parameters
+birtParameters.modelElementName = parameters.modelElementName
+birtParameters.userLogin = context.userLogin
+birtParameters.locale = locale
+
+request.setAttribute("birtParameters", birtParameters);
+return "success";

Added: ofbiz/trunk/plugins/birt/minilang/BirtPermissionServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/minilang/BirtPermissionServices.xml?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/minilang/BirtPermissionServices.xml (added)
+++ ofbiz/trunk/plugins/birt/minilang/BirtPermissionServices.xml Sat Jan 28 13:22:55 2017
@@ -0,0 +1,106 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+
+<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
+
+    <simple-method method-name="genericBirtPermission" short-description="Generic Service for Birt Permissions">
+        <set field="primaryPermission" value="BIRT"/>
+        <call-simple-method method-name="genericBasePermissionCheck" xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+
+        <!-- mainAction based call outs -->
+        <if>
+            <condition>
+                <not>
+                    <if-compare field="hasPermission" value="true" type="Boolean" operator="equals"/>
+                </not>
+            </condition>
+            <then>
+                <if>
+                    <!-- view data resource -->
+                    <condition>
+                        <if-compare field="parameters.mainAction" value="VIEW" operator="equals"/>
+                    </condition>
+                    <then>
+                        <call-simple-method method-name="viewBirtPermission"/>
+                    </then>
+                    <else-if>
+                        <!-- create data resource -->
+                        <condition>
+                            <if-compare field="parameters.mainAction" value="CREATE" operator="equals"/>
+                        </condition>
+                        <then>
+                            <call-simple-method method-name="createBirtPermission"/>
+                        </then>
+                    </else-if>
+                    <else-if>
+                        <!-- update data resource -->
+                        <condition>
+                            <if-compare field="parameters.mainAction" value="UPDATE" operator="equals"/>
+                        </condition>
+                        <then>
+                            <call-simple-method method-name="updateBirtPermission"/>
+                        </then>
+                    </else-if>
+                    <!-- all other actions use main base check -->
+                </if>
+            </then>
+            <else>
+                <log level="info" message="Admin permission found: ${primaryPermission}_${mainAction}"/>
+            </else>
+        </if>
+
+        <log level="info" message="Permission service [${mainAction} / ${parameters.contentId}] completed; returning hasPermission = ${hasPermission}"/>
+        <field-to-result field="hasPermission"/>
+    </simple-method>
+
+    <!-- Birt View Permission -->
+    <simple-method method-name="viewBirtPermission" short-description="Check user can view Birt reports">
+        <!-- if called directly check the main permission -->
+        <if-empty field="hasPermission">
+            <set field="primaryPermission" value="BIRT"/>
+            <set field="mainAction" value="VIEW"/>
+            <call-simple-method method-name="genericBasePermissionCheck"
+                                xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+        </if-empty>
+    </simple-method>
+
+    <!-- Birt Create Permission -->
+    <simple-method method-name="createBirtPermission" short-description="Check user can create new Birt report">
+        <!-- if called directly check the main permission -->
+        <if-empty field="hasPermission">
+            <set field="primaryPermission" value="BIRT"/>
+            <set field="mainAction" value="CREATE"/>
+            <call-simple-method method-name="genericBasePermissionCheck"
+                                xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+        </if-empty>
+        <!-- this is about the same as the VIEW permission; but left as a unique service for extending purposes -->
+    </simple-method>
+
+    <!-- Birt Update Permission -->
+    <simple-method method-name="updateBirtPermission" short-description="Check user can update existing Birt report">
+        <!-- if called directly check the main permission -->
+        <if-empty field="hasPermission">
+            <set field="primaryPermission" value="BIRT"/>
+            <set field="mainAction" value="UPDATE"/>
+            <call-simple-method method-name="genericBasePermissionCheck"
+                                xml-resource="component://common/minilang/permission/CommonPermissionServices.xml"/>
+        </if-empty>
+    </simple-method>
+</simple-methods>
\ No newline at end of file

Modified: ofbiz/trunk/plugins/birt/ofbiz-component.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/ofbiz-component.xml?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/ofbiz-component.xml (original)
+++ ofbiz/trunk/plugins/birt/ofbiz-component.xml Sat Jan 28 13:22:55 2017
@@ -26,7 +26,10 @@ under the License.
 
     <classpath type="dir" location="config"/>
     <entity-resource type="data" reader-name="seed" loader="main" location="data/BirtHelpData.xml"/>
-    <entity-resource type="data" reader-name="seed" loader="main" location="data/OrderPortletData.xml"/>
+    <entity-resource type="data" reader-name="seed" loader="main" location="data/BirtTypeData.xml"/>
+    <entity-resource type="data" reader-name="demo" loader="main" location="data/BirtSecurityGroupDemoData.xml"/>
+    <entity-resource type="data" reader-name="demo" loader="main" location="data/BirtMasterData.xml"/>
+
     <service-resource type="model" loader="main" location="servicedef/services.xml"/>
   
     <webapp name="accounting"

Modified: ofbiz/trunk/plugins/birt/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/servicedef/services.xml?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/servicedef/services.xml (original)
+++ ofbiz/trunk/plugins/birt/servicedef/services.xml Sat Jan 28 13:22:55 2017
@@ -35,8 +35,132 @@ under the License.
         <attribute name="bodyParameters" type="Map" mode="IN" optional="true"/>
         <attribute name="birtParameters" type="Map" mode="IN" optional="true"/>
         <attribute name="birtLocale" type="Locale" mode="IN" optional="true"/>
-        <attribute name="birtContentType" type="String" mode="IN" optional="true"></attribute>
+        <attribute name="birtContentType" type="String" mode="IN" optional="true"/>
         <attribute name="webSiteId" type="String" mode="IN" optional="true"/>
         <attribute name="body" type="String" mode="OUT" optional="false"/>
     </service>
+
+    <!-- SERVICES FOR REPORTS -->
+    <service name="genericBirtPermission" engine="simple" auth="true"
+            location="component://birt/minilang/BirtPermissionServices.xml" invoke="genericBirtPermission">
+        <description>Generic Birt Permission Service; Takes mainAction to determine the mode.</description>
+        <implements service="permissionInterface"/>
+    </service>
+
+    <!-- Interfaces -->
+    <service name="createFlexibleReportFromMasterInterface" engine="interface">
+        <attribute name="reportName" type="String" mode="IN" optional="false" />
+        <attribute name="description" type="String" mode="IN" optional="true" />
+        <attribute name="writeFilters" type="String" mode="IN" optional="true" />
+        <attribute name="masterContentId" type="String" mode="IN" optional="false" />
+        <attribute name="contentId" type="String" mode="OUT" optional="false" />
+    </service>
+    <service name="prepareFieldsForFlexibleReportInterface" engine="interface">
+        <attribute name="dataMap" type="Map" mode="OUT" optional="false" />
+        <attribute name="fieldDisplayLabels" type="Map" mode="OUT" optional="true"/>
+        <attribute name="filterMap" type="Map" mode="OUT" optional="true" />
+        <attribute name="filterDisplayLabels" type="Map" mode="OUT" optional="true"/>
+    </service>
+    <service name="searchRecordsForFlexibleReportInterface" engine="interface">
+        <attribute name="reportContext" type="Object" mode="IN" optional="false" />
+        <attribute name="records" type="List" mode="OUT" />
+    </service>
+
+    <service name="createFlexibleReport" engine="java" auth="true" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReport">
+        <description>BIRT report generation</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <attribute name="dataMap" type="Map" mode="IN" optional="false" />
+        <attribute name="fieldDisplayLabels" type="Map" mode="IN" optional="true" />
+        <attribute name="filterMap" type="Map" mode="IN" optional="true" />
+        <attribute name="filterDisplayLabels" type="Map" mode="IN" optional="true" />
+        <attribute name="writeFilters" type="String" mode="IN" optional="true" />
+        <attribute name="serviceName" type="String" mode="IN" optional="false" />
+        <attribute name="rptDesignName" type="String" mode="IN" optional="false" />
+    </service>
+
+    <service name="createFlexibleReportFromMaster" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReportFromMaster">
+        <description>Call report generator with appropriate workflow required by the given master report</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <attribute name="contentId" type="String" mode="IN" optional="false" />
+        <attribute name="reportName" type="String" mode="IN" optional="false" />
+        <attribute name="description" type="String" mode="IN" optional="false" />
+        <attribute name="writeFilters" type="String" mode="IN" optional="true" />
+        <attribute name="reportContentId" type="String" mode="OUT" optional="false"/>
+        <attribute name="textForm" type="String" mode="OUT" optional="false" allow-html="any"/>
+    </service>
+    <service name="createFlexibleReportFromMasterEntityWorkflow" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReportFromMasterEntityWorkflow">
+        <description>Create and save in db content, a new report design following entity workflow</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <implements service="createFlexibleReportFromMasterInterface"/>
+        <attribute name="entityViewName" type="String" mode="IN" optional="false" />
+    </service>
+    <service name="createFlexibleReportFromMasterServiceWorkflow" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFlexibleReportFromMasterServiceWorkflow">
+        <description>Create and save in db content, a new report following service workflow</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <implements service="createFlexibleReportFromMasterInterface"/>
+        <attribute name="serviceName" type="String" mode="IN" optional="false" />
+    </service>
+    <service name="deleteAllFlexibleReports" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="deleteAllReports">
+        <description>Delete all reports (admin purposes)</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_DELETE"/></required-permissions>
+    </service>
+    <service name="deleteFlexibleReport" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="deleteFlexibleReport">
+        <description>Delete a report</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_DELETE"/></required-permissions>
+        <attribute name="contentId" type="String" mode="IN" optional="false" />
+    </service>
+
+    <service name="prepareFlexibleReportOptionFieldsFromEntity" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="prepareFlexibleReportOptionFieldsFromEntity">
+        <description>Get fields corresponding to an entity or view, including _op _value and so on depending on type.</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <attribute name="entityViewName" type="String" mode="IN" optional="false" />
+        <attribute name="listMultiFields" type="List" mode="OUT" optional="false" />
+    </service>
+    <service name="prepareFlexibleReportFieldsFromEntity" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="prepareFlexibleReportFieldsFromEntity">
+        <description>prepare maps fields for ReportDesignGenerator</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_CREATE"/></required-permissions>
+        <implements service="prepareFieldsForFlexibleReportInterface"/>
+        <attribute name="modelEntity" mode="IN" type="Object"/>
+    </service>
+
+    <service name="uploadFlexibleReportRptDesign" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="uploadRptDesign">
+        <description>Upload design-modified rptdesign file</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_UPDATE"/></required-permissions>
+        <attribute name="dataResourceIdRpt" type="String" mode="IN" optional="false" />
+        <attribute name="uploadRptDesign" type="java.nio.ByteBuffer" mode="IN" optional="false" />
+    </service>
+
+    <service name="updateFlexibleReportSearchForm" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="overrideReportForm">
+        <description>Override report form</description>
+        <required-permissions join-type="OR">
+            <check-permission permission="BIRT_CREATE"/>
+            <check-permission permission="BIRT_UPDATE"/>
+        </required-permissions>
+        <attribute name="reportContentId" type="String" mode="IN" optional="false" />
+        <attribute name="overrideFilters" type="String" mode="IN" optional="true" allow-html="any"/>
+    </service>
+    <service name="prepareFlexibleReportSearchFormToEdit" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="createFormForDisplay">
+        <description>Prepare from DB report form for display</description>
+        <required-permissions join-type="OR">
+            <check-permission permission="BIRT_CREATE"/>
+            <check-permission permission="BIRT_UPDATE"/>
+        </required-permissions>
+        <attribute name="reportContentId" type="String" mode="IN" optional="false" />
+        <attribute name="textForm" type="String" mode="OUT" optional="false" allow-html="any"/>
+    </service>
+
+    <!-- Service example for flexible report-->
+    <service name="callPerformFindFromBirt" engine="java" auth="true" location="org.apache.ofbiz.birt.flexible.BirtServices" invoke="callPerformFindFromBirt" transaction-timeout="7200">
+        <description>Manages performFind calling from Birt. Flexible Report from entity workflow. (Default search service)</description>
+        <required-permissions join-type="AND"><check-permission permission="BIRT_VIEW"/></required-permissions>
+        <implements service="searchRecordsForFlexibleReportInterface"/>
+    </service>
+    <service name="flexibleReportTurnOver" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtMasterReportServices" invoke="turnOver">
+        <description>Service getting data for report. Turnover report</description>
+        <implements service="searchRecordsForFlexibleReportInterface"/>
+    </service>
+    <service name="flexibleReportTurnOverPrepareFields" auth="true" engine="java" location="org.apache.ofbiz.birt.flexible.BirtMasterReportServices" invoke="turnOverPrepareFields">
+        <description>Service configuring data for report (works in duo!). Turnover report.</description>
+        <implements service="prepareFieldsForFlexibleReportInterface"/>
+    </service>
 </services>

Modified: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java?rev=1780683&r1=1780682&r2=1780683&view=diff
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java (original)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/BirtWorker.java Sat Jan 28 13:22:55 2017
@@ -18,8 +18,12 @@
  *******************************************************************************/
 package org.apache.ofbiz.birt;
 
+import java.io.File;
+import java.io.IOException;
 import java.io.OutputStream;
+import java.io.StringWriter;
 import java.sql.SQLException;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -28,6 +32,21 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.GeneralException;
+import org.apache.ofbiz.base.util.UtilGenerics;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
+import org.apache.ofbiz.birt.flexible.BirtUtil;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.service.GenericServiceException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.apache.ofbiz.webapp.WebAppUtil;
 import org.eclipse.birt.report.engine.api.EXCELRenderOption;
 import org.eclipse.birt.report.engine.api.EngineException;
 import org.eclipse.birt.report.engine.api.HTMLRenderOption;
@@ -38,13 +57,6 @@ import org.eclipse.birt.report.engine.ap
 import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
 import org.eclipse.birt.report.engine.api.PDFRenderOption;
 import org.eclipse.birt.report.engine.api.RenderOption;
-import org.apache.ofbiz.base.util.Debug;
-import org.apache.ofbiz.base.util.GeneralException;
-import org.apache.ofbiz.base.util.UtilGenerics;
-import org.apache.ofbiz.base.util.UtilValidate;
-import org.apache.ofbiz.entity.Delegator;
-import org.apache.ofbiz.security.Security;
-import org.apache.ofbiz.service.LocalDispatcher;
 
 public final class BirtWorker {
 
@@ -55,10 +67,11 @@ public final class BirtWorker {
     private final static String BIRT_IMAGE_DIRECTORY = "birtImageDirectory";
     private final static String BIRT_CONTENT_TYPE = "birtContentType";
     private final static String BIRT_OUTPUT_FILE_NAME = "birtOutputFileName";
+    private static final String resourceError = "BirtErrorUiLabels";
 
     private final static HTMLServerImageHandler imageHandler = new HTMLServerImageHandler();
 
-    private BirtWorker () {}
+    private BirtWorker() {}
 
     /**
      * export report
@@ -71,16 +84,18 @@ public final class BirtWorker {
      * @throws SQLException
      */
     public static void exportReport(IReportRunnable design, Map<String, ? extends Object> context, String contentType, OutputStream output)
-        throws EngineException, GeneralException, SQLException {
+            throws EngineException, GeneralException, SQLException {
 
-        Locale birtLocale = (Locale)context.get(BIRT_LOCALE);
-        String birtImageDirectory = (String)context.get(BIRT_IMAGE_DIRECTORY);
+        Locale birtLocale = (Locale) context.get(BIRT_LOCALE);
+        String birtImageDirectory = (String) context.get(BIRT_IMAGE_DIRECTORY);
 
         if (contentType == null) {
             contentType = "text/html";
+        } else {
+            contentType = contentType.toLowerCase();
         }
         if (birtImageDirectory == null) {
-             birtImageDirectory = "/";
+            birtImageDirectory = "/";
         }
         Debug.logInfo("Get report engine", module);
         IReportEngine engine = BirtFactory.getReportEngine();
@@ -92,107 +107,65 @@ public final class BirtWorker {
         }
 
         // set parameters if exists
-        Map<String, Object> parameters = UtilGenerics.cast(context.get(BirtWorker.BIRT_PARAMETERS));
+        Map<String, Object> parameters = UtilGenerics.cast(context.get(BirtWorker.getBirtParameters()));
         if (parameters != null) {
-            Debug.logInfo("Set BIRT parameters:" + parameters, module);
+            //Debug.logInfo("Set BIRT parameters:" + parameters, module);
             task.setParameterValues(parameters);
         }
 
         // set output options
+        if (! BirtUtil.isSupportedMimeType(contentType)) {
+            throw new GeneralException("Unknown content type : " + contentType);
+        }
         RenderOption options = new RenderOption();
-        if ("text/html".equalsIgnoreCase(contentType)) { // HTML
-            options.setOutputFormat(RenderOption.OUTPUT_FORMAT_HTML);
+        options.setOutputFormat(BirtUtil.getMimeTypeOutputFormat(contentType));
+
+        //specific process for mimetype
+        if ("text/html".equals(contentType)) { // HTML
             HTMLRenderOption htmlOptions = new HTMLRenderOption(options);
             htmlOptions.setImageDirectory(birtImageDirectory);
             htmlOptions.setBaseImageURL(birtImageDirectory);
             options.setImageHandler(imageHandler);
-        } else if ("application/postscript".equalsIgnoreCase(contentType)) { // Post Script
-            options.setOutputFormat("postscript");
-        } else if ("application/pdf".equalsIgnoreCase(contentType)) { // PDF
-            options.setOutputFormat(RenderOption.OUTPUT_FORMAT_PDF);
+        } else if ("application/pdf".equals(contentType)) { // PDF
             PDFRenderOption pdfOptions = new PDFRenderOption(options);
-            pdfOptions.setOption(IPDFRenderOption.PAGE_OVERFLOW, Boolean.TRUE );
-        } else if ("application/vnd.ms-word".equalsIgnoreCase(contentType)) { // MS Word
-            options.setOutputFormat("doc");
-        }  else if ("application/vnd.ms-excel".equalsIgnoreCase(contentType)) { // MS Excel
-            options.setOutputFormat("xls");
+            pdfOptions.setOption(IPDFRenderOption.PAGE_OVERFLOW, Boolean.TRUE);
+        } else if ("application/vnd.ms-excel".equals(contentType)) { // MS Excel
             new EXCELRenderOption(options);
-        } else if ("application/vnd.ms-powerpoint".equalsIgnoreCase(contentType)) { // MS Power Point
-            options.setOutputFormat("ppt");
-        } else if ("application/vnd.oasis.opendocument.text".equalsIgnoreCase(contentType)) { // Open Document Text
-            options.setOutputFormat("odt");
-        } else if ("application/vnd.oasis.opendocument.spreadsheet".equalsIgnoreCase(contentType)) { // Open Document Spreadsheet
-            options.setOutputFormat("ods");
-        } else if ("application/vnd.oasis.opendocument.presentation".equalsIgnoreCase(contentType)) { // Open Document Presentation
-            options.setOutputFormat("odp");
-        } else if ("application/vnd.openxmlformats-officedocument.wordprocessingml.document".equalsIgnoreCase(contentType)) { // MS Word 2007
-            options.setOutputFormat("docx");
-        } else if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equalsIgnoreCase(contentType)) { // MS Excel 2007
-            options.setOutputFormat("xlsx");
-        } else if ("application/vnd.openxmlformats-officedocument.presentationml.presentation".equalsIgnoreCase(contentType)) { // MS Word 2007
-            options.setOutputFormat("pptx");
-        } else {
-            throw new GeneralException("Unknown content type : " + contentType);
         }
 
         options.setOutputStream(output);
         task.setRenderOption(options);
 
         // run report
-        Debug.logInfo("BIRT's locale is: " + task.getLocale(), module);
-        Debug.logInfo("Run report's task", module);
+        if (Debug.infoOn()) {
+            Debug.logInfo("BIRT's locale is: " + task.getLocale(), module);
+            Debug.logInfo("Run report's task", module);
+        }
         task.run();
         task.close();
     }
-    
+
     /**
      * set web context objects
      * @param appContext
      * @param request
      * @param response
      */
-    public static void setWebContextObjects(Map<String, Object> appContext, HttpServletRequest request, HttpServletResponse response) {
+    public static void setWebContextObjects(Map<String, Object> appContext, HttpServletRequest request, HttpServletResponse response)
+    throws GeneralException {
         HttpSession session = request.getSession();
         ServletContext servletContext = session.getServletContext();
-        
-        // set delegator
-        Delegator delegator = (Delegator) session.getAttribute("delegator");
-        if (UtilValidate.isEmpty(delegator)) {
-            delegator = (Delegator) servletContext.getAttribute("delegator");
-        }
-        if (UtilValidate.isEmpty(delegator)) {
-            delegator = (Delegator) request.getAttribute("delegator");
-        }
-        if (UtilValidate.isNotEmpty(delegator)) {
-            appContext.put("delegator", delegator);
-        }
 
-        // set JDBC connection
-        //appContext.put("OdaJDBCDriverPassInConnection", connection);
-
-        // set dispatcher
-        LocalDispatcher dispatcher = (LocalDispatcher) session.getAttribute("dispatcher");
-        if (UtilValidate.isEmpty(dispatcher)) {
-            dispatcher = (LocalDispatcher) servletContext.getAttribute("dispatcher");
-        }
-        if (UtilValidate.isEmpty(dispatcher)) {
-            dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
-        }
-        if (UtilValidate.isNotEmpty(dispatcher)) {
-            appContext.put("dispatcher", dispatcher);
+        if (appContext == null || servletContext == null) {
+            throw new GeneralException("The context reporting is empty, check your configuration");
         }
 
-        // set security
-        Security security = (Security) session.getAttribute("security");
-        if (UtilValidate.isEmpty(security)) {
-            security = (Security) servletContext.getAttribute("security");
-        }
-        if (UtilValidate.isEmpty(security)) {
-            security = (Security) request.getAttribute("security");
-        }
-        if (UtilValidate.isNotEmpty(security)) {
-            appContext.put("security", security);
-        }
+        // initialize the delegator
+        appContext.put("delegator", WebAppUtil.getDelegator(servletContext));
+        // initialize security
+        appContext.put("security", WebAppUtil.getSecurity(servletContext));
+        // initialize the services dispatcher
+        appContext.put("dispatcher", WebAppUtil.getDispatcher(servletContext));
     }
 
     public static String getBirtParameters () {
@@ -214,4 +187,93 @@ public final class BirtWorker {
     public static String getBirtOutputFileName () {
         return BIRT_OUTPUT_FILE_NAME;
     }
+
+    //TODO documentation
+    public static String recordReportContent(Delegator delegator, LocalDispatcher dispatcher, Map<String, Object> context) throws GeneralException {
+        Locale locale = (Locale) context.get("locale");
+        String description = (String) context.get("description");
+        String reportName = (String) context.get("reportName");
+        String writeFilters = (String) context.get("writeFilters");
+        GenericValue userLogin = (GenericValue) context.get("userLogin");
+        String entityViewName = (String) context.get("entityViewName");
+        String serviceName = (String) context.get("serviceName");
+        String masterContentId = (String) context.get("masterContentId");
+        String dataResourceId = delegator.getNextSeqId("DataResource");
+        String contentId = delegator.getNextSeqId("Content");
+        context.put("contentId", contentId);
+
+        if (UtilValidate.isEmpty(serviceName) && UtilValidate.isEmpty(entityViewName)) {
+            throw new GenericServiceException("Service and entity name cannot be both empty");
+        }
+
+        String modelType = null;
+        String modelElementName = null;
+        String workflowType = null;
+        if (UtilValidate.isEmpty(serviceName)) {
+            modelElementName = entityViewName;
+            workflowType = "Entity";
+        } else {
+            modelElementName = serviceName;
+            workflowType = "Service";
+        }
+
+        //resolve the path location to store the RptDesign file, check if the file already exists under this name and increment index name if needed
+        List<GenericValue> listRptDesigns = null;
+        EntityCondition entityConditionRpt = EntityCondition.makeCondition("contentTypeId", "RPTDESIGN");
+        String templatePathLocation = BirtUtil.resolveTemplatePathLocation();
+        File templatePathLocationDir = new File(templatePathLocation);
+            if (!templatePathLocationDir.exists()) {
+                boolean created = templatePathLocationDir.mkdirs();
+                if (!created) {
+                    new GeneralException(UtilProperties.getMessage(resourceError, "BirtErrorCannotLocateReportFolder", locale));
+                }
+            }
+        int i = 0;
+        String templateFileLocation = null;
+        EntityCondition ecl = null;
+        do {
+            StringBuffer rptDesignNameSb = new StringBuffer(templatePathLocation);
+            rptDesignNameSb.append(BirtUtil.encodeReportName(reportName));
+            rptDesignNameSb.append("_").append(i);
+            rptDesignNameSb.append(".rptdesign");
+            templateFileLocation = rptDesignNameSb.toString();
+            EntityCondition entityConditionOnName = EntityCondition.makeCondition("drObjectInfo", templateFileLocation);
+            ecl = EntityCondition.makeCondition(UtilMisc.toList(entityConditionRpt, entityConditionOnName));
+            i++;
+        } while (delegator.findCountByCondition("ContentDataResourceView", ecl, null, null) > 0);
+
+        //resolve the initial form structure from master content
+        Map<String, Object> resultElectronicText = dispatcher.runSync("getElectronicText", UtilMisc.toMap("contentId", masterContentId, "locale", locale, "userLogin", userLogin));
+        if (ServiceUtil.isError(resultElectronicText)) {
+            new GeneralException(ServiceUtil.getErrorMessage(resultElectronicText));
+        }
+        String reportForm = (String) resultElectronicText.get("textData");
+        if (! reportForm.startsWith("<?xml")) {
+            StringBuffer xmlHeaderForm = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+            xmlHeaderForm.append("<forms xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://ofbiz.apache.org/dtds/widget-form.xsd\">");
+            xmlHeaderForm.append(reportForm);
+            xmlHeaderForm.append("</forms>");
+            reportForm = xmlHeaderForm.toString();
+        }
+        FlexibleStringExpander reportFormExpd = FlexibleStringExpander.getInstance(reportForm);
+        reportForm = reportFormExpd.expandString(context);
+
+        //create content and dataressource strucutre
+        dispatcher.runSync("createDataResource", UtilMisc.toMap("dataResourceId", dataResourceId, "dataResourceTypeId", "ELECTRONIC_TEXT", "dataTemplateTypeId", "FORM_COMBINED", "userLogin", userLogin));
+        dispatcher.runSync("createElectronicTextForm", UtilMisc.toMap("dataResourceId", dataResourceId, "textData", reportForm, "userLogin", userLogin));
+        dispatcher.runSync("createContent", UtilMisc.toMap("contentId", contentId, "contentTypeId", "FLEXIBLE_REPORT", "dataResourceId", dataResourceId, "statusId", "CTNT_IN_PROGRESS", "contentName", reportName, "description", description, "userLogin", userLogin));
+        String dataResourceIdRpt = delegator.getNextSeqId("DataResource");
+        String contentIdRpt = delegator.getNextSeqId("Content");
+        String rptDesignName = BirtUtil.encodeReportName(reportName);
+        if (! rptDesignName.endsWith(".rptdesign")) {
+            rptDesignName = rptDesignName.concat(".rptdesign");
+        }
+        dispatcher.runSync("createDataResource", UtilMisc.toMap("dataResourceId", dataResourceIdRpt, "dataResourceTypeId", "LOCAL_FILE", "mimeTypeId", "text/rptdesign", "dataResourceName", rptDesignName, "objectInfo", templateFileLocation, "userLogin", userLogin));
+        dispatcher.runSync("createContent", UtilMisc.toMap("contentId", contentIdRpt, "contentTypeId", "RPTDESIGN", "dataResourceId", dataResourceIdRpt, "statusId", "CTNT_PUBLISHED", "contentName", reportName, "description", description + " (.rptDesign file)", "userLogin", userLogin));
+        dispatcher.runSync("createContentAssoc", UtilMisc.toMap("contentId", masterContentId, "contentIdTo", contentId, "contentAssocTypeId", "SUB_CONTENT", "userLogin", userLogin));
+        dispatcher.runSync("createContentAssoc", UtilMisc.toMap("contentId", contentId, "contentIdTo", contentIdRpt, "contentAssocTypeId", "SUB_CONTENT", "userLogin", userLogin));
+        dispatcher.runSync("createContentAttribute", UtilMisc.toMap("contentId", contentId, "attrName", workflowType, "attrValue", modelElementName, "userLogin", userLogin));
+        return contentId;
+    }
+
 }

Added: ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java?rev=1780683&view=auto
==============================================================================
--- ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java (added)
+++ ofbiz/trunk/plugins/birt/src/main/java/org/apache/ofbiz/birt/flexible/BirtMasterReportServices.java Sat Jan 28 13:22:55 2017
@@ -0,0 +1,294 @@
+package org.apache.ofbiz.birt.flexible;
+
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ofbiz.base.util.UtilDateTime;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.entity.condition.EntityExpr;
+import org.apache.ofbiz.entity.condition.EntityOperator;
+import org.apache.ofbiz.entity.util.EntityUtil;
+import org.apache.ofbiz.party.party.PartyHelper;
+import org.apache.ofbiz.service.DispatchContext;
+import org.apache.ofbiz.service.ServiceUtil;
+import org.eclipse.birt.report.engine.api.script.IReportContext;
+
+public class BirtMasterReportServices {
+
+    public static final String module = BirtServices.class.getName();
+    public static final String resource = "BirtUiLabels";
+    public static final String resource_error = "BirtErrorUiLabels";
+
+    // The following funtion are flexible service as example for reporting
+    public static Map<String, Object> workEffortPerPersonPrepareDate(DispatchContext dctx, Map<String, Object> context) {
+        Map<String, String> dataMap = UtilMisc.toMap("lastName", "name", "firstName", "name", "hours", "floating-point", "fromDate", "date-time", "thruDate", "date-time");
+        LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
+        filterMap.put("firstName", "name");
+        filterMap.put("lastName", "name");
+        filterMap.put("fromDate", "date-time");
+        filterMap.put("thruDate", "date-time");
+        Map<String, String> fieldDisplayLabels = UtilMisc.toMap("lastName", "Last name", "firstName", "First name", "hours", "Hours", "fromDate", "From date", "thruDate", "Thru date");
+        LinkedHashMap<String, String> filterDisplayLabels = new LinkedHashMap<String, String>();
+        filterDisplayLabels.put("firstName", "First name");
+        filterDisplayLabels.put("lastName", "Last name");
+        filterDisplayLabels.put("fromDate", "From date");
+        filterDisplayLabels.put("thruDate", "Thru date");
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("dataMap", dataMap);
+        result.put("filterMap", filterMap);
+        result.put("fieldDisplayLabels", fieldDisplayLabels);
+        result.put("filterDisplayLabels", filterDisplayLabels);
+        return result;
+    }
+
+    public static Map<String, Object> workEffortPerPerson(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = (Delegator) dctx.getDelegator();
+        IReportContext reportContext = (IReportContext) context.get("reportContext");
+        Map<String, Object> parameters = (Map<String, Object>) reportContext.getParameterValue("parameters");
+        List<GenericValue> listWorkEffortTime = null;
+
+        if (UtilValidate.isEmpty(parameters.get("firstName")) && UtilValidate.isEmpty(parameters.get("lastName"))) {
+            return ServiceUtil.returnError("First and last name can not be both empty");
+        }
+        List<GenericValue> listPersons = null;
+        try {
+            // TODO: translate labels
+            List<EntityExpr> listConditions = new ArrayList<EntityExpr>();
+            if (UtilValidate.isNotEmpty(parameters.get("firstName"))) {
+                EntityExpr conditionFirstName = EntityCondition.makeCondition("firstName", parameters.get("firstName"));
+                listConditions.add(conditionFirstName);
+            }
+            if (UtilValidate.isNotEmpty(parameters.get("lastName"))) {
+                EntityExpr conditionLastName = EntityCondition.makeCondition("lastName", parameters.get("lastName"));
+                listConditions.add(conditionLastName);
+            }
+            EntityCondition ecl = EntityCondition.makeCondition(listConditions, EntityOperator.AND);
+            listPersons = delegator.findList("Person", ecl, UtilMisc.toSet("partyId", "firstName", "lastName"), null, null, true);
+            GenericValue person = null;
+            if (listPersons.size() > 1) {
+                return ServiceUtil.returnError("Your criteria match with several people");
+            } else if (listPersons.size() == 1) {
+                person = listPersons.get(0);
+            } else {
+                return ServiceUtil.returnError("Could not find this person");
+            }
+            String partyId = person.getString("partyId");
+
+            List<EntityExpr> listConditionsWorkEffort = new ArrayList<EntityExpr>();
+            Timestamp thruDate = null;
+            Timestamp fromDate = null;
+            if (UtilValidate.isEmpty(parameters.get("fromDate"))) {
+                return ServiceUtil.returnError("The starting date is mandatory");
+            } else {
+                fromDate = Timestamp.valueOf((String) parameters.get("fromDate"));
+                EntityExpr conditionFromDate = EntityCondition.makeCondition("fromDate", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate);
+                listConditionsWorkEffort.add(conditionFromDate);
+            }
+            if (UtilValidate.isEmpty(parameters.get("thruDate"))) {
+                thruDate = UtilDateTime.nowTimestamp();
+            } else {
+                thruDate = Timestamp.valueOf((String) parameters.get("thruDate"));
+            }
+            EntityExpr conditionThruDate = EntityCondition.makeCondition("thruDate", EntityOperator.LESS_THAN_EQUAL_TO, thruDate);
+            listConditionsWorkEffort.add(conditionThruDate);
+            EntityExpr conditionParty = EntityCondition.makeCondition("partyId", partyId);
+            listConditionsWorkEffort.add(conditionParty);
+            ecl = EntityCondition.makeCondition(listConditionsWorkEffort, EntityOperator.AND);
+            listWorkEffortTime = delegator.findList("WorkEffortAndTimeEntry", ecl, UtilMisc.toSet("hours", "fromDate", "thruDate"), null, null, true);
+        } catch (GenericEntityException e) {
+            e.printStackTrace();
+            ServiceUtil.returnError("Error getting party from person name.");
+        }
+        List<GenericValue> listCompiled = new ArrayList<GenericValue>();
+        if (UtilValidate.isNotEmpty(listWorkEffortTime)) listCompiled.addAll(listWorkEffortTime);
+        if (UtilValidate.isNotEmpty(listPersons)) listCompiled.addAll(listPersons);
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("records", listCompiled);
+        return result;
+    }
+
+    public static Map<String, Object> turnOverPrepareFields(DispatchContext dctx, Map<String, Object> context) {
+        Map<String, String> dataMap = UtilMisc.toMap("invoiceTypeId", "short-varchar", "invoicePartyId", "short-varchar", "statusId", "short-varchar", "invoiceDate", "date", "dueDate", "date", "currencyUomId", "short-varchar", "invoiceItemTypeId", "short-varchar", "invoiceItemSeqId", "short-varchar", "productId", "short-varchar", "partyId", "short-varchar", "partyName", "short-varchar", "primaryProductCategoryId", "short-varchar", "quantity", "numeric", "amount", "currency-amount", "productStoreId", "short-varchar", "storeName", "short-varchar");
+        Map<String, String> fieldDisplayLabels = UtilMisc.toMap("invoiceTypeId", "invoice Type", "invoicePartyId", "Invoice", "statusId", "Status", "invoiceDate", "Date", "dueDate", "Due date ", "currencyUomId", "Currency", "invoiceItemTypeId", "Invoice type line", "invoiceItemSeqId", "Invoice line", "productId", "Product", "partyId", "Customer", "partyName", "Customer name", "primaryProductCategoryId", "Product category", "quantity", "Qty", "amount", "Montant", "productStoreId", "Product Store", "storeName", "Product store name");
+        LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
+        filterMap.put("productCategoryId", "short-varchar");
+        filterMap.put("productStoreId", "short-varchar");
+        filterMap.put("fromDate", "date");
+        filterMap.put("thruDate", "date");
+        LinkedHashMap<String, String> filterDisplayLabels = new LinkedHashMap<String, String>();
+        //it's better to use Label Map, maybe an improvement point !
+        filterDisplayLabels.put("productCategoryId", "product Category");
+        filterDisplayLabels.put("productStoreId", "product Store");
+        filterDisplayLabels.put("fromDate", "from Date");
+        filterDisplayLabels.put("thruDate", "through Date");
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("dataMap", dataMap);
+        result.put("filterMap", filterMap);
+        result.put("fieldDisplayLabels", fieldDisplayLabels);
+        result.put("filterDisplayLabels", filterDisplayLabels);
+        return result;
+    }
+
+    public static Map<String, Object> turnOver(DispatchContext dctx, Map<String, Object> context) {
+        Delegator delegator = (Delegator) dctx.getDelegator();
+        Locale locale = (Locale) context.get("locale");
+        IReportContext reportContext = (IReportContext) context.get("reportContext");
+        Map<String, Object> parameters = (Map<String, Object>) reportContext.getParameterValue("parameters");
+
+        List<GenericValue> listTurnOver = null;
+        List<Map<String, Object>> listInvoiceEditable = new ArrayList<Map<String, Object>>();
+        List<EntityCondition> listAllConditions = new ArrayList<EntityCondition>();
+        try {
+            // treating fromDate field condition
+            if (UtilValidate.isNotEmpty(parameters.get("fromDate"))) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                String fromDateString = (String) parameters.get("fromDate");
+                Timestamp fromDate = new Timestamp(sdf.parse(fromDateString).getTime());
+                EntityExpr conditionFromDate = EntityCondition.makeCondition("invoiceDate", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate);
+                listAllConditions.add(conditionFromDate);
+            }
+
+            // treating throughDate field condition
+            if (UtilValidate.isNotEmpty(parameters.get("throughDate"))) {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                String throughDateString = (String) parameters.get("throughDate");
+                Timestamp throughDate = new Timestamp(sdf.parse(throughDateString).getTime());
+                EntityExpr conditionThroughDate = EntityCondition.makeCondition("invoiceDate", EntityOperator.LESS_THAN_EQUAL_TO, throughDate);
+                listAllConditions.add(conditionThroughDate);
+            }
+
+            // product category field condition
+            if (UtilValidate.isNotEmpty(parameters.get("productCategoryId"))) {
+                List<String> productCategoryList = new ArrayList<String>();
+                if (parameters.get("productCategoryId") instanceof String) {
+                    String productCategoryId = (String) parameters.get("productCategoryId");
+                    productCategoryList.add(productCategoryId);
+                } else {
+                    productCategoryList = (List<String>) parameters.get("productCategoryId");
+                }
+                // getting productIds in these categories
+                EntityExpr conditionProductCategory = EntityCondition.makeCondition("primaryProductCategoryId", EntityOperator.IN, productCategoryList);
+                EntityExpr conditionFromDate = EntityCondition.makeCondition("fromDate", EntityOperator.GREATER_THAN_EQUAL_TO, UtilDateTime.nowTimestamp());
+                EntityExpr conditionBeforeDate = EntityCondition.makeCondition("thruDate", EntityOperator.LESS_THAN_EQUAL_TO, UtilDateTime.nowTimestamp());
+                EntityExpr conditionNull = EntityCondition.makeCondition("thruDate", null);
+                EntityCondition conditionThroughDate = EntityCondition.makeCondition(EntityOperator.OR, UtilMisc.toList(conditionBeforeDate, conditionNull));
+                List<GenericValue> listProductIds = delegator.findList("ProductCategoryMember", EntityCondition.makeCondition(UtilMisc.toList(conditionProductCategory, conditionFromDate, conditionThroughDate)), UtilMisc.toSet("productId"), null, null, true);
+                List<String> listProductIdsString = EntityUtil.getFieldListFromEntityList(listProductIds, "productId", true);
+
+                EntityExpr conditionProductCat = EntityCondition.makeCondition("productId", EntityOperator.IN, listProductIdsString);
+                listAllConditions.add(conditionProductCat);
+            }
+
+            // productStoreId condition
+            List<String> productStoreList = new ArrayList<String>();
+            if (UtilValidate.isNotEmpty(parameters.get("productStoreId"))) {
+                if (parameters.get("productStoreId") instanceof String) {
+                    String productStoreId = (String) parameters.get("productStoreId");
+                    productStoreList.add(productStoreId);
+                } else {
+                    productStoreList = (List<String>) parameters.get("productStoreId");
+                }
+                // getting list of invoice Ids linked to these productStore
+                EntityExpr conditionProductStoreId = EntityCondition.makeCondition("productStoreId", EntityOperator.IN, productStoreList);
+                List<GenericValue> listOrderAndProductStores = delegator.findList("OrderAndProductStore", conditionProductStoreId, UtilMisc.toSet("orderId"), null, null, true);
+                List<String> listOrderIds = EntityUtil.getFieldListFromEntityList(listOrderAndProductStores, "orderId", true);
+                EntityExpr conditionOrderId = EntityCondition.makeCondition("orderId", EntityOperator.IN, listOrderIds);
+                List<GenericValue> listInvoices = delegator.findList("OrderItemBilling", conditionOrderId, UtilMisc.toSet("invoiceId"), null, null, false);
+                List<String> listInvoiceString = EntityUtil.getFieldListFromEntityList(listInvoices, "invoiceId", true);
+
+                EntityExpr conditionInvoiceIdProductStore = EntityCondition.makeCondition("invoiceId", EntityOperator.IN, listInvoiceString);
+                listAllConditions.add(conditionInvoiceIdProductStore);
+            }
+
+            // adding mandatory conditions
+            // condition on invoice item type
+            List<String> listInvoiceItemType = UtilMisc.toList("ITM_PROMOTION_ADJ", "INV_PROD_ITEM", "INV_FPROD_ITEM", "INV_DPROD_ITEM", "INV_FDPROD_ITEM", "INV_PROD_FEATR_ITEM");
+            listInvoiceItemType.add("ITM_DISCOUNT_ADJ");
+            listInvoiceItemType.add("CRT_FPROD_ITEM");
+            listInvoiceItemType.add("CRT_DPROD_ITEM");
+            listInvoiceItemType.add("CRT_FDPROD_ITEM");
+            listInvoiceItemType.add("CRT_SPROD_ITEM");
+            listInvoiceItemType.add("CRT_PROMOTION_ADJ");
+            listInvoiceItemType.add("CRT_DISCOUNT_ADJ");
+            listInvoiceItemType.add("CRT_MAN_ADJ");
+            listInvoiceItemType.add("INV_SPROD_ITEM");
+            EntityExpr conditionInvoiceItemType = EntityCondition.makeCondition("invoiceItemTypeId", EntityOperator.IN, listInvoiceItemType);
+            listAllConditions.add(conditionInvoiceItemType);
+
+            // condition on invoice ((not cancelled) or null)
+            EntityExpr conditionStatusNotCancelled = EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "INVOICE_CANCELLED");
+            EntityExpr conditionStatusNull = EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, null);
+            EntityCondition conditionStatus = EntityCondition.makeCondition(UtilMisc.toList(conditionStatusNotCancelled, conditionStatusNull), EntityOperator.OR);
+            listAllConditions.add(conditionStatus);
+
+            // condition sales invoice or customer return invoice
+            EntityExpr conditionSalesInvoice = EntityCondition.makeCondition("invoiceTypeId", EntityOperator.IN, UtilMisc.toList("SALES_INVOICE", "CUST_RTN_INVOICE"));
+            listAllConditions.add(conditionSalesInvoice);
+
+            // retrieving all invoices
+            Set<String> fieldsToSelect = UtilMisc.toSet("invoiceId");
+            fieldsToSelect.add("invoiceTypeId");
+            fieldsToSelect.add("invoicePartyId");
+            fieldsToSelect.add("statusId");
+            fieldsToSelect.add("invoiceDate");
+            fieldsToSelect.add("dueDate");
+            fieldsToSelect.add("currencyUomId");
+            fieldsToSelect.add("invoiceItemTypeId");
+            fieldsToSelect.add("invoiceItemSeqId");
+            fieldsToSelect.add("quantity");
+            fieldsToSelect.add("amount");
+            fieldsToSelect.add("productId");
+            fieldsToSelect.add("partyId");
+            fieldsToSelect.add("primaryProductCategoryId");
+            listTurnOver = delegator.findList("InvoiceItemProductAndParty", EntityCondition.makeCondition(listAllConditions), fieldsToSelect, null, null, true);
+
+            // adding missing fields
+            for (GenericValue invoice : listTurnOver) {
+                Map<String, Object> invoiceEditableTemp = (Map<String, Object>) invoice.clone();
+                invoiceEditableTemp.remove("GenericEntity");
+                Map<String, Object> invoiceEditable = new HashMap<String, Object>();
+                invoiceEditable.putAll(invoiceEditableTemp);
+                invoiceEditable.put("partyName", PartyHelper.getPartyName(delegator, invoice.getString("partyId"), false));
+
+                // adding productStoreId and productStoreName
+                EntityExpr conditionInvoiceId = EntityCondition.makeCondition("invoiceId", invoice.getString("invoiceId"));
+//                EntityExpr conditionInvoiceItemSeqId = EntityCondition.makeCondition("invoiceItemSeqId", invoice.getString("invoiceItemSeqId"));
+//                List<GenericValue> listOrderBilling = delegator.findList("OrderItemBilling", EntityCondition.makeCondition(UtilMisc.toList(conditionInvoiceId, conditionInvoiceItemSeqId)), UtilMisc.toSet("orderId"), null, null, false);
+                List<GenericValue> listOrderBilling = delegator.findList("OrderItemBilling", conditionInvoiceId, UtilMisc.toSet("orderId"), null, null, false);
+                if (UtilValidate.isNotEmpty(listOrderBilling)) {
+                    GenericValue orderBilling = EntityUtil.getFirst(listOrderBilling);
+                    EntityExpr conditionOrderId = EntityCondition.makeCondition("orderId", orderBilling.getString("orderId"));
+                    List<GenericValue> listProductStore = delegator.findList("OrderAndProductStore", conditionOrderId, null, null, null, true);
+                    GenericValue productStore = EntityUtil.getFirst(listProductStore);
+                    if (UtilValidate.isNotEmpty(productStoreList) && ! productStoreList.contains(productStore.getString("productStoreId"))) {
+                        continue; // pretty ugly... but had problems with the rare case where an invoice matches with several orders with more than one productStore
+                    }
+                    invoiceEditable.put("productStoreId", productStore.getString("productStoreId"));
+                    invoiceEditable.put("storeName", productStore.getString("storeName"));
+                } else {
+                    invoiceEditable.put("productStoreId", "_NA_");
+                    invoiceEditable.put("storeName", "_NA_");
+                }
+                listInvoiceEditable.add(invoiceEditable);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "BirtErrorRetrievingTurnOver", locale));
+        }
+        Map<String, Object> result = ServiceUtil.returnSuccess();
+        result.put("records", listInvoiceEditable);
+        return result;
+    }
+}