intra-mart Accel Kaiden! プログラミングガイド 第11版 2019-12-01

4.5.2.1. IM-LogicDesigner拡張プログラミング

本項では、IM-LogicDesigner拡張プログラムを作成します。
個別で作成したガジェットを自動申請で使用したい場合、事前にガジェット(経費旅費) を参照して作成してください。
IM-LogicDesigner拡張プログラミングの詳細は『IM-LogicDesigner拡張プログラミングガイド』を参照してください。

4.5.2.1.1. 自動申請要素の引数クラスの作成

自動申請ジョブで使用する引数となるクラスを作成します。
Kaiden!ではサンプルとして、「TransitManagerRegisterParameter」クラスを提供しています。
package jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.transitmanager;

import java.util.List;
import java.util.Map;
import jp.co.intra_mart.foundation.logic.annotation.TypeHint;
import jp.co.slcs.kaiden2.base.foundation.model.dto.KaidenDto;

/**
 * TransitManager自動申請要素の引数クラス.
 * 
 * @author Sumitomo Life Information Systems Co.,Ltd.
 */
public class TransitManagerRegisterParameter extends KaidenDto {
    
    /** イベントデータ. */
    private List<Map<String, Object>> datas;
    /** イベント引数. */
    private Map<String, Object> args;
    
    /**
     * イベントデータを返却.
     *
     * @return イベントデータ
     */
    @TypeHint(Map.class)
    public List<Map<String, Object>> getDatas() {
        return datas;
    }
    
    /**
     * イベントデータを設定.
     *
     * @param datas イベントデータ
     */
    public void setDatas(List<Map<String, Object>> datas) {
        this.datas = datas;
    }
    
    /**
     * イベント引数を返却.
     * 
     * @return イベント引数
     */
    public Map<String, Object> getArgs() {
        return args;
    }
    
    /**
     * イベント引数を設定.
     * 
     * @param args イベント引数
     */
    public void setArgs(Map<String, Object> args) {
        this.args = args;
    }
    
}

4.5.2.1.2. 自動申請要素の戻り値クラスの作成

自動申請ジョブで使用する戻り値となるクラスを作成します。
Kaiden!ではサンプルとして、「TransitManagerRegisterResult」クラスを提供しています。
package jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.transitmanager;

/**
 * TransitManager自動申請要素の戻り値クラス.
 * 
 * @author Sumitomo Life Information Systems Co.,Ltd.
 */
public class TransitManagerRegisterResult extends TransitManagerRegisterParameter {
    
    /** システム案件ID. */
    private String systemMatterId;
    /** ユーザデータID. */
    private String userDataId;
    /** 処理ステータス. */
    private String status;
    /** メッセージ. */
    private String message;
    
    /**
     * コンストラクタ.
     */
    public TransitManagerRegisterResult() {
    }
    
    /**
     * システム案件IDを返却.
     * 
     * @return システム案件ID
     */
    public String getSystemMatterId() {
        return systemMatterId;
    }
    
    /**
     * システム案件IDを設定.
     * 
     * @param systemMatterId システム案件ID
     */
    public void setSystemMatterId(String systemMatterId) {
        this.systemMatterId = systemMatterId;
    }
    
    /**
     * ユーザデータIDを返却.
     * 
     * @return ユーザデータID
     */
    public String getUserDataId() {
        return userDataId;
    }
    
    /**
     * ユーザデータIDを設定.
     * 
     * @param userDataId ユーザデータID
     */
    public void setUserDataId(String userDataId) {
        this.userDataId = userDataId;
    }
    
    /**
     * 処理ステータスを返却.
     * 
     * @return 処理ステータス
     */
    public String getStatus() {
        return status;
    }
    
    /**
     * 処理ステータスを設定.
     * 
     * @param status 処理ステータス
     */
    public void setStatus(String status) {
        this.status = status;
    }
    
    /**
     * メッセージを返却.
     * 
     * @return メッセージ
     */
    public String getMessage() {
        return message;
    }
    
    /**
     * メッセージを設定.
     * 
     * @param message メッセージ
     */
    public void setMessage(String message) {
        this.message = message;
    }
}

4.5.2.1.3. 自動申請要素のメタデータクラスの作成

自動申請ジョブで使用するメタデータクラスを作成します。
getElementNameメソッドで返却している名称がパレット上に表示される名前となります。
コンストラクタ内で呼び出しているsuper()はフロー要素クラス作成後に、フロー要素クラスを指定してください。
Kaiden!ではサンプルとして、「TransitManagerRegisterTaskMetadata」クラスを提供しています。
package jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.transitmanager;

