svn commit: r1770621 [4/5] - in /ofbiz/trunk/specialpurpose/pricat: ./ config/ data/ entitydef/ groovyScripts/ groovyScripts/pricat/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/ofbiz/ src/main/jav...

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

svn commit: r1770621 [4/5] - in /ofbiz/trunk/specialpurpose/pricat: ./ config/ data/ entitydef/ groovyScripts/ groovyScripts/pricat/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/ofbiz/ src/main/jav...

shijh
Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlReport.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlReport.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlReport.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlReport.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.
+ *******************************************************************************/
+package org.apache.ofbiz.pricat;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.ofbiz.htmlreport.AbstractHtmlReport;
+import org.apache.ofbiz.htmlreport.InterfaceReportThread;
+import org.apache.ofbiz.htmlreport.util.ReportStringUtil;
+
+/**
+ * Provides a html report for running parse a PriCat file.<p>
+ *
+ */
+public class PricatParseExcelHtmlReport extends AbstractHtmlReport {
+
+ public static final String PRICAT_REPORT_CLASS = "PRICAT_HTML_REPORT";
+
+    /**
+     * Public constructor with report variables.<p>
+     *
+     * @param req the HttpServletRequest request
+     * @param res the HttpServletResponse response
+     */
+    public PricatParseExcelHtmlReport(HttpServletRequest request, HttpServletResponse response) {
+
+        super(request, response, true, true);
+    }
+    
+    public static PricatParseExcelHtmlReport getReport(HttpServletRequest request, HttpServletResponse response) {
+    
+     PricatParseExcelHtmlReport wp = (PricatParseExcelHtmlReport) request.getAttribute(PRICAT_REPORT_CLASS);
+     if (wp == null) {
+     wp = new PricatParseExcelHtmlReport(request, response);
+     request.setAttribute(PRICAT_REPORT_CLASS, wp);
+     }
+     return wp;
+    }
+    
+    public InterfaceReportThread initializeThread(HttpServletRequest request, HttpServletResponse response, String name) {
+
+ if (name == null) {
+ name = "";
+ }
+        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+        int i = threadGroup.activeCount();
+        Thread[] threads = new Thread[i];
+        threadGroup.enumerate(threads, true);
+        InterfaceReportThread thread = null;
+        for (int j=0; j<threads.length; j++) {
+         Thread threadInstance = threads[j];
+         if (threadInstance instanceof PricatParseExcelHtmlThread) {
+         thread = (PricatParseExcelHtmlThread) threadInstance;
+         break;
+         }
+        }
+        if (thread == null) {
+            thread = new PricatParseExcelHtmlThread(request, response, name);
+        }
+
+        return thread;
+    }
+
+    public static String checkButton(HttpServletRequest request, HttpServletResponse response) {
+     String action = request.getParameter("action");
+     if (ReportStringUtil.isNotEmpty(action)) {
+     if (action.equalsIgnoreCase("ok")) {
+     request.removeAttribute(PRICAT_REPORT_CLASS);
+     request.removeAttribute(DIALOG_URI);
+     return "ok";
+     } else if (action.equalsIgnoreCase("cancel")) {
+     request.removeAttribute(PRICAT_REPORT_CLASS);
+     request.removeAttribute(DIALOG_URI);
+     return "cancel";
+     }
+     }
+     action = request.getParameter("ok");
+     if (ReportStringUtil.isNotEmpty(action)) {
+     if (action.equalsIgnoreCase("ok")) {
+     request.removeAttribute(PRICAT_REPORT_CLASS);
+     request.removeAttribute(DIALOG_URI);
+     return "ok";
+     }
+     }
+        action = request.getParameter("cancel");
+        if (ReportStringUtil.isNotEmpty(action)) {
+         if (action.equalsIgnoreCase("cancel")) {
+     request.removeAttribute(PRICAT_REPORT_CLASS);
+     request.removeAttribute(DIALOG_URI);
+         return "cancel";
+         }
+        }
+        
+     return "success";
+    }
+
+    /**
+     * Performs the dialog actions depending on the initialized action.<p>
+     *
+     * @throws IOException
+     */
+    public void prepareDisplayReport(HttpServletRequest request, HttpServletResponse response, String name, String dialogUri) throws IOException {
+
+     if (ReportStringUtil.isNotEmpty(dialogUri)) {
+     setDialogRealUri(request, dialogUri);
+     }
+    
+        String action = getParamAction(request);
+        if (action == null) action = "";
+        if (action.equals("reportend") || action.equals("cancel")) {
+            setParamAction("reportend");
+            setDialogRealUri(request, dialogUri);
+        } else if (action.equals("reportupdate")) {
+            setParamAction("reportupdate");
+        } else {
+            InterfaceReportThread thread = initializeThread(request, response, name);
+            thread.start();
+            setParamAction("reportbegin");
+            setParamThread(thread.getUUID().toString());
+        }
+    }
+}

Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlThread.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlThread.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlThread.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatParseExcelHtmlThread.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * 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.
+ *******************************************************************************/
+package org.apache.ofbiz.pricat;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.ofbiz.htmlreport.AbstractReportThread;
+import org.apache.ofbiz.htmlreport.InterfaceReport;
+import org.apache.ofbiz.pricat.sample.SamplePricatParser;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.FileUtil;
+import org.apache.ofbiz.base.util.UtilDateTime;
+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.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.EntityOperator;
+import org.apache.ofbiz.entity.util.EntityUtil;
+import org.apache.ofbiz.service.LocalDispatcher;
+
+/**
+ * Thread for running pricat import excel html report.
+ *
+ */
+public class PricatParseExcelHtmlThread extends AbstractReportThread {
+
+ public static final String module = PricatParseExcelHtmlThread.class.getName();
+
+ public static final String PARSE_EXCEL = "parse_excel";
+
+ public static final String CONFIRM = "confirm_action";
+
+ public static final String[] messageLabels = new String[] {"FORMAT_DEFAULT", "FORMAT_WARNING", "FORMAT_HEADLINE", "FORMAT_NOTE", "FORMAT_OK", "FORMAT_ERROR", "FORMAT_THROWABLE"};
+
+ public static final List<String> messages = Collections.unmodifiableList(Arrays.asList(messageLabels));
+
+    public static final String FileDateTimePattern = "yyyyMMddHHmmss";
+    
+    public static final String defaultColorName = "DefaultColor";
+    
+    public static final String defaultDimensionName = "DefaultDimension";
+    
+    public static final String defaultCategoryName = "DefaultCategory";
+    
+    public static final String EXCEL_TEMPLATE_TYPE = "excelTemplateType";
+    
+    public static final String FACILITY_ID = "facilityId";
+    
+ private LocalDispatcher dispatcher;
+
+ private Delegator delegator;
+
+ private List<FileItem> fileItems;
+
+ private File pricatFile;
+
+ private String userLoginId;
+
+ private GenericValue userLogin;
+
+ private Map<String, String[]> facilities = new HashMap<String, String[]>();
+
+    public static final String resource = "PricatUiLabels";
+    
+    private HttpSession session;
+    
+    public static final String PRICAT_FILE = "__PRICAT_FILE__";
+
+    public static final String DEFAULT_PRICAT_TYPE = "sample_pricat";
+    
+    private String selectedPricatType = DEFAULT_PRICAT_TYPE;
+    
+    private String selectedFacilityId;
+    
+    public static final Map<String, String> PricatTypeLabels = UtilMisc.toMap("sample_pricat", "SamplePricatTemplate",
+                                                                      "ofbiz_pricat", "OFBizPricatTemplate");
+    
+    private InterfacePricatParser pricatParser;
+    
+    private String thruReasonId = "EXCEL_IMPORT_SUCCESS";
+    
+ /**
+     * Constructor, creates a new html thread.
+ *
+ * @param request
+ * @param response
+ * @param name
+ */
+    public PricatParseExcelHtmlThread(HttpServletRequest request, HttpServletResponse response, String name) {
+
+        super(request, response, name);
+ dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
+ setDelegator(dispatcher.getDelegator());
+ userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
+ if (UtilValidate.isEmpty(userLogin)) {
+        initHtmlReport(request, response, true, true);
+ getReport().println(UtilProperties.getMessage(resource, "PricatRequireUserLogin", getLocale()), InterfaceReport.FORMAT_ERROR);
+ return;
+ } else {
+ userLoginId = userLogin.getString("userLoginId");
+ session = request.getSession();
+ }
+
+ long sequenceNum = addExcelImportHistory();
+     File userFolder = FileUtil.getFile(InterfacePricatParser.tempFilesFolder + userLoginId + "/");
+     if (!userFolder.exists()) {
+     userFolder.mkdirs();
+     }
+ String logFileName = InterfacePricatParser.tempFilesFolder + userLoginId + "/" + sequenceNum + ".log";
+        initHtmlReport(request, response, true, true, logFileName);
+ if (sequenceNum > 0) {
+ getReport().setSequenceNum(sequenceNum);
+ getReport().addLogFile(logFileName);
+ }
+        try {
+         getReport().print(UtilProperties.getMessage(resource, "StartStoreExcel", getLocale()), InterfaceReport.FORMAT_HEADLINE);
+            ServletFileUpload dfu = new ServletFileUpload(new DiskFileItemFactory(10240, userFolder));
+         fileItems = UtilGenerics.checkList(dfu.parseRequest(request));
+        } catch (FileUploadException e) {
+            getReport().addError(e);
+        }
+        if (UtilValidate.isEmpty(fileItems)) {
+         getReport().println(UtilProperties.getMessage(resource, "NoFileUploaded", getLocale()), InterfaceReport.FORMAT_ERROR);
+        } else {
+         getReport().println(UtilProperties.getMessage(resource, "ok", getLocale()), InterfaceReport.FORMAT_OK);
+        }
+    }
+
+    public String getReportUpdate() {
+
+        return getReport().getReportUpdate();
+    }
+
+    /**
+     * @see java.lang.Runnable#run()
+     */
+    public void run() {
+
+        try {
+            if (getName().startsWith(PARSE_EXCEL) && UtilValidate.isNotEmpty(fileItems)) {
+     getReport().println();
+             getReport().println(UtilProperties.getMessage(resource, "StartParsePricat", getLocale()), InterfaceReport.FORMAT_HEADLINE);
+             if (prepareParse()) {
+                 if (selectedPricatType.equals(DEFAULT_PRICAT_TYPE)) {
+                 pricatParser = new SamplePricatParser(dispatcher, delegator, getLocale(), getReport(), facilities, pricatFile, userLogin);
+                 }
+                 if (UtilValidate.isEmpty(pricatParser)) {
+                 getReport().println(UtilProperties.getMessage(resource, "NoPricatParserFor", getLocale()), InterfaceReport.FORMAT_ERROR);
+                 } else {
+                     pricatParser.parsePricatExcel();
+                     getReport().println(UtilProperties.getMessage(resource, "PricatParseCompleted", getLocale()), InterfaceReport.FORMAT_HEADLINE);
+                 }
+             }
+         } else {
+             getReport().println(getName(), InterfaceReport.FORMAT_ERROR);
+             Debug.logError(getName(), module);
+             thruReasonId = "EXCEL_IMPORT_ERROR";
+            }
+        } catch (Exception e) {
+         getReport().println(e);
+         Debug.logError(e, module);
+         thruReasonId = "EXCEL_IMPORT_ERROR";
+        } finally {
+         // wait 5 seconds to wait page output
+         try {
+ sleep(5000);
+ } catch (InterruptedException e) {
+ }
+         // call report update to make sure all messages are output to file
+         getReport().getReportUpdate();
+         String logFileName = getReport().closeLogFile();
+         if (UtilValidate.isNotEmpty(pricatParser)) {
+         if (thruReasonId.equals("EXCEL_IMPORT_SUCCESS") && pricatParser.hasErrorMessages()) {
+         thruReasonId = "EXCEL_IMPORT_QUEST";
+         }
+             pricatParser.endExcelImportHistory(logFileName, thruReasonId);
+         }
+        }
+    }
+
+    private boolean prepareParse() throws IOException {
+ // 1 get facilities belong to current userLogin
+ facilities = getCurrentUserLoginFacilities();
+ if (UtilValidate.isEmpty(facilities)) {
+ getReport().println(UtilProperties.getMessage(resource, "CurrentUserLoginNoFacility", new Object[]{userLoginId}, getLocale()), InterfaceReport.FORMAT_ERROR);
+ return false;
+ } else {
+ getReport().println(" ... " + UtilProperties.getMessage(resource, "ok", getLocale()), InterfaceReport.FORMAT_OK);
+ getReport().println();
+ }
+
+ // 2. store the pricat excel file
+ if (!storePricatFile()) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean storePricatFile() throws IOException {
+        FileItem fi = null;
+        FileItem pricatFi = null;
+        byte[] pricatBytes = {};
+        // check excelTemplateType
+        for (int i = 0; i < fileItems.size(); i++) {
+         fi = fileItems.get(i);
+         String fieldName = fi.getFieldName();
+         if (fi.isFormField() && UtilValidate.isNotEmpty(fieldName)) {
+         if (fieldName.equals(EXCEL_TEMPLATE_TYPE)) {
+         selectedPricatType = fi.getString();
+         }
+         }
+        }
+        getReport().print(UtilProperties.getMessage(resource, "ExcelTemplateTypeSelected", getLocale()), InterfaceReport.FORMAT_DEFAULT);
+        if (PricatTypeLabels.containsKey(selectedPricatType)) {
+            getReport().print(UtilProperties.getMessage(resource, PricatTypeLabels.get(selectedPricatType), getLocale()), InterfaceReport.FORMAT_DEFAULT);
+ getReport().println(" ... " + UtilProperties.getMessage(resource, "ok", getLocale()), InterfaceReport.FORMAT_OK);
+        } else {
+            getReport().println(UtilProperties.getMessage(resource, PricatTypeLabels.get(selectedPricatType), getLocale()), InterfaceReport.FORMAT_ERROR);
+         return false;
+        }
+
+        // store the file
+        for (int i = 0; i < fileItems.size(); i++) {
+            fi = fileItems.get(i);
+            String fieldName = fi.getFieldName();
+            if (fieldName.equals("filename")) {
+                pricatFi = fi;
+                pricatBytes = pricatFi.get();
+                Path path = Paths.get(fi.getName());
+                pricatFile = new File(InterfacePricatParser.tempFilesFolder + userLoginId + "/" + path.getFileName().toString());
+                FileOutputStream fos = new FileOutputStream(pricatFile);
+                fos.write(pricatBytes);
+                fos.flush();
+                fos.close();
+                session.setAttribute(PRICAT_FILE, pricatFile.getAbsolutePath());
+            }
+        }
+        return true;
+ }
+
+ private Map<String, String[]> getCurrentUserLoginFacilities() {
+ getReport().println();
+ getReport().println(UtilProperties.getMessage(resource, "GetCurrentUserLoginFacility", getLocale()), InterfaceReport.FORMAT_DEFAULT);
+ Map<String, Object> context = new HashMap<String, Object>();
+ context.put("userLogin", userLogin);
+ context.put("locale", getLocale());
+ try {
+ List<EntityCondition> orgConditions = new LinkedList<EntityCondition>();
+ orgConditions.add(EntityCondition.makeCondition("onePartyIdFrom", EntityOperator.EQUALS, userLogin.getString("partyId")));
+ orgConditions.add(EntityCondition.makeCondition("twoRoleTypeIdFrom", EntityOperator.EQUALS, "INTERNAL_ORGANIZATIO"));
+ orgConditions.add(EntityCondition.makeCondition("twoRoleTypeIdTo", EntityOperator.EQUALS, "EMPLOYEE"));
+ orgConditions.add(EntityCondition.makeCondition("twoRoleTypeIdTo", EntityOperator.EQUALS, "EMPLOYEE"));
+ List<GenericValue> organizations = delegator.findList("PartyRelationshipToFrom", EntityCondition.makeCondition(orgConditions), null, null, null, false);
+ Timestamp now = UtilDateTime.nowTimestamp();
+ organizations = EntityUtil.filterByDate(organizations, now, "twoFromDate", "twoThruDate", true);
+ organizations = EntityUtil.filterByDate(organizations, now, "oneFromDate", "oneThruDate", true);
+
+ List<EntityCondition> ownerPartyConditions = new LinkedList<EntityCondition>();
+ Set<String> orgPartyIds = new HashSet<String>();
+ for (GenericValue organization : organizations) {
+ String orgPartyId = organization.getString("onePartyIdTo");
+ if (!orgPartyIds.contains(orgPartyId)) {
+ ownerPartyConditions.add(EntityCondition.makeCondition("ownerPartyId", EntityOperator.EQUALS, orgPartyId));
+ orgPartyIds.add(orgPartyId);
+ }
+ }
+ if (UtilValidate.isEmpty(ownerPartyConditions)) {
+ return facilities;
+ }
+
+ List<GenericValue> facilityValues = delegator.findList("Facility", EntityCondition.makeCondition(ownerPartyConditions, EntityOperator.OR), null, null, null, false);
+ if (UtilValidate.isNotEmpty(facilityValues)) {
+ int i = 1;
+ for (GenericValue facilityValue : facilityValues) {
+ if (UtilValidate.isNotEmpty(facilityValue)) {
+ String facilityId = facilityValue.getString("facilityId");
+ if (!facilities.containsKey(facilityId)) {
+ String facilityName = facilityValue.getString("facilityName");
+ facilities.put(facilityId, new String[] {facilityName, facilityValue.getString("ownerPartyId")});
+ getReport().println(UtilProperties.getMessage(resource, "FacilityFoundForCurrentUserLogin", new Object[]{String.valueOf(i), facilityName, facilityId}, getLocale()), InterfaceReport.FORMAT_NOTE);
+ i++;
+ }
+ }
+ }
+ }
+ }catch (GenericEntityException e) {
+ Debug.logError(e.getMessage(), module);
+ }
+ return facilities;
+ }
+
+ public Delegator getDelegator() {
+ return delegator;
+ }
+
+ public void setDelegator(Delegator delegator) {
+ this.delegator = delegator;
+ }
+
+ public synchronized long addExcelImportHistory() {
+ long latestId = 1;
+ try {
+ List<GenericValue> historyValues = delegator.findByAnd("ExcelImportHistory", UtilMisc.toMap("userLoginId", userLoginId), UtilMisc.toList("sequenceNum DESC"), false);
+ GenericValue latestHistoryValue = EntityUtil.getFirst(historyValues);
+ if (UtilValidate.isNotEmpty(latestHistoryValue)) {
+ latestId = latestHistoryValue.getLong("sequenceNum") + 1;
+ }
+ GenericValue newHistoryValue = delegator.makeValue("ExcelImportHistory", UtilMisc.toMap("sequenceNum", latestId, "userLoginId", userLoginId,
+ "fileName", pricatFile == null ? "" : pricatFile.getName(), "statusId", isAlive() ? "EXCEL_IMPORTING" : "EXCEL_IMPORTED",
+ "fromDate", UtilDateTime.nowTimestamp(), "threadName", getName(), "logFileName", InterfacePricatParser.tempFilesFolder + userLoginId + "/" + latestId + ".log"));
+ newHistoryValue.create();
+ } catch (GenericEntityException e) {
+ Debug.logError(e, module);
+ return -1;
+ }
+ return latestId;
+ }
+}

Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatEvents.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatEvents.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatEvents.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.
+ *******************************************************************************/
+package org.apache.ofbiz.pricat.sample;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jdom.JDOMException;
+import org.apache.ofbiz.base.location.ComponentLocationResolver;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.UtilHttp;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.pricat.PricatEvents;
+
+public class SamplePricatEvents extends PricatEvents {
+
+ public static final String module = SamplePricatEvents.class.getName();
+
+ public static final String PricatLatestVersion = UtilProperties.getPropertyValue("pricat", "pricat.latest.version", "V1.1");
+
+ public static final String DemoPricatFileName = "SamplePricatTemplate_" + PricatLatestVersion + ".xlsx";
+
+ public static final String DemoPricatPath = "component://pricat/webapp/pricatdemo/downloads/";
+
+    /**
+ * Download excel template.
+ *
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ * @throws JDOMException
+ */
+ public static String downloadExcelTemplate(HttpServletRequest request, HttpServletResponse response) {
+ String templateType = request.getParameter("templateType");
+ if (UtilValidate.isEmpty(templateType)) {
+ return "error";
+ }
+ try {
+ String path = ComponentLocationResolver.getBaseLocation(DemoPricatPath).toString();
+ String fileName = null;
+ if ("pricatExcelTemplate".equals(templateType)) {
+ fileName = DemoPricatFileName;
+ }
+ if (UtilValidate.isEmpty(fileName)) {
+ return "error";
+ }
+        Path file = Paths.get(path + fileName);
+        byte[] bytes = Files.readAllBytes(file);
+        UtilHttp.streamContentToBrowser(response, bytes, "application/octet-stream", URLEncoder.encode(fileName, "UTF-8"));
+ } catch (MalformedURLException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ } catch (IOException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ }
+        return "success";
+    }
+}

Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatParser.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatParser.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatParser.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/sample/SamplePricatParser.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,665 @@
+/*******************************************************************************
+ * 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.
+ *******************************************************************************/
+package org.apache.ofbiz.pricat.sample;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.poi.POIXMLException;
+import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.ofbiz.pricat.AbstractPricatParser;
+import org.apache.ofbiz.htmlreport.InterfaceReport;
+import org.apache.ofbiz.order.finaccount.FinAccountHelper;
+import org.apache.ofbiz.base.util.Debug;
+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.transaction.GenericTransactionException;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ServiceUtil;
+
+/**
+ * Sample pricat excel parser.
+ *
+ */
+public class SamplePricatParser extends AbstractPricatParser {
+
+ public static final String module = SamplePricatParser.class.getName();
+
+    public static final Map<String, List<Object[]>> ColNamesList = UtilMisc.toMap("V1.1", genExcelHeaderNames("V1.1"));
+
+    public static final int headerRowNo = 4;
+    
+    private List<String> headerColNames = new ArrayList<String>();
+    
+    public SamplePricatParser(LocalDispatcher dispatcher, Delegator delegator, Locale locale, InterfaceReport report, Map<String, String[]> facilities, File pricatFile, GenericValue userLogin) {
+        super(dispatcher, delegator, locale, report, facilities, pricatFile, userLogin);
+    }
+
+ /**
+     * Parse pricat excel file in xlsx format.
+     *
+     */
+ public void parsePricatExcel(boolean writeFile) {
+ XSSFWorkbook workbook = null;
+ try {
+ // 1. read the pricat excel file
+            FileInputStream is = new FileInputStream(pricatFile);
+
+ // 2. use POI to load this bytes
+         report.print(UtilProperties.getMessage(resource, "ParsePricatFileStatement", new Object[] { pricatFile.getName() }, locale), InterfaceReport.FORMAT_DEFAULT);
+ try {
+    workbook = new XSSFWorkbook(is);
+ report.println(UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ } catch(IOException e) {
+ report.println(e);
+ report.println(UtilProperties.getMessage(resource, "PricatSuggestion", locale), InterfaceReport.FORMAT_ERROR);
+ return;
+ } catch(POIXMLException e) {
+ report.println(e);
+ report.println(UtilProperties.getMessage(resource, "PricatSuggestion", locale), InterfaceReport.FORMAT_ERROR);
+ return;
+ }
+
+ // 3. only first sheet will be parsed
+ // 3.1 verify the file has a sheet at least
+ formatter = new HSSFDataFormatter(locale);
+ isNumOfSheetsOK(workbook);
+
+ // 3.2 verify the version is supported
+ XSSFSheet sheet = workbook.getSheetAt(0);
+ if (!isVersionSupported(sheet)) {
+ return;
+ }
+
+ // 3.3 get currencyId
+ existsCurrencyId(sheet);
+
+ // 3.4 verify the table header row is just the same as column names, if not, print error and return
+ if (!isTableHeaderMatched(sheet)) {
+ return;
+ }
+
+ // 3.5 verify the first table has 6 rows at least
+ containsDataRows(sheet);
+
+ if (UtilValidate.isNotEmpty(errorMessages)) {
+ report.println(UtilProperties.getMessage(resource, "HeaderContainsError", locale), InterfaceReport.FORMAT_ERROR);
+ return;
+ }
+
+        // 4. parse data
+ // 4.1 parse row by row and store the contents into database
+ parseRowByRow(sheet);
+ if (UtilValidate.isNotEmpty(errorMessages)) {
+ report.println(UtilProperties.getMessage(resource, "DataContainsError", locale), InterfaceReport.FORMAT_ERROR);
+ if (writeFile) {
+ sequenceNum = report.getSequenceNum();
+ writeCommentsToFile(workbook, sheet);
+ }
+ }
+
+ // 5. clean up the log files and commented Excel files
+ cleanupLogAndCommentedExcel();
+ } catch (IOException e) {
+ report.println(e);
+ Debug.logError(e, module);
+ } finally {
+            if (UtilValidate.isNotEmpty(fileItems)) {
+     // remove tmp files
+                FileItem fi = null;
+                for (int i = 0; i < fileItems.size(); i++) {
+                    fi = fileItems.get(i);
+                    fi.delete();
+                }
+            }
+            if (workbook != null) {
+             try {
+ workbook.close();
+ } catch (IOException e) {
+ Debug.logError(e, module);
+ }
+            }
+ }
+ }
+
+ public boolean existsCurrencyId(XSSFSheet sheet) {
+ report.print(UtilProperties.getMessage(resource, "StartCheckCurrencyId", locale), InterfaceReport.FORMAT_NOTE);
+ XSSFCell currencyIdCell = sheet.getRow(2).getCell(1);
+ currencyId = currencyIdCell.getStringCellValue().trim().toUpperCase();
+ if (UtilValidate.isEmpty(currencyId)) {
+ String errorMessage = UtilProperties.getMessage(resource, "CurrencyIdRequired", locale);
+ report.println(errorMessage, InterfaceReport.FORMAT_ERROR);
+ errorMessages.put(new CellReference(currencyIdCell), errorMessage);
+ return false;
+ } else {
+ try {
+ GenericValue currencyUom = delegator.findOne("Uom", UtilMisc.toMap("uomId", currencyId), false);
+ if (!"CURRENCY_MEASURE".equals(currencyUom.getString("uomTypeId"))) {
+ String errorMessage = UtilProperties.getMessage(resource, "CurrencyIdNotCurrency", new Object[] {currencyId}, locale);
+ report.println(errorMessage, InterfaceReport.FORMAT_ERROR);
+ errorMessages.put(new CellReference(currencyIdCell), errorMessage);
+ return false;
+ }
+ } catch(GenericEntityException e) {
+ String errorMessage = UtilProperties.getMessage(resource, "CurrencyIdNotFound", new Object[] {currencyId}, locale);
+ report.println(errorMessage, InterfaceReport.FORMAT_ERROR);
+ errorMessages.put(new CellReference(currencyIdCell), errorMessage);
+ return false;
+ }
+ report.print(UtilProperties.getMessage(resource, "CurrencyIdIs", new Object[] {currencyId}, locale), InterfaceReport.FORMAT_NOTE);
+ report.println(" ... " + UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ }
+ return true;
+ }
+
+ public void parseRowByRow(XSSFSheet sheet) {
+ int rows = sheet.getPhysicalNumberOfRows();
+ List<Object[]> colNames = ColNamesList.get(pricatFileVersion);
+ int colNumber = colNames.size();
+
+ int emptyRowStart = -1;
+ int emptyRowEnd = -1;
+ for (int i = headerRowNo + 1; i < rows; i++) {
+ XSSFRow row = sheet.getRow(i);
+ if (UtilValidate.isEmpty(row) || isEmptyRow(row, colNumber, false)) {
+ if (emptyRowStart == -1) {
+ report.print("(" + (i + 1) + ") ", InterfaceReport.FORMAT_NOTE);
+ emptyRowStart = i;
+ } else {
+ emptyRowEnd = i;
+ }
+ continue;
+ } else {
+ if (emptyRowStart != -1) {
+ if (emptyRowEnd != -1) {
+ report.print(" - (" + (emptyRowEnd + 1) + ") ", InterfaceReport.FORMAT_NOTE);
+ }
+ report.print(UtilProperties.getMessage(resource, "ExcelEmptyRow", locale), InterfaceReport.FORMAT_NOTE);
+ report.println(" ... " + UtilProperties.getMessage(resource, "skipped", locale), InterfaceReport.FORMAT_NOTE);
+ emptyRowStart = -1;
+ emptyRowEnd = -1;
+ }
+ }
+ report.print("(" + (i + 1) + ") ", InterfaceReport.FORMAT_NOTE);
+ List<Object> cellContents = getCellContents(row, colNames, colNumber);
+ try {
+ if (parseCellContentsAndStore(row, cellContents)) {
+ report.println(" ... " + UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ } else {
+ report.println(" ... " + UtilProperties.getMessage(resource, "skipped", locale), InterfaceReport.FORMAT_NOTE);
+ }
+ } catch (GenericTransactionException e) {
+ report.println(e);
+ }
+ }
+ if (emptyRowEnd != -1) {
+ report.print(" - (" + (emptyRowEnd + 1) + ") ", InterfaceReport.FORMAT_NOTE);
+ report.print(UtilProperties.getMessage(resource, "ExcelEmptyRow", locale), InterfaceReport.FORMAT_NOTE);
+ report.println(" ... " + UtilProperties.getMessage(resource, "skipped", locale), InterfaceReport.FORMAT_NOTE);
+ }
+ }
+
+ /**
+ * Check data according to business logic. If data is ok, store it.
+ *
+ * @param row
+ * @param cellContents
+ * @param document
+ * @return
+ * @throws GenericTransactionException
+ */
+ public boolean parseCellContentsAndStore(XSSFRow row, List<Object> cellContents) throws GenericTransactionException {
+ if (UtilValidate.isEmpty(cellContents)) {
+ return false;
+ }
+ switch(pricatFileVersion) {
+ case "V1.1":
+ default:
+ return parseCellContentsAndStoreV1_X(row, cellContents);
+ }
+ }
+
+ private boolean parseCellContentsAndStoreV1_X(XSSFRow row, List<Object> cellContents) throws GenericTransactionException {
+ if (UtilValidate.isEmpty(cellContents)) {
+ return false;
+ }
+ // 1. check if facilityId is in the facilities belong to the user, or if the name is correct for the id
+ String facilityName = (String) getCellContent(cellContents, "Facility Name");
+ String facilityId = (String) getCellContent(cellContents, "FacilityId");
+ if (!isFacilityOk(row, facilityName, facilityId))
+ return false;
+
+ // 2. get productCategoryId
+ String ownerPartyId = facilities.get(facilityId)[1];
+ String productCategoryId = getProductCategoryId(cellContents, ownerPartyId);
+
+ // 3. get productFeatureId of brand
+ String brandName = (String) getCellContent(cellContents, "Brand");
+ String brandId = getBrandId(brandName, ownerPartyId);
+ if (UtilValidate.isEmpty(brandId)) {
+ return false;
+ }
+
+ // 4. get productId from brandId, model name
+ String modelName = (String) getCellContent(cellContents, "Style No");
+ String productName = (String) getCellContent(cellContents, "Product Name");
+ BigDecimal listPrice = (BigDecimal) getCellContent(cellContents, "List Price");
+ String productId = getProductId(row, brandId, modelName, productName, productCategoryId, ownerPartyId, listPrice);
+ if (UtilValidate.isEmpty(productId) || UtilValidate.isEmpty(listPrice)) {
+ return false;
+ }
+
+ // 5. update color and size if necessary
+ String color = (String) getCellContent(cellContents, "Color");
+ if (UtilValidate.isEmpty(color) || UtilValidate.isEmpty(color.trim())) {
+ color = defaultColorName;
+ }
+ String dimension = (String) getCellContent(cellContents, "Size");
+ if (UtilValidate.isEmpty(dimension) || UtilValidate.isEmpty(dimension.trim())) {
+ dimension = defaultDimensionName;
+ }
+ Map<String, Object> features = updateColorAndDimension(productId, ownerPartyId, color, dimension);
+ if (ServiceUtil.isError(features)) {
+ if (features.containsKey("index") && String.valueOf(features.get("index")).contains("0")) {
+ int cell = headerColNames.indexOf("Color");
+ XSSFCell colorCell = row.getCell(cell);
+ errorMessages.put(new CellReference(colorCell), UtilProperties.getMessage(resource, "PricatColorError", locale));
+ }
+ if (features.containsKey("index") && String.valueOf(features.get("index")).contains("1")) {
+ int cell = headerColNames.indexOf("Size");
+ XSSFCell colorCell = row.getCell(cell);
+ errorMessages.put(new CellReference(colorCell), UtilProperties.getMessage(resource, "PricatDimensionError", locale));
+ }
+ return false;
+ }
+ String colorId = (String) features.get("colorId");
+ String dimensionId = (String) features.get("dimensionId");
+
+ // 6. update skuIds by productId
+ String barcode = (String) getCellContent(cellContents, "Barcode");
+ BigDecimal inventory = (BigDecimal) getCellContent(cellContents, "Stock Qty");
+ BigDecimal averageCost = (BigDecimal) getCellContent(cellContents, "Average Cost");
+ String skuId = updateSku(row, productId, ownerPartyId, facilityId, barcode, inventory, colorId, color, dimensionId, dimension, listPrice, averageCost);
+ if (UtilValidate.isEmpty(skuId)) {
+ return false;
+ }
+
+ // 7. store prices
+ BigDecimal memberPrice = (BigDecimal) getCellContent(cellContents, "Member Price");
+ Map<String, Object> results = updateSkuPrice(skuId, ownerPartyId, memberPrice);
+ if (ServiceUtil.isError(results)) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ public String updateSku(XSSFRow row, String productId, String ownerPartyId, String facilityId, String barcode, BigDecimal inventory,
+ String colorId, String color, String dimensionId, String dimension, BigDecimal listPrice, BigDecimal averageCost) {
+ return "sampleSkuId";
+ }
+
+ public String getProductId(XSSFRow row, String brandId, String modelName, String productName, String productCategoryId, String ownerPartyId, BigDecimal listPrice) {
+ return "sampleProductId";
+ }
+
+ public Object getCellContent(List<Object> cellContents, String colName) {
+ if (UtilValidate.isNotEmpty(headerColNames) && headerColNames.contains(colName)) {
+ return cellContents.get(headerColNames.indexOf(colName));
+ }
+ return null;
+ }
+
+ public String getProductCategoryId(List<Object> cellContents, String ownerPartyId) {
+ return "sampleProductCategoryId";
+ }
+
+ public boolean isFacilityOk(XSSFRow row, String facilityName, String facilityId) {
+ if (!facilities.containsKey(facilityId)) {
+ if (UtilValidate.isEmpty(facilityId) && facilities.keySet().size() == 1) {
+ if (UtilValidate.isEmpty(facilityName)) {
+ return true;
+ } else {
+ String theFacilityId = (String) facilities.keySet().toArray()[0];
+ String name = facilities.get(theFacilityId)[0];
+ if (!name.equals(facilityName)) {
+ String errorMessage = UtilProperties.getMessage(resource, "FacilityNameNotMatchId", new Object[]{theFacilityId, name, facilityName}, locale);
+ report.println();
+ report.print(errorMessage, InterfaceReport.FORMAT_ERROR);
+ XSSFCell cell = row.getCell(0);
+ errorMessages.put(new CellReference(cell), errorMessage);
+ return false;
+ }
+ }
+ } else {
+ String errorMessage = UtilProperties.getMessage(resource, "FacilityNotBelongToYou", new Object[]{facilityName, facilityId}, locale);
+ report.println();
+ report.print(errorMessage, InterfaceReport.FORMAT_ERROR);
+ XSSFCell cell = row.getCell(1);
+ errorMessages.put(new CellReference(cell), errorMessage);
+ return false;
+ }
+ } else {
+ String name = facilities.get(facilityId)[0];
+ if (!name.equals(facilityName)) {
+ String errorMessage = UtilProperties.getMessage(resource, "FacilityNameNotMatchId", new Object[]{facilityId, name, facilityName}, locale);
+ report.println();
+ report.print(errorMessage, InterfaceReport.FORMAT_ERROR);
+ XSSFCell cell = row.getCell(0);
+ errorMessages.put(new CellReference(cell), errorMessage);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean isTableHeaderMatched(XSSFSheet sheet) {
+ List<Object[]> columnNames = ColNamesList.get(pricatFileVersion);
+ short cols = sheet.getRow(headerRowNo).getLastCellNum();
+ report.print(UtilProperties.getMessage(resource, "StartCheckHeaderColNum", new Object[] {pricatFileVersion}, locale), InterfaceReport.FORMAT_NOTE);
+ if (cols != columnNames.size()) {
+ report.print(UtilProperties.getMessage(resource, "HeaderColNumNotMatch", new Object[] {String.valueOf(cols), String.valueOf(columnNames.size())}, locale), InterfaceReport.FORMAT_WARNING);
+ if (cols < columnNames.size()) {
+ report.println(UtilProperties.getMessage(resource, "HeaderColNumShortThanRequired", new Object[] {String.valueOf(columnNames.size())}, locale), InterfaceReport.FORMAT_ERROR);
+ return false;
+ } else {
+ report.println(UtilProperties.getMessage(resource, "UseHeaderColNum", new Object[] {String.valueOf(columnNames.size())}, locale), InterfaceReport.FORMAT_WARNING);
+ cols = (short) columnNames.size();
+ }
+ } else {
+ report.println(UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ }
+
+ report.print(UtilProperties.getMessage(resource, "StartCheckHeaderColLabel", new Object[] {pricatFileVersion}, locale), InterfaceReport.FORMAT_NOTE);
+ boolean foundLabelNotMatch = false;
+ for (int i = 0; i < cols; i++) {
+ String coltext = sheet.getRow(headerRowNo).getCell(i).getStringCellValue().trim();
+ headerColNames.add(coltext);
+ Object[] versionColumn = columnNames.get(i);
+ if (!coltext.equals(versionColumn[0])) {
+ report.println(UtilProperties.getMessage(resource, "HeaderColLabelNotMatch", new Object[] {String.valueOf(headerRowNo + 1), String.valueOf(i + 1), coltext, versionColumn[0]}, locale), InterfaceReport.FORMAT_ERROR);
+ foundLabelNotMatch = true;
+ } else {
+ report.print(" " + coltext, InterfaceReport.FORMAT_NOTE);
+ if (i < cols - 1) {
+ report.print(",", InterfaceReport.FORMAT_NOTE);
+ }
+ }
+ }
+ if (foundLabelNotMatch) {
+ report.println();
+ return false;
+ }
+ report.println(" ... " + UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ return true;
+ }
+
+ public boolean isVersionSupported(XSSFSheet sheet) {
+ report.print(UtilProperties.getMessage(resource, "StartCheckPricatVersion", locale), InterfaceReport.FORMAT_NOTE);
+ pricatFileVersion = sheet.getRow(2).getCell(0).getStringCellValue().trim();
+ if (ColNamesList.containsKey(pricatFileVersion)) {
+ report.print(" " + pricatFileVersion + " ... ", InterfaceReport.FORMAT_NOTE);
+ report.println(UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ } else {
+ report.println(UtilProperties.getMessage(resource, "error", locale), InterfaceReport.FORMAT_ERROR);
+ report.println(UtilProperties.getMessage(resource, "PricatVersionNotSupport", new Object[] {pricatFileVersion}, locale), InterfaceReport.FORMAT_ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean containsDataRows(XSSFSheet sheet) {
+ int rows = sheet.getPhysicalNumberOfRows();
+ if (rows > headerRowNo + 1) {
+ report.println(UtilProperties.getMessage(resource, "PricatTableRows", new Object[] {String.valueOf(headerRowNo + 1), String.valueOf(rows - headerRowNo - 1), sheet.getSheetName()}, locale), InterfaceReport.FORMAT_NOTE);
+ } else {
+ report.println(UtilProperties.getMessage(resource, "PricatNoDataRows", new Object[] {sheet.getSheetName()}, locale), InterfaceReport.FORMAT_ERROR);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The Object[] have 4 elements, they are:
+ * 1. Header Label Name.
+ * 2. Cell data type to return.
+ * 3. Boolean value to indicate whether the column is required.
+ * 4. Boolean value to indicate whether the column is a price when cell data type is BigDecimal, this element is optional.
+ *
+ * @param version
+ * @return List of Object[]
+ */
+ private static List<Object[]> genExcelHeaderNames(String version){
+ switch (version) {
+ case "V1.1":
+ default:
+ return genExcelHeaderNamesV1_1();
+ }
+ }
+
+ /**
+ * Get V1.1 pricat excel header names and attributes.
+ *
+ * @return list of Object[]
+ */
+ private static List<Object[]> genExcelHeaderNamesV1_1() {
+ List<Object[]> listHeaderName = new ArrayList<Object[]>();
+ listHeaderName.add(new Object[] {"Facility Name",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.TRUE});
+ listHeaderName.add(new Object[] {"FacilityId",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.TRUE});
+ listHeaderName.add(new Object[] {"Category L1",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Category L2",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Category L3",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Category L4",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Brand",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.TRUE});
+ listHeaderName.add(new Object[] {"Style No",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.TRUE});
+ listHeaderName.add(new Object[] {"Product Name",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.TRUE});
+ listHeaderName.add(new Object[] {"Color",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Size",
+                                         XSSFCell.CELL_TYPE_STRING,
+                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Barcode",
+                                         XSSFCell.CELL_TYPE_STRING,
+                                         Boolean.FALSE});
+ listHeaderName.add(new Object[] {"Stock Qty",
+                                         XSSFCell.CELL_TYPE_NUMERIC,
+                                         Boolean.TRUE});
+ listHeaderName.add(new Object[] {"Average Cost",
+                                         XSSFCell.CELL_TYPE_NUMERIC,
+                                         Boolean.TRUE,
+                     Boolean.TRUE});
+ listHeaderName.add(new Object[] {"List Price",
+ XSSFCell.CELL_TYPE_NUMERIC,
+ Boolean.TRUE,
+ Boolean.TRUE});
+ listHeaderName.add(new Object[] {"Member Price",
+                                       XSSFCell.CELL_TYPE_NUMERIC,
+                                       Boolean.FALSE,
+                                       Boolean.TRUE});
+ return listHeaderName;
+ }
+
+ @Override
+ public void parsePricatExcel() {
+ parsePricatExcel(true);
+ }
+
+ /**
+ * Get data by version definition.
+ *
+ * @param row
+ * @param colNames
+ * @param size
+ * @return
+ */
+ public List<Object> getCellContents(XSSFRow row, List<Object[]> colNames, int size) {
+ List<Object> results = new ArrayList<Object>();
+ boolean foundError = false;
+ if (isEmptyRow(row, size, true)) {
+ return null;
+ }
+
+ // check and get data
+ for (int i = 0; i < size; i++) {
+ XSSFCell cell = null;
+ if (row.getPhysicalNumberOfCells() > i) {
+ cell = row.getCell(i);
+ }
+ if (cell == null) {
+ if (((Boolean) colNames.get(i)[2]).booleanValue() && (facilities.keySet().size() > 1 || (facilities.keySet().size() == 1 && i >= 2))) {
+ report.print(UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale), InterfaceReport.FORMAT_WARNING);
+ cell = row.createCell(i);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale));
+ foundError = true;
+ results.add(null);
+ continue;
+ } else {
+ cell = row.createCell(i);
+ }
+ }
+ int cellType = cell.getCellType();
+ String cellValue = formatter.formatCellValue(cell);
+ if (UtilValidate.isNotEmpty(cellValue) && UtilValidate.isNotEmpty(cellValue.trim())) {
+ if (cellType == XSSFCell.CELL_TYPE_FORMULA) {
+ try {
+ cellValue = BigDecimal.valueOf(cell.getNumericCellValue()).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding).toString();
+ } catch (IllegalStateException e) {
+ try {
+ cellValue = cell.getStringCellValue();
+ } catch (IllegalStateException e1) {
+ // do nothing
+ }
+ }
+ report.print(((i == 0)?"":", ") + cellValue, InterfaceReport.FORMAT_NOTE);
+ } else {
+ report.print(((i == 0)?"":", ") + cellValue, InterfaceReport.FORMAT_NOTE);
+ }
+ } else {
+ report.print(((i == 0)?"":","), InterfaceReport.FORMAT_NOTE);
+ }
+ if (((Boolean) colNames.get(i)[2]).booleanValue() && UtilValidate.isEmpty(cellValue) && (facilities.keySet().size() > 1 || (facilities.keySet().size() == 1 && i >= 2))) {
+ report.print(UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale), InterfaceReport.FORMAT_WARNING);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale));
+ foundError = true;
+ results.add(null);
+ continue;
+ }
+ if (((Boolean) colNames.get(i)[2]).booleanValue() && cellType != (int) colNames.get(i)[1]) {
+ // String warningMessage = "";
+ if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_STRING) {
+ if (UtilValidate.isNotEmpty(cellValue) && UtilValidate.isNotEmpty(cellValue.trim())) {
+ results.add(cellValue);
+ } else {
+ results.add(null);
+ }
+ } else if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_NUMERIC) {
+ if (cell.getCellType() != XSSFCell.CELL_TYPE_STRING) {
+ cell.setCellType(XSSFCell.CELL_TYPE_STRING);
+ }
+ try {
+ results.add(BigDecimal.valueOf(Double.parseDouble(cell.getStringCellValue())).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ }
+ } else {
+ if (UtilValidate.isEmpty(cellValue) || UtilValidate.isEmpty(cellValue.trim())) {
+ results.add(null);
+ continue;
+ }
+ if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_STRING) {
+ if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
+ cellValue = cell.getStringCellValue().trim();
+ results.add(cellValue);
+ } else {
+ results.add(cellValue.trim());
+ }
+ } else if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_NUMERIC) {
+ if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
+ try {
+ results.add(BigDecimal.valueOf(Double.valueOf(cell.getStringCellValue())));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ } else if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC) {
+ try {
+ results.add(BigDecimal.valueOf(cell.getNumericCellValue()).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ } else {
+ try {
+ results.add(BigDecimal.valueOf(Double.valueOf(cellValue)).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ }
+ }
+ }
+ }
+ if (foundError) {
+ return null;
+ }
+ return results;
+ }
+
+ protected int getHeaderRowNo() {
+ return headerRowNo;
+ }
+}

Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/poi/xssf/usermodel/OFBizPricatUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/poi/xssf/usermodel/OFBizPricatUtil.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/poi/xssf/usermodel/OFBizPricatUtil.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/poi/xssf/usermodel/OFBizPricatUtil.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.poi.xssf.usermodel;
+
+import org.apache.poi.ss.util.CellReference;
+import com.microsoft.schemas.vml.CTShape;
+
+public final class OFBizPricatUtil {
+ public static void formatCommentShape(XSSFSheet sheet, CellReference cell) {
+        XSSFVMLDrawing vml = sheet.getVMLDrawing(true);
+        CTShape ctshape = vml.findCommentShape(cell.getRow(), cell.getCol());
+        ctshape.setType("#_x0000_t202");
+ }
+
+ public static void formatCommentShape(XSSFSheet sheet, int rowNum, short colNum) {
+        XSSFVMLDrawing vml = sheet.getVMLDrawing(true);
+        CTShape ctshape = vml.findCommentShape(rowNum, colNum);
+        ctshape.setType("#_x0000_t202");
+ }
+}

Added: ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/controller.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/controller.xml?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/controller.xml (added)
+++ ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/controller.xml Mon Nov 21 08:07:57 2016
@@ -0,0 +1,48 @@
+<?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.
+-->
+
+<site-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns="http://ofbiz.apache.org/Site-Conf" xsi:schemaLocation="http://ofbiz.apache.org/Site-Conf http://ofbiz.apache.org/dtds/site-conf.xsd">
+    <include location="component://common/webcommon/WEB-INF/common-controller.xml"/>
+    <include location="component://common/webcommon/WEB-INF/portal-controller.xml"/>
+
+    <description>PriCat</description>
+
+    <!-- define -->
+    <request-map uri="main">
+        <security https="true" auth="true"/>
+        <response name="success" type="view" value="main"/>
+    </request-map>
+
+    <request-map uri="downloadCommentedExcel">
+        <security https="true" auth="true"/>
+        <event type="java" path="org.apache.ofbiz.pricat.PricatEvents" invoke="downloadCommentedExcel"/>
+        <response name="success" type="none" />
+        <response name="error" type="none" />
+    </request-map>
+
+    <request-map uri="viewExcelImportLog">
+        <security https="true" auth="true"/>
+        <response name="success" type="view" value="viewExcelImportLog"/>
+    </request-map>
+    
+ <view-map name="main" type="screen" page="component://pricat/widget/CommonScreens.xml#viewExcelImportHistory"/>
+ <view-map name="viewExcelImportLog" type="screen" page="component://pricat/widget/CommonScreens.xml#viewExcelImportLog"/>
+</site-conf>

Added: ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/web.xml?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/web.xml (added)
+++ ofbiz/trunk/specialpurpose/pricat/webapp/pricat/WEB-INF/web.xml Mon Nov 21 08:07:57 2016
@@ -0,0 +1,100 @@
+<?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.
+-->
+
+<web-app version="3.0">
+
+    <display-name>Apache OFBiz - PriCat</display-name>
+    <description>PriCat Application of the Apache OFBiz Project</description>
+
+    <context-param>
+        <description>A unique name used to identify/recognize the local dispatcher for the Service Engine</description>
+        <param-name>localDispatcherName</param-name><param-value>pricat</param-value>
+    </context-param>
+    <context-param>
+        <description>The Name of the Entity Delegator to use, defined in entityengine.xml</description>
+        <param-name>entityDelegatorName</param-name><param-value>default</param-value>
+    </context-param>
+    <context-param>
+        <description>The location of the main-decorator screen to use for this webapp; referred to as a context variable in screen def XML files.</description>
+        <param-name>mainDecoratorLocation</param-name>
+        <param-value>component://pricat/widget/SampleScreens.xml</param-value>
+    </context-param>
+    <context-param>
+        <description>Remove unnecessary whitespace from HTML output.</description>
+        <param-name>compressHTML</param-name>
+        <param-value>false</param-value>
+    </context-param>
+
+    <filter>
+        <display-name>ControlFilter</display-name>
+        <filter-name>ControlFilter</filter-name>
+        <filter-class>org.apache.ofbiz.webapp.control.ControlFilter</filter-class>
+        <init-param>
+            <param-name>allowedPaths</param-name>
+            <param-value>/error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images:/js:/ws:/includes</param-value>
+        </init-param>
+        <init-param>
+            <param-name>redirectPath</param-name>
+            <param-value>/control/main</param-value>
+        </init-param>
+    </filter>
+    <filter>
+        <display-name>ContextFilter</display-name>
+        <filter-name>ContextFilter</filter-name>
+        <filter-class>org.apache.ofbiz.webapp.control.ContextFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>ControlFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+    <filter-mapping>
+        <filter-name>ContextFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <listener><listener-class>org.apache.ofbiz.webapp.control.ControlEventListener</listener-class></listener>
+    <listener><listener-class>org.apache.ofbiz.webapp.control.LoginEventListener</listener-class></listener>
+    <!-- NOTE: not all app servers support mounting implementations of the HttpSessionActivationListener interface -->
+    <!-- <listener><listener-class>org.apache.ofbiz.webapp.control.ControlActivationEventListener</listener-class></listener> -->
+
+    <servlet>
+        <description>Main Control Servlet</description>
+        <display-name>ControlServlet</display-name>
+        <servlet-name>ControlServlet</servlet-name>
+        <servlet-class>org.apache.ofbiz.webapp.control.ControlServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping><servlet-name>ControlServlet</servlet-name><url-pattern>/control/*</url-pattern></servlet-mapping>
+
+    <session-config>
+        <session-timeout>60</session-timeout><!-- in minutes -->
+        <cookie-config>
+          <http-only>true</http-only>
+          <secure>true</secure>
+        </cookie-config>
+        <tracking-mode>COOKIE</tracking-mode>
+    </session-config>
+
+    <welcome-file-list>
+        <welcome-file>index.jsp</welcome-file>
+        <welcome-file>index.html</welcome-file>
+        <welcome-file>index.htm</welcome-file>
+    </welcome-file-list>
+</web-app>

Added: ofbiz/trunk/specialpurpose/pricat/webapp/pricat/error/error.jsp
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/webapp/pricat/error/error.jsp?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/webapp/pricat/error/error.jsp (added)
+++ ofbiz/trunk/specialpurpose/pricat/webapp/pricat/error/error.jsp Mon Nov 21 08:07:57 2016
@@ -0,0 +1,52 @@
+<%--
+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.
+--%>
+<%@ page import="org.apache.ofbiz.base.util.*" %>
+<html>
+<head>
+<title>OFBiz Message</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<% String errorMsg = (String) request.getAttribute("_ERROR_MESSAGE_"); %>
+
+<body bgcolor="#FFFFFF">
+<div align="center">
+  <br/>
+  <table width="100%" border="1" height="200">
+    <tr>
+      <td>
+        <table width="100%" border="0" height="200">
+          <tr bgcolor="#CC6666">
+            <td height="45">
+              <div align="center"><font face="Verdana, Arial, Helvetica, sans-serif" size="4" color="#FFFFFF"><b>:ERROR MESSAGE:</b></font></div>
+            </td>
+          </tr>
+          <tr>
+            <td>
+              <div align="left"><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><%=UtilFormatOut.replaceString(errorMsg, "\n", "<br/>")%></font></div>
+            </td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+  </table>
+</div>
+<div align="center"></div>
+</body>
+</html>

Added: ofbiz/trunk/specialpurpose/pricat/webapp/pricat/ftl/ExcelImportHistoryReport.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/webapp/pricat/ftl/ExcelImportHistoryReport.ftl?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/webapp/pricat/ftl/ExcelImportHistoryReport.ftl (added)
+++ ofbiz/trunk/specialpurpose/pricat/webapp/pricat/ftl/ExcelImportHistoryReport.ftl Mon Nov 21 08:07:57 2016
@@ -0,0 +1,109 @@
+<#--
+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.
+-->
+<div class="row">
+ <div class="col-sm-12 m-b-xs text-left p-xs">
+ <label >${uiLabelMap.ExcelImportHistoryList}</label>
+ <span class="tooltip pad-left30 top">${uiLabelMap.OnlyYourOwnImportHistoryDisplayed}</span>
+ </div>
+</div>
+
+<div id="loadBody" style="display:none">
+</div>
+<table id="productlist" name="productlist" class="table table-striped ms-table-primary">
+ <thead>
+ <th></th>
+ <th>${uiLabelMap.SerialNumber}</th>
+ <th>${uiLabelMap.Filename}</th>
+ <th>${uiLabelMap.FromDate}</th>
+ <th>${uiLabelMap.ThruDate}</th>
+ <th>${uiLabelMap.ImportStatus}</th>
+ <th>${uiLabelMap.ThruReasonId}</th>
+ <th>${uiLabelMap.Actions}</th>
+ </thead>
+ <tbody>
+ <#if (data?has_content)>
+ <#list data as historyEntry>
+ <tr name="${historyEntry.sequenceNum!}">
+ <td>
+ <#if historyEntry.statusId?exists && historyEntry.statusId == 'EXCEL_IMPORTING'>
+ <img src="/erptheme/images/blue_anime.gif" alt="${uiLabelMap.EXCE_IMPORTING}" tooltip="${uiLabelMap.EXCE_IMPORTING}">
+ <#elseif historyEntry.statusId?exists && historyEntry.statusId == 'EXCEL_IMPORTED' && historyEntry.thruReasonId?exists && historyEntry.thruReasonId?has_content>
+ <#if historyEntry.thruReasonId == 'EXCEL_IMPORT_SUCCESS'>
+ <button id="excel-import-status" data-tooltip="${uiLabelMap.get(historyEntry.thruReasonId)}"><i class="icon-ok-sign success-color">${uiLabelMap.ReasonOK}</i></button>
+ <#elseif historyEntry.thruReasonId == 'EXCEL_IMPORT_STOPPED'>
+ <button id="excel-import-status" data-tooltip="${uiLabelMap.get(historyEntry.thruReasonId)}"><i class="icon-remove-sign stopped-color">${uiLabelMap.ReasonStopped}</i></button>
+ <#elseif historyEntry.thruReasonId == 'EXCEL_IMPORT_ERROR'>
+ <button id="excel-import-status" data-tooltip="${uiLabelMap.get(historyEntry.thruReasonId)}"><i class="icon-exclamation-sign error-color"></i>${uiLabelMap.ReasonError}</button>
+ <#elseif historyEntry.thruReasonId == 'EXCEL_IMPORT_QUEST'>
+ <button id="excel-import-status" data-tooltip="${uiLabelMap.get(historyEntry.thruReasonId)}"><i class="icon-question-sign question-color"></i>${uiLabelMap.ReasonWarning}</button>
+ </#if>
+ </#if>
+ </td>
+ <td>${historyEntry.sequenceNum!}</td>
+   <td style="text-align:right;">${historyEntry.fileName!}</td>
+ <td><#if historyEntry.fromDate?exists && historyEntry.fromDate?has_content>${historyEntry.fromDate?string("yyyy-MM-dd HH:mm:ss")}</#if></td>
+ <td><#if historyEntry.thruDate?exists && historyEntry.thruDate?has_content>${historyEntry.thruDate?string("yyyy-MM-dd HH:mm:ss")}</#if></td>
+ <td><#if historyEntry.statusId?exists && historyEntry.statusId?has_content>${uiLabelMap.get(historyEntry.statusId)}</#if></td>
+ <td><#if historyEntry.statusId?exists && historyEntry.statusId == "EXCEL_IMPORTED" && historyEntry.thruReasonId?exists && historyEntry.thruReasonId?has_content>${uiLabelMap.get(historyEntry.thruReasonId)}</#if></td>
+ <td>
+ <#assign buttons = 0 />
+ <#if historyEntry.logFileName?exists && historyEntry.logFileName?has_content>
+ <#if Static["org.apache.ofbiz.base.util.FileUtil"].getFile(historyEntry.logFileName).exists()>
+                     <button id="excel-import-log" type="button" onclick="viewExcelImportLog(${historyEntry.sequenceNum});" data-tooltip="${uiLabelMap.ViewExcelImportLogContent}">
+     <i class="icon-comments icon-blue">${uiLabelMap.ViewPricatLog}</i>
+     </button>
+     <#assign buttons = buttons + 1 />
+        </#if>
+                        </#if>
+ <#if buttons == 0>
+                     <#--- <button id="excel-import-empty" type="button"></button> -->
+     <#assign buttons = buttons + 1 />
+ </#if>
+ <#if historyEntry.logFileName?exists && historyEntry.logFileName?has_content>
+ <#if Static["org.apache.ofbiz.pricat.AbstractPricatParser"].isCommentedExcelExists(request, historyEntry.sequenceNum)>
+                     <button id="excel-import-download" type="button" onclick="downloadCommentedExcel(${historyEntry.sequenceNum});" data-tooltip="${uiLabelMap.DownloadCommentedExcel}">
+     <i class="icon-download icon-blue">${uiLabelMap.DownloadCommentedPricat}</i>
+     </button>
+     <#assign buttons = buttons + 1 />
+        </#if>
+                        </#if>
+ <#if buttons == 1>
+                     <#--- <button id="excel-import-empty" type="button"></button> -->
+ </#if>
+                    </td>
+ </tr>
+ </#list>
+ <#else>
+ <tr>
+ <td colspan="10" style="text-align:center;vertical-align:middle;height:60px;">
+ ${uiLabelMap.ExcelImportTipNoData}
+ </td>
+ </tr>
+ </#if>
+ </tbody>
+</table>
+<script type="text/javascript" language="JavaScript">
+ function viewExcelImportLog(sequenceNum) {
+        document.location = "<@ofbizUrl>viewExcelImportLog</@ofbizUrl>?sequenceNum=" + sequenceNum;
+    }
+
+ function downloadCommentedExcel(sequenceNum) {
+        document.location = "<@ofbizUrl>downloadCommentedExcel</@ofbizUrl>?sequenceNum=" + sequenceNum;
+    }
+</script>
\ No newline at end of file