This is an automated email from the ASF dual-hosted git repository.

arunpati pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 11ad4c1fdb Improved: View combined PDF of selected orders from Find 
Orders (OFBIZ-13598) (#2025)
11ad4c1fdb is described below

commit 11ad4c1fdb295aa483eca8634a30bf06c4c54ad5
Author: Arun Patidar <[email protected]>
AuthorDate: Wed Sep 16 15:06:22 2026 +0530

    Improved: View combined PDF of selected orders from Find Orders 
(OFBIZ-13598) (#2025)
    
    Implements
    [OFBIZ-13598](https://issues.apache.org/jira/browse/OFBIZ-13598): adds a
    **View PDF** mass action to the Find Orders screen that opens one
    combined PDF containing all selected orders in a new browser tab. The
    existing Print (PDF) and Create File actions are unchanged.
    
    ## Changes
    
    - **OrderEvents.java**: new `viewOrdersPdf` event — loops the selected
    `orderIdList`, renders the existing `OrderPrintScreens.xml#OrderPDF`
    screen per order through the existing ScreenRenderer + FOP pipeline,
    merges the results with PDFBox `PDFMergerUtility` (already an OFBiz
    dependency), and streams the combined PDF inline as `application/pdf`.
    The screen location is hardcoded (not taken from a request parameter) to
    avoid a screen-injection vector. Per-order permission checks apply,
    since `OrderViewWebSecure.groovy` runs inside each render.
    - **controller.xml**: new `orders.pdf` request-map for the event
    (`auth=true`, success response `type=none`).
    - **FindOrders.ftl**: new **View PDF** option in the mass action
    dropdown, submitted with `target=_blank` so the PDF opens in a new tab
    and the Find Orders results stay intact.
    - **OrderUiLabels.xml**: new `OrderViewOrdersPdf` label ("View PDF",
    English).
---
 applications/order/config/OrderUiLabels.xml        |  3 +
 .../org/apache/ofbiz/order/order/OrderEvents.java  | 80 ++++++++++++++++++++++
 applications/order/template/order/FindOrders.ftl   |  3 +
 .../order/webapp/ordermgr/WEB-INF/controller.xml   |  6 ++
 4 files changed, 92 insertions(+)

diff --git a/applications/order/config/OrderUiLabels.xml 
b/applications/order/config/OrderUiLabels.xml
index a7256a6235..01a8d00bcc 100644
--- a/applications/order/config/OrderUiLabels.xml
+++ b/applications/order/config/OrderUiLabels.xml
@@ -15187,6 +15187,9 @@
         <value xml:lang="zh-CN">查看订单历史</value>
         <value xml:lang="zh-TW">檢視訂單歷史</value>
     </property>
+    <property key="OrderViewOrdersPdf">
+        <value xml:lang="en">View PDF</value>
+    </property>
     <property key="OrderViewPermissionError">
         <value xml:lang="ar">ليس لديك صلاحية مشاهدة هذه الصفحة (تحتاج إلى 
"ORDERMGR_VIEW" أو "ORDERMGR_PURCHASE_VIEW" أو "ORDERMGR_ADMIN").</value>
         <value xml:lang="de">Sie haben keine Leseberechtigung für diese Seite 
("ORDERMGR_VIEW", "ORDERMGR_PURCHASE_VIEW" oder "ORDERMGR_ADMIN" 
benötigt).</value>
diff --git 
a/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderEvents.java
 
b/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderEvents.java
index 02a4cd4880..6c0d319a9e 100644
--- 
a/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderEvents.java
+++ 
b/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderEvents.java
@@ -18,30 +18,54 @@
  
*******************************************************************************/
 package org.apache.ofbiz.order.order;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.stream.StreamSource;
+
 import jakarta.servlet.ServletContext;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.servlet.http.HttpSession;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.MimeConstants;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
 import org.apache.ofbiz.base.util.UtilHttp;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.base.util.collections.MapStack;
 import org.apache.ofbiz.content.data.DataResourceWorker;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericValue;
 import org.apache.ofbiz.entity.util.EntityQuery;
+import org.apache.ofbiz.security.Security;
 import org.apache.ofbiz.service.GenericServiceException;
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.service.ServiceUtil;
+import org.apache.ofbiz.webapp.view.ApacheFopWorker;
+import org.apache.ofbiz.widget.renderer.ScreenRenderer;
+import org.apache.ofbiz.widget.renderer.ScreenStringRenderer;
+import org.apache.ofbiz.widget.renderer.VisualTheme;
+import org.apache.ofbiz.widget.renderer.fo.FoFormRenderer;
+import org.apache.ofbiz.widget.renderer.macro.MacroScreenRenderer;
+import org.apache.pdfbox.io.RandomAccessReadBuffer;
+import org.apache.pdfbox.multipdf.PDFMergerUtility;
+import org.xml.sax.SAXException;
+
+import freemarker.template.TemplateException;
 
 /**
  * Order Events
@@ -49,6 +73,62 @@ import org.apache.ofbiz.service.ServiceUtil;
 public class OrderEvents {
 
     private static final String MODULE = OrderEvents.class.getName();
+    private static final String ORDER_PDF_SCREEN = 
"component://order/widget/ordermgr/OrderPrintScreens.xml#OrderPDF";
+
+    /**
+     * Streams one combined PDF for all selected orders to the browser, used 
by the
+     * Find Orders "View PDF" mass action.
+     */
+    public static String viewOrdersPdf(HttpServletRequest request, 
HttpServletResponse response) {
+        String[] orderIds = request.getParameterValues("orderIdList");
+        Delegator delegator = (Delegator) request.getAttribute("delegator");
+        LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
+        Security security = (Security) request.getAttribute("security");
+        GenericValue userLogin = (GenericValue) 
request.getSession().getAttribute("userLogin");
+        Locale locale = UtilHttp.getLocale(request);
+        VisualTheme visualTheme = UtilHttp.getVisualTheme(request);
+
+        try {
+            ScreenStringRenderer foScreenRenderer = new 
MacroScreenRenderer(visualTheme.getModelTheme().getType("screenfop"),
+                    
visualTheme.getModelTheme().getScreenRendererLocation("screenfop"));
+            PDFMergerUtility merger = new PDFMergerUtility();
+            int orderCount = 0;
+            for (String orderId : orderIds != null ? orderIds : new String[0]) 
{
+                if (UtilValidate.isEmpty(orderId)) {
+                    continue;
+                }
+                Writer writer = new StringWriter();
+                ScreenRenderer screens = new ScreenRenderer(writer, 
MapStack.create(), foScreenRenderer);
+                screens.populateBasicContext(UtilMisc.toMap("orderId", 
(Object) orderId), delegator, dispatcher, security, locale, userLogin);
+                screens.getContext().put("formStringRenderer", new 
FoFormRenderer());
+                screens.render(ORDER_PDF_SCREEN);
+
+                ByteArrayOutputStream orderPdf = new ByteArrayOutputStream();
+                Fop fop = ApacheFopWorker.createFopInstance(orderPdf, 
MimeConstants.MIME_PDF);
+                ApacheFopWorker.transform(new StreamSource(new 
StringReader(writer.toString())), null, fop);
+                merger.addSource(new 
RandomAccessReadBuffer(orderPdf.toByteArray()));
+                orderCount++;
+            }
+            if (orderCount == 0) {
+                request.setAttribute("_ERROR_MESSAGE_", "No orders selected.");
+                return "error";
+            }
+            ByteArrayOutputStream mergedPdf = new ByteArrayOutputStream();
+            merger.setDestinationStream(mergedPdf);
+            
merger.mergeDocuments(org.apache.pdfbox.io.IOUtils.createMemoryOnlyStreamCache());
+
+            response.setContentType("application/pdf");
+            response.setHeader("Content-Disposition", "inline; 
filename=\"orders.pdf\"");
+            response.setContentLength(mergedPdf.size());
+            mergedPdf.writeTo(response.getOutputStream());
+        } catch (GeneralException | IOException | SAXException | 
ParserConfigurationException | TemplateException e) {
+            String errMsg = "Error rendering orders PDF: " + e.toString();
+            Debug.logError(e, errMsg, MODULE);
+            request.setAttribute("_ERROR_MESSAGE_", errMsg);
+            return "error";
+        }
+        return "success";
+    }
 
     public static String downloadDigitalProduct(HttpServletRequest request, 
HttpServletResponse response) {
         HttpSession session = request.getSession();
diff --git a/applications/order/template/order/FindOrders.ftl 
b/applications/order/template/order/FindOrders.ftl
index 7380d190eb..86c5c13a18 100644
--- a/applications/order/template/order/FindOrders.ftl
+++ b/applications/order/template/order/FindOrders.ftl
@@ -48,6 +48,8 @@ function setServiceName(selection) {
 }
 function runAction() {
     var form = document.massOrderChangeForm;
+    // the combined orders PDF opens in a new tab, all other actions submit as 
usual
+    form.target = form.action.indexOf("orders.pdf") >= 0 ? '_blank' : '';
     form.submit();
 }
 
@@ -470,6 +472,7 @@ document.lookuporder.orderId.focus();
            <option 
value="<@ofbizUrl>massQuickShipOrders?hideFields=${hideFields}${ampersand}${paramList}</@ofbizUrl>">${uiLabelMap.OrderQuickShipEntireOrder}</option>
            <option 
value="<@ofbizUrl>massPrintOrders?hideFields=${hideFields}${ampersand}${paramList}</@ofbizUrl>">${uiLabelMap.CommonPrint}</option>
            <option 
value="<@ofbizUrl>massCreateFileForOrders?hideFields=${hideFields}${ampersand}${paramList}</@ofbizUrl>">${uiLabelMap.ContentCreateFile}</option>
+           <option 
value="<@ofbizUrl>orders.pdf</@ofbizUrl>">${uiLabelMap.OrderViewOrdersPdf}</option>
         </select>
         <#if printers?has_content>
         <select name="printerName">
diff --git a/applications/order/webapp/ordermgr/WEB-INF/controller.xml 
b/applications/order/webapp/ordermgr/WEB-INF/controller.xml
index 71bb387e82..1a25f2bb09 100644
--- a/applications/order/webapp/ordermgr/WEB-INF/controller.xml
+++ b/applications/order/webapp/ordermgr/WEB-INF/controller.xml
@@ -158,6 +158,12 @@ under the License.
         <response name="success" type="request-redirect" value="findorders"/>
         <response name="error" type="view" value="findorders"/>
     </request-map>
+    <request-map uri="orders.pdf">
+        <security https="true" auth="true"/>
+        <event type="java" path="org.apache.ofbiz.order.order.OrderEvents" 
invoke="viewOrdersPdf"/>
+        <response name="success" type="none"/>
+        <response name="error" type="view" value="findorders"/>
+    </request-map>
 
     <!-- Delivery Info Requests, intended for sales orders but can be used for 
purchase orders as well -->
     <request-map uri="OrderDeliveryScheduleInfo">

Reply via email to