import jp.co.intra_mart.foundation.logic.element.metadata.FlowElementMetadata;
import jp.co.slcs.kaiden2.base.foundation.helper.PropertyHelper;
import jp.co.slcs.kaiden2.product_workflow.foundation.conf.ProductWorkflowProp;
import org.seasar.framework.container.SingletonS2Container;

/**
 * TransitManager自動申請要素のメタデータクラス.
 * 
 * @author Sumitomo Life Information Systems Co.,Ltd.
 */
public class TransitManagerRegisterTaskMetadata extends FlowElementMetadata {
    
    /**
     * コンストラクタ.
     */
    public TransitManagerRegisterTaskMetadata() {
        super(TransitManagerRegisterTask.class);
    }
    
    /**
     * パレット上の表示名を返却.
     * 
     * @return パレット上の表示名
     */
    @Override
    public String getElementName() {
        PropertyHelper propertyHelper = SingletonS2Container.getComponent(PropertyHelper.class);
        return propertyHelper.getSurface(ProductWorkflowProp.S.LogicDesigner.TRANSIT_MANAGER_REGISTER_NAME);
    }
}

4.5.2.1.4. 自動申請要素のフロー要素クラスの作成

自動申請ジョブで使用するフロー要素クラスを作成します。
Kaiden!ではサンプルとして、「TransitManagerRegisterTask」クラスを提供しています。
サンプルではinsertTableメソッドで「transit manager」から取得したデータを旅程明細のテーブルに挿入しています。
また、createApplyParamメソッドで申請情報を設定しています。
サンプルを参考に、業務要件にあわせてクラスを作成してください。
package jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.transitmanager;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jp.co.intra_mart.foundation.logic.annotation.LogicFlowElement;
import jp.co.intra_mart.foundation.logic.element.ElementContext;
import jp.co.intra_mart.foundation.logic.element.FlowElementCloser;
import jp.co.intra_mart.foundation.logic.element.Task;
import jp.co.intra_mart.foundation.logic.exception.FlowExecutionException;
import jp.co.intra_mart.foundation.workflow.application.model.ApplyResultModel;
import jp.co.intra_mart.foundation.workflow.application.model.param.ApplyParam;
import jp.co.intra_mart.foundation.workflow.application.process.ApplyManager;
import jp.co.intra_mart.foundation.workflow.exception.WorkflowException;
import jp.co.slcs.kaiden2.base.foundation.conf.ConstTransitManager;
import jp.co.slcs.kaiden2.base.foundation.helper.DateHelper;
import jp.co.slcs.kaiden2.base.foundation.helper.IdentifierHelper;
import jp.co.slcs.kaiden2.base.foundation.util.StringUtil;
import jp.co.slcs.kaiden2.extension_imw.feature.plugin.kaiden.workflow.ImwActionProcessPlugin;
import jp.co.slcs.kaiden2.product_workflow.foundation.model.entity.K30tRouteDetail;
import jp.co.slcs.kaiden2.product_workflow.foundation.model.service.K30tRouteDetailService;
import jp.co.slcs.kaiden2.product_workflow.foundation.plugin.logicdesigner.category.KaidenProductWorkflowCategory;
import net.arnx.jsonic.JSON;
import org.seasar.framework.beans.util.Beans;
import org.seasar.framework.container.SingletonS2Container;

/**
 * TransitManager自動申請要素クラス.
 * 
 * @author Sumitomo Life Information Systems Co.,Ltd.
 */
