ProcessReworkAction.java

/*
 *        @ Copyright 2001 FA Software;
 *        All right reserved. No part of this program may be reproduced or
 *        transmitted in any form or by any means, electronic or
 *        mechanical, including photocopying, recording, or by any
 *        information storage or retrieval system without written
 *        permission from FA Software, except for inclusion of brief
 *        quotations in a review.
 */
package com.mycim.webapp.actions.process;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.framework.utils.lang.time.DateUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.consts.VersionStatus;
import com.mycim.valueobject.prp.*;
import com.mycim.webapp.TemplateLocation;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.PrpSetupAction;
import com.mycim.webapp.forms.ProcessReworkForm;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.write.WritableFont;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.lang.Override;
import java.util.*;

public class ProcessReworkAction extends PrpSetupAction {

    private static final String CN = "cn";

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm theform, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        ProcessReworkForm form = (ProcessReworkForm) theform;
        String processId = form.getInstanceId();

        Assert.isFalse(StringUtils.isEmpty(processId),
                       Errors.create().key(MessageIdList.PROCESS_INVALID).content("Invalid process id!").build());

        ProcessPlanning processPlanning = new ProcessPlanning(processId, getNamedSpace(ObjectList.WFL_KEY,
                                                                                       LocalContext.getFacilityRrn()),
                                                              ObjectList.WFL_KEY);

        processPlanning = (ProcessPlanning) getInstance(processPlanning);

        ProcessVersion processVersion = prpService
                .getProcessVersion(processPlanning.getInstanceRrn(), Integer.parseInt(form.getVersionId()));

