diff --git a/plugin/kintone-addins/src/actions/datetime-calc.ts b/plugin/kintone-addins/src/actions/datetime-calc.ts new file mode 100644 index 0000000..ae72a57 --- /dev/null +++ b/plugin/kintone-addins/src/actions/datetime-calc.ts @@ -0,0 +1,202 @@ +import { actionAddins } from "."; +import { IAction, IActionResult, IActionNode, IActionProperty, IField ,IContext, IVarName} from "../types/ActionTypes"; + +/** + * アクションの属性定義 + */ +interface IDateTimeCalcProps{ + verName:IVarName; + calcOption:string; + resultVerName:string; + year:string; + month:string; + date:string; + hour:string; + minute:string; + second:string; +} + +/** + * + */ +export class DateTimeCalcAction implements IAction{ + name: string; + actionProps: IActionProperty[]; + props:IDateTimeCalcProps; + constructor(){ + this.name="日時を加算/減算する";// DBに登録したアクション名 + this.actionProps=[]; + //プロパティ属性の初期化 + this.props={ + verName:{name:''}, + calcOption:'', + resultVerName:'', + year:"0", + month:"0", + date:"0", + hour:"0", + minute:"0", + second:"0" + } + //アクションを登録する + this.register(); + } + + /** + * 基準日となる変数の値が、日付・日時の形式であるか、判断する + * @param {string} dateValue + * @returns {boolean} + */ + isDateValue(dateValue :string){ + let date; + + //正規表現チェック + let singleDigitMonth = dateValue.match(/(\d{4})-(\d{1})-(\d{1})$/);//4桁の数字-1桁の数字-2桁の数字 + let twoDigitMonth = dateValue.match(/(\d{4})-(\d{2})-(\d{2})$/);//4桁の数字-2桁の数字-2桁の数字 + let singleDigitDate = dateValue.match(/(\d{4})-(\d{2})-(\d{1})$/);//4桁の数字-2桁の数字-1桁の数字 + let twoDigitDate = dateValue.match(/(\d{4})-(\d{1})-(\d{2})$/);//4桁の数字-1桁の数字-2桁の数字 + let dateTimeMilliSecond = dateValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).(\d{2,3})Z$/);//時刻入りのUTCの日付形式(ミリ秒) + let dateTime = dateValue.match(/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/);//時刻入りのUTCの日付形式 + + //date型に変換 + date = new Date(dateValue); + + //date型変換できたか確認 + if(date !== undefined && !isNaN(date.getDate())){ + //正規表現チェック確認 + if(twoDigitMonth === null && singleDigitMonth === null && singleDigitDate === null && twoDigitDate === null && dateTime === null && dateTimeMilliSecond === null){ + throw new Error("計算の基準日となる値が、適切な日付・日時の形式ではありません。「日時を加算/減算する」コンポーネントの処理を中断しました。"); + } + } + return true; + } + + /** + * 値を数値に変換する + * @param {any} context + * @param {string} calcValue,calcOption + * @returns {number} + */ + valueToNumber(context :any,calcValue :string,calcOption :string): number{ + + const getContextVarByPath = (obj: any, path: string) => { + return path.split(".").reduce((o, k) => (o || {})[k], obj); + }; + + //計算値が変数の場合は、変数の値を取得 + if(calcOption === "変数" && isNaN(Number(calcValue))){ + calcValue = getContextVarByPath (context.variables,calcValue); + } + + //数値型に変換 + let number = Number(calcValue); + + //有限数かどうか判定 + if(!isFinite(number)){ + throw new Error("計算値が、数値ではありません。「日時を加算/減算する」コンポーネントの処理を中断しました。"); + } + return number; + } + + /** + * 日付・日時を加算・減算する + * @param {any} dateValue + * @param {number} year month day hour minute second + * @returns {string} + */ + calcDate(dateValue:any,year:number,month:number,date:number,hour:number,minute:number,second:number):string{ + + let calcResult; + //フィールドの値(文字列)をdate型に変換する + dateValue = new Date(dateValue); + + // 年を計算 + dateValue.setFullYear(dateValue.getFullYear()+year); + //月を計算 + dateValue.setMonth(dateValue.getMonth()+month); + //日を計算 + dateValue.setDate(dateValue.getDate()+date); + //時間を計算 + dateValue.setHours(dateValue.getHours()+hour); + //分を計算 + dateValue.setMinutes(dateValue.getMinutes()+minute); + //秒を計算 + dateValue.setSeconds(dateValue.getSeconds()+second); + + //UTC形式に変換 + calcResult = dateValue.toISOString(); + return calcResult; + } + + /** + * アクションの実行を呼び出す + * @param actionNode + * @param event + * @returns + */ + async process(actionNode:IActionNode,event:any,context:IContext):Promise { + let result={ + canNext:true, + result:false + }; + try{ + //属性設定を取得する + this.actionProps = actionNode.actionProps; + this.props = actionNode.ActionValue as IDateTimeCalcProps; + + const getContextVarByPath = (obj: any, path: string) => { + return path.split(".").reduce((o, k) => (o || {})[k], obj); + }; + + //基準日となる変数の値取得 + const dateValue = getContextVarByPath (context.variables,this.props.verName.name); + + //基準日となる変数の値が空の場合、処理を終了する + if(!dateValue){ + throw new Error("基準値となる変数の値が空、または存在しません。「日時を加算/減算する」コンポーネントの処理を中断しました。"); + } + + let checkDateValue; + //基準値となる変数の値、日時、日付形式か確認する + checkDateValue = this.isDateValue(dateValue); + + if(checkDateValue){ + //計算値の入力方法を取得する + let calcOptions = this.props.calcOption; + + //計算値を数値型に変換する + let year = this.valueToNumber(context,this.props.year,calcOptions); + let month = this.valueToNumber(context,this.props.month,calcOptions); + let date = this.valueToNumber(context,this.props.date,calcOptions); + let hour = this.valueToNumber(context,this.props.hour,calcOptions); + let minute = this.valueToNumber(context,this.props.minute,calcOptions); + let second = this.valueToNumber(context,this.props.second,calcOptions); + + //計算結果の日付を格納する変数 + let calculatedDate; + + //日付を加算、減算する + calculatedDate = this.calcDate(dateValue,year,month,date,hour,minute,second); + + //計算結果を変数に代入する + context.variables[this.props.resultVerName] = calculatedDate; + } + + result= { + canNext:true, + result:true + } + return result; + }catch(error){ + context.errors.handleError(error,actionNode); + result.canNext=false; + return result; + } + + } + + register(): void { + actionAddins[this.name]=this; + } +} +new DateTimeCalcAction(); diff --git a/plugin/kintone-addins/src/types/action-process.ts b/plugin/kintone-addins/src/types/action-process.ts index 78b6ab4..e0fe403 100644 --- a/plugin/kintone-addins/src/types/action-process.ts +++ b/plugin/kintone-addins/src/types/action-process.ts @@ -23,7 +23,7 @@ import '../actions/login-user-getter'; import '../actions/auto-lookup'; import '../actions/field-disable'; import '../actions/style-field'; - +import '../actions/datetime-calc'; import { ActionFlow,ErrorManager,IActionFlow, IActionResult,IContext } from "./ActionTypes"; const ShowErrorEvents:string[] = [ "app.record.create.submit.success", @@ -64,7 +64,7 @@ export class ActionProcess{ result = await action.process(nextAction,this.event,this.context); } let nextInput = ''; - //outputPoints一つ以上の場合、次のInputPointは戻り値を設定する + //outputPoints一㝤以上㝮場坈〝次㝮InputPoint㝯戻り値を設定㝙る if(nextAction.outputPoints && nextAction.outputPoints.length>1){ nextInput = result.result||''; }