@LogicFlowElement(id = "TransitManagerRegister", category = KaidenProductWorkflowCategory.class, index = 100)
public class TransitManagerRegisterTask extends
        Task<TransitManagerRegisterTaskMetadata, TransitManagerRegisterParameter, TransitManagerRegisterResult>
        implements FlowElementCloser {
    
    /** K30tRouteDetailService. */
    protected K30tRouteDetailService k30tRouteDetailService;
    /** DateHelper. */
    protected DateHelper dateHelper;
    /** IdentifierHelper. */
    protected IdentifierHelper identifierHelper;
    
    /** システム案件ID. */
    private static final String SYSTEM_MATTER_ID = "systemMatterId";
    /** ユーザデータID. */
    private static final String USER_DATA_ID = "userDataId";
    /** フォーマットパターン:yyyy-MM-dd. */
    private static final String FORMAT_PATTERN_HAIFUN_YMD = "yyyy-MM-dd";
    
    /**
     * コンストラクタ.
     * 
     * @param context {@link ElementContext}
     */
    public TransitManagerRegisterTask(ElementContext context) {
        super(context);
        context.addFlowElementCloser(this);
        
        k30tRouteDetailService = SingletonS2Container.getComponent(K30tRouteDetailService.class);
        dateHelper = SingletonS2Container.getComponent(DateHelper.class);
        identifierHelper = SingletonS2Container.getComponent(IdentifierHelper.class);
    }
    
    /**
     * ロジックフロー実行.
     * 
     * @param parameter {@link TransitManagerRegisterParameter}
     */
    @Override
    public TransitManagerRegisterResult execute(TransitManagerRegisterParameter parameter)
            throws FlowExecutionException {
        TransitManagerRegisterResult result = new TransitManagerRegisterResult();
        Beans.copy(parameter, result).execute();
        
        result.setStatus("0");
        result.setMessage("自動申請成功");
        
        // 旅程明細テーブルへ登録
        int insertCnt = insertTable(parameter.getArgs(), parameter.getDatas());
        
        if (insertCnt > 0) {
            try {
                // 申請処理
                ApplyResultModel resultModel = apply(parameter.getArgs());
                
                result.setSystemMatterId(resultModel.getSystemMatterId());
                result.setUserDataId(resultModel.getUserDataId());
                
            } catch (WorkflowException e) {
                result.setStatus("1");
                result.setMessage("自動申請失敗");
            } finally {
                deleteTable(parameter.getArgs());
            }
        }
        
        return result;
    }
    
    /**
     * 後処理.
     */
    @Override
    public void close() {
    }
    
    /**
     * 旅程明細のテーブルにデータを登録する。
     * 
     * @param args 申請に必要なデータ
     * @param datas TMデータ
     */
    private int insertTable(Map<String, Object> args, List<Map<String, Object>> datas) {
        List<K30tRouteDetail> entityList = new ArrayList<K30tRouteDetail>();
        Long tupleId = 0L;
        Long rowNumber = 1L;
        for (Map<String, Object> map : datas) {
            
            K30tRouteDetail entity = new K30tRouteDetail();
            entity.systemMatterId = (String) args.get(SYSTEM_MATTER_ID);
            entity.userDataId = (String) args.get(USER_DATA_ID);
            entity.gadgetClass = "routeDetail";
            entity.gadgetVariation = "v03";
            entity.gadgetInstance = 0L;
            entity.tupleId = tupleId;
            entity.gadgetId = entity.gadgetClass + "_" + entity.gadgetVariation + "_" + entity.gadgetInstance;
            entity.rowNumber = rowNumber;
            
            entity.expTypeCd = "20100002";
            entity.accountCd = "31001011";
            entity.taxTypeCd = "V8";
            entity.taxRate = new BigDecimal("0.08");
            entity.quantity = BigDecimal.ONE;
            entity.transCurrencyCd = "JPY";
            entity.companyRate = BigDecimal.ONE;
            entity.companyCurrencyCd = "JPY";
            entity.payTypeCd = "0002";
            entity.departmentSetCd = "comp_sample_01";
            entity.departmentCd = "dept_sample_11";
            entity.projectCd = "000001";
            entity.roundTripFlag = "0";
            entity.routeLinkFlag = "0";
            
            // TransitManagerのデータの設定
            String categoryCd = (String) map.get(ConstTransitManager.CATEGORY_CODE);
            entity.routeDate = dateHelper.toTimestamp(converFormatDate((String) map.get(ConstTransitManager.PAY_DATE),
                    FORMAT_PATTERN_HAIFUN_YMD, DateHelper.FORMAT_PATTERN_SLASH_YMD));
            
            if (ConstTransitManager.TRAIN.equals(categoryCd)) {
                // 鉄道
                entity.startingSpot = (String) map.get(ConstTransitManager.STATION_NAME1);
                entity.arrivalSpot = (String) map.get(ConstTransitManager.STATION_NAME2);
            } else if (ConstTransitManager.BUS.equals(categoryCd)) {
                // バス
                entity.startingSpot = (String) map.get(ConstTransitManager.COMPANY_NAME1);
                entity.arrivalSpot = (String) map.get(ConstTransitManager.COMPANY_NAME1);
            } else if (ConstTransitManager.SALE.equals(categoryCd)) {
                // 物販
                entity.startingSpot = ConstTransitManager.DISP_SALE;
                entity.arrivalSpot = ConstTransitManager.DISP_SALE;
            }
            
            entity.supplement = (String) map.get(ConstTransitManager.MEMO);
            entity.transAmount = (BigDecimal) map.get(ConstTransitManager.PAYMENT);
            entity.companyAmount = (BigDecimal) map.get(ConstTransitManager.PAYMENT);
            entity.companyAmountSum = (BigDecimal) map.get(ConstTransitManager.PAYMENT);
            
            // TMキー
            String tmKey = (String) map.get(ConstTransitManager.USER_NO) + "_"
                    + map.get(ConstTransitManager.USER_CARD_NO) + "_" + map.get(ConstTransitManager.IC_RECORD_ID)
                    + "_0_" + map.get(ConstTransitManager.TM_APPLY_NO);
            entity.relationId = tmKey;
            entity.relationType = "searchTransitManager";
            
            Map<String, Object> camelMap = new HashMap<String, Object>();
            for (String key : map.keySet()) {
                String camelKey = StringUtil.snakeToCamel(key);
                camelMap.put(camelKey, map.get(key));
            }
            entity.relationData = JSON.encode(camelMap);
            
            entityList.add(entity);
            
            tupleId++;
            rowNumber++;
        }
        
        return k30tRouteDetailService.insertBatch(entityList).length;
    }
    
    /**
     * 登録したデータを削除する。
     * 
     * @param args
     * @return 削除件数
     */
    private int deleteTable(Map<String, Object> args) {
        
        Map<String, Object> criteria = new HashMap<String, Object>();
        criteria.put(SYSTEM_MATTER_ID, args.get(SYSTEM_MATTER_ID));
        criteria.put(USER_DATA_ID, args.get(USER_DATA_ID));
        
        List<K30tRouteDetail> entityList = k30tRouteDetailService.genericSelectList(criteria);
        
        return k30tRouteDetailService.deleteBatch(entityList).length;
    }
    
    /**
     * 申請処理.
     * 
     * @param args
     * @return result 申請結果
     * @throws WorkflowException
     */
    private ApplyResultModel apply(Map<String, Object> args) throws WorkflowException {
        ApplyManager applyManager = new ApplyManager();
        
        ApplyParam applyParam = createApplyParam(args);
        
        Map<String, Object> userParam = createUserParam(args);
        Map<String, Object> copyData = new HashMap<String, Object>();
        copyData.put(SYSTEM_MATTER_ID, args.get(SYSTEM_MATTER_ID));
        copyData.put(USER_DATA_ID, args.get(USER_DATA_ID));
        userParam.put("copyTarget", copyData);
        
        // 申請処理
        return applyManager.apply(applyParam, userParam);
        
    }
    
    /**
     * ApplyParamを生成する。.
     * 
     * @param k30mTmAutoApply
     * @param k30mTmAutoUser
     * @return ApplyParam
     */
    private ApplyParam createApplyParam(Map<String, Object> args) {
        ApplyParam applyParam = new ApplyParam();
        
        applyParam.setFlowId("0_test"); // フローID
        applyParam.setMatterName("自動登録"); // 案件名
        applyParam.setApplyBaseDate(dateHelper.getNowStringYYYYMMDD()); // 申請基準日
        applyParam.setApplyAuthUserCode((String) args.get("userCd")); // 申請権限者
        applyParam.setApplyExecuteUserCode((String) args.get("userCd")); // 申請実行者
        applyParam.setApplyAuthCompanyCode((String) args.get("companyCd")); // 権限者会社コード
        applyParam.setApplyAuthOrgzCode("comp_sample_01"); // 権限者組織コード
        applyParam.setApplyAuthOrgzSetCode((String) args.get("companyCd")); // 権限者組織セットコード
        applyParam.setUserDataId(identifierHelper.get()); // ユーザデータID
        
        return applyParam;
    }
    
    /**
     * UserParamを生成する。.
     * 
     * @return UserParam ユーザパラメータ
     */
    private Map<String, Object> createUserParam(Map<String, Object> args) {
        
        Map<String, Object> userParam = new HashMap<String, Object>();
        userParam.put(ImwActionProcessPlugin.SEND_DATA_FLAG, "true");
        userParam.put(ImwActionProcessPlugin.SEARCH_CRITERIA_COMPANY_KEY, args.get("companyCd"));
        userParam.put(ImwActionProcessPlugin.SEARCH_CRITERIA_DATE_KEY, dateHelper.getNowStringYYYYMMDD());
        
        return userParam;
    }
    
    /**
     * 日付形式変換.
     * formatterBefore 形式から formatterAfter 形式へ変換する。
     * dateが空白またはnullの場合、nullを返却する。
     * 
     * @param date 変換したい値
     * @param formatterBefore 変換前フォーマット
     * @param formatterAfter 変換後フォーマット
     * @return
     */
    private String converFormatDate(String date, String formatterBefore, String formatterAfter) {
        if (StringUtil.isEmpty(date)) {
            return null;
        }
        Date payDate = dateHelper.toDate(date, formatterBefore);
        return dateHelper.toFormat(payDate, formatterAfter);
    }
}