        form.setInstanceId(processId);
        form.setVersionId(processVersion.getVersionId());
        form.setVersionStatus(processVersion.getVersionStatus());
        form.setProcessReworkInfos(prpService.processReworkInfoList(processId, Integer.parseInt(form.getVersionId())));
        form.setNpwType(processPlanning.getAttribute3());
        return mapping.getInputForward();
    }

    public ActionForward addProcessRework(ActionMapping mapping, HttpServletRequest request, ProcessReworkForm theform,
                                          HttpServletResponse response) throws Exception {

        ProcessPlanning processPlanning = new ProcessPlanning(theform.getInstanceId(), getNamedSpace(ObjectList.WFL_KEY,
                                                                                                     LocalContext
                                                                                                             .getFacilityRrn()),
                                                              ObjectList.WFL_KEY);

        processPlanning = (ProcessPlanning) getInstance(processPlanning);

        ProcessVersion processVersion = prpService
                .getProcessVersion(processPlanning.getInstanceRrn(), Integer.parseInt(theform.getVersionId()));

        if (StringUtils.isNotBlank(theform.getRouteIdByStep())) {
            theform.setRouteId(theform.getRouteIdByStep());
        } else {
            theform.setRouteId(theform.getRouteIdByRoute());
        }

        List<String> operationIdList = null;
        if (StringUtils.equalsIgnoreCase("byRoute", theform.getAddWay())) {
            operationIdList = validateReworkSetForBatch(theform, processVersion.getInstanceVersion(),
                                                        LocalContext.getFacilityRrn());
        } else {
            operationIdList = validateReworkSet(theform, processVersion.getInstanceVersion(),
                                                LocalContext.getFacilityRrn());
        }

        //返工路径如果已经在流程中,不允许添加,为了避免reseq重复#32470
        List<Map<String, Object>> allRouteByProcess = prpService
                .getAllRouteByProcess(processPlanning.getInstanceId(), processVersion.getInstanceVersion());
        for (Map<String, Object> map : allRouteByProcess) {
            String routeId = MapUtils.getString(map, "routeId");
            Assert.isFalse(StringUtils.equalsIgnoreCase(StringUtils.trim(theform.getReworkRouteId()), routeId),
                           Errors.create().content("'{}' is already in the process, cannot be added!").args(routeId)
                                 .build());
        }
        //判断是否是返工路径
        Route route = new Route(theform.getReworkRouteId(),
                                getNamedSpace(ObjectList.WFL_KEY, LocalContext.getFacilityRrn()), ObjectList.WFL_KEY);
        route = prpService.getRoute(route);
        Assert.isFalse(route != null && !StringUtils.STRING_ON.equalsIgnoreCase(route.getReworkFlag()),
                       Errors.create().content("'{}' is not a RWK Sub Plan").args(theform.getReworkRouteId()).build());


        // 2019-02-22 lvyue 需求变动,start step改为所在工序的第一个工步
        // 如果工序的第一个工步是流程的第一个工步,则改为该工序的第二个工步
        String returnOperationId = StringUtils.EMPTY;
        if (StringUtils.isBlank(theform.getReturnRouteId())) {
            String returnRouteId = theform.getRouteId();
            Map<String, Object> firstOperationMap = prpService
                    .getFirstStepInProcessRoute(theform.getInstanceId(), processVersion.getInstanceVersion(),
                                                returnRouteId);
            if (MapUtils.isNotEmpty(firstOperationMap)) {
                returnOperationId = MapUtils.getString(firstOperationMap, "operationId");
            }
        } else {
            returnOperationId = StringUtils.trimToUpperCase(theform.getReturnOperationId());
        }
        String returnRouteId = StringUtils.isBlank(theform.getReturnRouteId()) ? StringUtils
                .trimToUpperCase(theform.getRouteId()) : StringUtils.trimToUpperCase(theform.getReturnRouteId());
        if (!StringUtils.equalsIgnoreCase("byRoute", theform.getAddWay())) {
            // 已存在相同sub plan id下的rework设置,但是return的sub plan id和step id不同,不能添加rework信息
            Assert.isTrue(prpService
                                  .equalsReworkReturnInfo(theform.getInstanceId(), processVersion.getInstanceVersion(),
                                                          theform.getRouteId(), returnRouteId, returnOperationId),
                          Errors.create().key(MessageIdList.REWORK_RETURN_DIFFERENT).content(
                                  "已存在相同sub plan " + "id下的rework" + "设置,但是return" + "的sub plan " + "id和step " + "id" +
                                          "不同,不能添加rework信息").build());
        }
        //相同subPlan下的返工次数需一致
        Assert.isTrue(prpService.equalsReworkMaxTimes(theform.getInstanceId(), processVersion.getInstanceVersion(),
                                                      theform.getRouteId(), theform.getReworkMaxTimes()),
                      Errors.create().key(MessageIdList.REWORK_MAXTIMES_DIFFERENT)
                            .content("应与已经设置的sub plan下的最大返工次数保持相同").build());

        if (CollectionUtils.isNotEmpty(operationIdList) && StringUtils.isNotBlank(returnOperationId)) {

            int reworkRouteActiveVersion = 0;
            String reworkRouteId = StringUtils.trimToUpperCase(theform.getReworkRouteId());

            Long reworkRouteRrn = getInstanceRrn(StringUtils.trimToUpperCase(theform.getReworkRouteId()),
                                                 LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);

            reworkRouteActiveVersion = baseService.getActiveVersion(reworkRouteRrn, true);

            Assert.isTrue(reworkRouteActiveVersion > 0,
                          Errors.create().key(MessageIdList.ROUTE_NO_ACTIVE_VERSION).content("{} is no active version!")
                                .args(reworkRouteId).build());

            for (int i = 0; i < operationIdList.size(); i++) {
                ReworkRouteContextValue contextValue = ctxExecService.buildNewReworkRouteContextValue();
                contextValue.setStatus(VersionStatus.ACTIVE_KEY);
                contextValue.setContextKey2(theform.getInstanceId());
                contextValue.setContextKey3(StringUtils.trimToUpperCase(theform.getRouteId()));
                // contextValue.setContextKey4(StringUtils.trimToUpperCase(theform.getOperationId()));
                contextValue.setContextKey4(
                        StringUtils.trimToUpperCase(StringUtils.trimToUpperCase(operationIdList.get(i))));
                contextValue.setContextKey8(StringUtils.toString(processVersion.getInstanceVersion()));

                contextValue.setResultValue1(StringUtils.trimToUpperCase(theform.getReworkRouteId()));
                contextValue.setResultValue2(returnRouteId);
                contextValue.setResultValue3(returnOperationId);

                contextValue.setResultValue4(StringUtils.toString(theform.getReworkMaxTimes()));
                contextValue.setReworkRouteVersion(reworkRouteActiveVersion);
                contextValue.setCountWay(theform.getAddWay());

                ctxService.createOrUpdateContextValueWithActivatedEcn(contextValue);
            }

            // 将流程下设置的相同的 Rework Route 的 Version 信息更新至最新版
            List<ContextValue> contextValues = prpService
                    .listContextValuesFilterReworkRouteId(LocalContext.getFacilityRrn(), theform.getInstanceId(),
                                                          processVersion.getInstanceVersion(), reworkRouteId);
            prpService.updateReworkRouteVersion4Add(contextValues, reworkRouteActiveVersion);
        }

        return init(mapping, theform, request, response);
    }

    public ActionForward delete(ActionMapping mapping, HttpServletRequest request, ProcessReworkForm theform,
                                HttpServletResponse response) throws Exception {
        String routeId = WebUtils.getParameterUpperCase("routeId", request);
        String operationId = WebUtils.getParameterUpperCase("operationId", request);
        String countWay = WebUtils.getParameterUpperCase("countWay", request);

        ReworkRouteContextValue contextValue = ctxExecService.buildNewReworkRouteContextValue();

        contextValue.setContextKey2(theform.getInstanceId());
        contextValue.setContextKey3(routeId);
        contextValue.setContextKey4(operationId);
        contextValue.setContextKey8(StringUtils.toString(theform.getVersionId()));

        contextValue.setCountWay(countWay);

        prpService.deleteReworkRouteContextValue(contextValue);

        return init(mapping, theform, request, response);
    }

    public ActionForward export(HttpServletRequest request, ProcessReworkForm theForm,
                                HttpServletResponse response) throws Exception {
        Map<String, Object> titles = WebUtils.getExportTitles(request);
        String processId = theForm.getInstanceId();

        String exportDateTime = DateUtils.getNowTime(DateUtils.DATE_FORMAT4NOSPLICING);
        List data = prpService.processReworkInfoList(processId, Integer.parseInt(theForm.getVersionId()));

        String fileName = "ProcessReworkSetup_" + exportDateTime + ".xlsx";

        if (StringUtils.equalsIgnoreCase(CN, I18nUtils.getCurrentLanguage().toString())) {
            titles.put("title", "流程返工设置信息");
        } else {
            titles.put("title", "Process Rework Setup");
        }
        titles.put("titleProcessId", "Process ID:" + processId);
        titles.put("titleProcessVersion", "Process Ver.:" + theForm.getVersionId());
        WebUtils.exportExcel(fileName, titles, data, TemplateLocation.PROCESS_REWORK_SETUP, response);
        return WebUtils.NULLActionForward;
    }

    private List<String> validateReworkSetForBatch(ProcessReworkForm theform, int processVersion, Long facilityRrn) {
        List<String> operationIdList = new ArrayList<String>();

        Long processRrn = getInstanceRrn(theform.getInstanceId(), facilityRrn, ObjectList.WFL_KEY);
        Map<String, Object> matchingRules = new HashMap<String, Object>();
        matchingRules.put("processRrn", processRrn);

        List wflTree = prpService.getWorkFlowTree(processRrn, processVersion, matchingRules);
        Assert.isFalse(wflTree == null || wflTree.isEmpty(),
                       Errors.create().key(MessageIdList.EDITOR_MUST_SAVE).content("Please save in process editor!")
                             .build());

        String routeId = StringUtils.trimToUpperCase(theform.getRouteId());
        Assert.isFalse(StringUtils.isBlank(routeId),
                       Errors.create().key(MessageIdList.ROUTE_CANNOT_EMPTY).content("Sub plan cannot be empty!")
                             .build());
        Long routeRrn = getInstanceRrn(routeId, facilityRrn, ObjectList.WFL_KEY);
        Assert.isFalse(routeRrn == null || routeRrn.longValue() == 0,
                       Errors.create().content("Sub plan didnot exist!").build());

        Assert.isTrue(isExistInWFL(processVersion, processRrn, null, routeId, ObjectList.WFL_KEY),
                      Errors.create().content("Sub plan do not exist in the process!").build());

        List<Map<String, Object>> routeTree = prpService
                .qryProcessInfoInProcessTree(processRrn, processVersion, routeRrn, null);
        Assert.isTrue(CollectionUtils.isNotEmpty(routeTree),
                      Errors.create().content("No step infomation under the route!").build());
        Boolean isFirstStepInProcess = false;
        for (Map<String, Object> map : routeTree) {
            isFirstStepInProcess = prpService.isFirstStepInProcess(null, processRrn, processVersion, routeRrn,
                                                                   MapUtils.getLong(map, "operationRrn"));
            if (isFirstStepInProcess) {
                // 过滤掉流程第一个工步
            } else {
                operationIdList.add(MapUtils.getString(map, "operationId"));
            }
        }

        Assert.isFalse(isFirstStepInProcess && operationIdList.size() <= 0,
                       Errors.create().content("Step cannot be the first " + "step in process!").build());

        String reworkRouteId = StringUtils.trimToUpperCase(theform.getReworkRouteId());
        Assert.isFalse(StringUtils.isBlank(reworkRouteId),
                       Errors.create().key(MessageIdList.REWORK_EMPTY).content("rework empty").build());
        Long reworkRouteRrn = getInstanceRrn(reworkRouteId, facilityRrn, ObjectList.WFL_KEY);
        Assert.isFalse(reworkRouteRrn == null || reworkRouteRrn.longValue() == 0,
                       Errors.create().key(MessageIdList.REWORK_MISSING_SUB_PLAN).content("rework sub plab miss")
                             .build());
        Route route = new Route(reworkRouteId, getNamedSpace(ObjectList.WFL_KEY, LocalContext.getFacilityRrn()),
                                ObjectList.WFL_KEY);
        route = (Route) getInstance(route);
        Assert.isTrue(StringUtils.equals(route.getReworkFlag(), "on"),
                      Errors.create().key(MessageIdList.REWORK_ROUTEID_HAS_NOT_REWORKFLAG)
                            .content("rework route has not " + "rework flag").build());

        String returnRouteId = StringUtils.trimToUpperCase(theform.getReturnRouteId());
        String returnOperationId = StringUtils.trimToUpperCase(theform.getReturnOperationId());
        if (StringUtils.isNotBlank(returnRouteId)) {
            Long returnRouteRrn = getInstanceRrn(returnRouteId, facilityRrn, ObjectList.WFL_KEY);
            Assert.isFalse(returnRouteRrn == null || returnRouteRrn.longValue() == 0,
                           Errors.create().content("Return sub plan " + "didnot " + "exist!").build());

            Long returnStepRrn = getInstanceRrn(returnOperationId, facilityRrn, ObjectList.OPERATION_KEY);
            Assert.isFalse(returnStepRrn == null || returnStepRrn.longValue() == 0,
                           Errors.create().content("Return step didnot" + " exist!").build());

            Assert.isTrue(isExistInWFL(processVersion, processRrn, null, returnRouteId, ObjectList.WFL_KEY),
                          Errors.create().content("Return sub plan do not exist in the process!").build());

            Assert.isTrue(isExistInWFL(processVersion, processRrn, returnRouteRrn, returnOperationId,
                                       ObjectList.OPERATION_KEY),
                          Errors.create().content("Return step do not exist in " + "the" + " return sub plan!")
                                .build());
        }

        return operationIdList;
    }

    private List<String> validateReworkSet(ProcessReworkForm theform, int processVersion, Long facilityRrn) {
        List<String> operationIdList = new ArrayList<String>();

        Long processRrn = getInstanceRrn(theform.getInstanceId(), facilityRrn, ObjectList.WFL_KEY);
        Map<String, Object> matchingRules = new HashMap<String, Object>();
        matchingRules.put("processRrn", processRrn);

        List wflTree = prpService.getWorkFlowTree(processRrn, processVersion, matchingRules);
        Assert.isFalse(wflTree == null || wflTree.isEmpty(),
                       Errors.create().key(MessageIdList.EDITOR_MUST_SAVE).content("Please save in process editor!")
                             .build());

        String routeId = StringUtils.trimToUpperCase(theform.getRouteId());
        Assert.isFalse(StringUtils.isBlank(routeId),
                       Errors.create().key(MessageIdList.ROUTE_CANNOT_EMPTY).content("Sub plan cannot be empty!")
                             .build());
        Long routeRrn = getInstanceRrn(routeId, facilityRrn, ObjectList.WFL_KEY);

        Assert.isFalse(routeRrn == null || routeRrn.longValue() == 0,
                       Errors.create().key(MessageIdList.ROUTE_MISSING).content("Sub plan didnot exist!").build());
        Assert.isTrue(isExistInWFL(processVersion, processRrn, null, routeId, ObjectList.WFL_KEY),
                      Errors.create().key(MessageIdList.ROUTE_MISSING_IN_PROCESS)
                            .content("Sub plan do not exist in the process!").build());

        Long stepRrn = new Long(0);
        String operationId = StringUtils.trimToUpperCase(theform.getOperationId());
        if (StringUtils.isNotBlank(operationId)) {
            stepRrn = getInstanceRrn(operationId, facilityRrn, ObjectList.OPERATION_KEY);
            Assert.isFalse(stepRrn == null || stepRrn.longValue() == 0,
                           Errors.create().key(MessageIdList.STEP_EXIST).content("Step didnot exist!").build());

            Assert.isTrue(isExistInWFL(processVersion, processRrn, routeRrn, operationId, ObjectList.OPERATION_KEY),
                          Errors.create().key(MessageIdList.STEP_MISSING_ROUTE)
                                .content("Step do not exist in the sub plan!").build());

            Boolean isFirstStepInProcess = prpService
                    .isFirstStepInProcess(null, processRrn, processVersion, routeRrn, stepRrn);
            Assert.isFalse(isFirstStepInProcess, Errors.create().key(MessageIdList.STEP_CANNOT_IN_PROCESS)
                                                       .content("Step cannot be the first step in process!").build());
        }

        String reworkRouteId = StringUtils.trimToUpperCase(theform.getReworkRouteId());
        Assert.isFalse(StringUtils.isBlank(reworkRouteId),
                       Errors.create().key(MessageIdList.REWORK_EMPTY).content("rework empty").build());
        Long reworkRouteRrn = getInstanceRrn(reworkRouteId, facilityRrn, ObjectList.WFL_KEY);
        Assert.isFalse(reworkRouteRrn == 0,
                       Errors.create().key(MessageIdList.REWORK_MISSING_SUB_PLAN).content("rework sub plan miss")
                             .build());

        String returnRouteId = StringUtils.trimToUpperCase(theform.getReturnRouteId());
        String returnOperationId = StringUtils.trimToUpperCase(theform.getReturnOperationId());
        if (!StringUtils.isEmpty(returnRouteId)) {
            routeRrn = getInstanceRrn(returnRouteId, facilityRrn, ObjectList.WFL_KEY);
            Assert.isFalse(routeRrn == 0, Errors.create().key(MessageIdList.ROUTE_RETURN_NOT_EXIST)
                                                .content("Return sub plan didnot exist!").build());

            stepRrn = getInstanceRrn(returnOperationId, facilityRrn, ObjectList.OPERATION_KEY);
            Assert.isFalse(stepRrn == 0,
                           Errors.create().key(MessageIdList.STEP_NOT_EXIST).content("Return step didnot exist!")
                                 .build());

            Assert.isTrue(isExistInWFL(processVersion, processRrn, null, returnRouteId, ObjectList.WFL_KEY),
                          Errors.create().key(MessageIdList.ROUTE_MISSING_IN_PROCESS)
                                .content("Return sub plan do not exist in the process!").build());

            Assert.isTrue(
                    isExistInWFL(processVersion, processRrn, routeRrn, returnOperationId, ObjectList.OPERATION_KEY),
                    Errors.create().key(MessageIdList.STEP_MISSING_IN_PROCESS)
                          .content("Return step do not exist in " + "the return sub plan!").build());
        } else {
            routeRrn = getInstanceRrn(routeId, facilityRrn, ObjectList.WFL_KEY);
            stepRrn = getInstanceRrn(operationId, facilityRrn, ObjectList.OPERATION_KEY);
        }

        Boolean isFirstStepInProcess = prpService
                .isFirstStepInProcess(null, processRrn, processVersion, routeRrn, stepRrn);
        Assert.isFalse(isFirstStepInProcess, Errors.create().key(MessageIdList.CYCLE_CANNOT_FIRST_STEP).build());

        operationIdList.add(StringUtils.trimToUpperCase(theform.getOperationId()));
        return operationIdList;
    }

    private boolean isExistInWFL(int processVersion, Long processRrn, Long wflRrn, String stepId, String type) {
        long stepRrnInWfl;
        if (StringUtils.equals(type, ObjectList.OPERATION_KEY)) {
            int routeVersion = prpService.getWFLVersionByProcess(processRrn, processVersion, wflRrn);
            stepRrnInWfl = prpService.getStepRrnForStep(wflRrn, stepId, routeVersion);
        } else {
            stepRrnInWfl = prpService.getStepRrnForStep(processRrn, stepId, processVersion);
        }
        return stepRrnInWfl != 0;
    }

    private ActionForward export(ActionMapping mapping, HttpServletRequest request, ProcessReworkForm theform,
                                 HttpServletResponse response) throws Exception {
        List<Map<String, String>> reworkInfos = prpService
                .processReworkInfoList(theform.getInstanceId(), NumberUtils.toInt(theform.getVersionId()));
        ByteArrayOutputStream os = (ByteArrayOutputStream) createWorkBookByRework(theform, reworkInfos, request);

        ServletOutputStream out = response.getOutputStream();

        response.setHeader("Content-Disposition", "attachment;filename=ProcessReworkSetup_" +
                DateUtils.getNowTime(DateUtils.DATE_FORMAT4NOSPLICING) + ".xls");
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        out.write(os.toByteArray());
        out.flush();
        out.close();

        return WebUtils.NULLActionForward;
    }

    private OutputStream createWorkBookByRework(ProcessReworkForm theform, List<Map<String, String>> reworkInfos,
                                                HttpServletRequest request) throws Exception {
        OutputStream os = new ByteArrayOutputStream();
        jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os);
        String excelTitle = "";
        if (StringUtils.equalsIgnoreCase("CN", I18nUtils.getCurrentLanguage().toString())) {
            excelTitle = "流程返工设置信息";
        } else {
            excelTitle = "Process Rework Setup";
        }

        jxl.write.WritableSheet ws = wwb.createSheet(excelTitle, 0);
        jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TAHOMA, 20, WritableFont.BOLD, true);
        jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf);
        wcfF.setAlignment(Alignment.CENTRE);

        ws.mergeCells(0, 0, 10, 0);
        jxl.write.Label labelTitle = new jxl.write.Label(0, 0, excelTitle, wcfF);
        ws.addCell(labelTitle);

        jxl.write.Label labelColes = null;
        jxl.write.WritableFont wfs = new jxl.write.WritableFont(WritableFont.ARIAL, 12, WritableFont.BOLD, false);
        jxl.write.WritableCellFormat wfColes = new jxl.write.WritableCellFormat(wfs);
        wfColes.setAlignment(Alignment.CENTRE);

        labelColes = new jxl.write.Label(2, 3, "Process ID:" + theform.getInstanceId(), wfColes);
        ws.addCell(labelColes);
        labelColes = new jxl.write.Label(6, 3, "Process Ver.:" + theform.getVersionId(), wfColes);
        ws.addCell(labelColes);

        jxl.write.Label labelCols = null;
        jxl.write.WritableCellFormat wfCols = new jxl.write.WritableCellFormat();
        wfCols.setBorder(Border.ALL, BorderLineStyle.THIN, Colour.BLACK);

        String[] columnTitleArray = null;
        if (StringUtils.equalsIgnoreCase("EN", I18nUtils.getCurrentLanguage().toString())) {
            columnTitleArray = new String[]{"No.", "Sub Plan ID", "Flow seq", "Step ID", "RWK Sub Plan",
                    "Rtn Sub " + "Plan ID", "Return Flow Seq", "Rtn Step ID", "Rework Count"};
        } else {
            columnTitleArray = new String[]{"序号", "工序", "序号", "工步", "返工工序", "返回工序", "返回序号", "返回工步", "返工次数"};
        }

        int j = 0;
        for (int i = 0; i < columnTitleArray.length; i++) {
            ws.setColumnView(i, 15);
            labelCols = new jxl.write.Label(j++, 5, columnTitleArray[i], wfCols);
            ws.addCell(labelCols);
        }

        Iterator it = reworkInfos.iterator();

        jxl.write.Number numberValue = null;
        jxl.write.Label stringValue = null;
        int i = 6;
        int seq = 1;
        j = 0;

        while (it.hasNext()) {
            Map<String, Object> reworkInfoM = (Map<String, Object>) it.next();
            numberValue = new jxl.write.Number(j++, i, seq++, wfCols);
            ws.addCell(numberValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "routeId"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "flowSeq"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "operationId"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "reworkRouteId"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "returnRouteId"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "returnFlowSeq"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "returnOperationId"), wfCols);
            ws.addCell(stringValue);
            stringValue = new jxl.write.Label(j++, i, MapUtils.getString(reworkInfoM, "maxReworkTimes"), wfCols);
            ws.addCell(stringValue);

            j = 0;
            i++;
        }

        if (wwb != null) {
            wwb.write();
            wwb.close();
        }

        return os;
    }

}