375 lines
8.0 KiB
TypeScript
375 lines
8.0 KiB
TypeScript
import {
|
|
IAction,
|
|
IActionResult,
|
|
IActionNode,
|
|
IActionProperty,
|
|
IContext,
|
|
} from "../types/ActionTypes";
|
|
import { actionAddins } from ".";
|
|
|
|
interface Props {
|
|
displayName: string;
|
|
sources: Sources;
|
|
condition: string;
|
|
conditionO: Condition;
|
|
verName: VerName;
|
|
}
|
|
|
|
interface Condition {
|
|
queryString: string;
|
|
index: number;
|
|
type: string;
|
|
children: Child[];
|
|
parent: null;
|
|
logicalOperator: string;
|
|
}
|
|
|
|
interface Child {
|
|
index: number;
|
|
type: string;
|
|
parent: string;
|
|
object: Object;
|
|
operator: ChildOperator;
|
|
value: Value;
|
|
}
|
|
|
|
interface Value {
|
|
sharedText: string;
|
|
_t: string;
|
|
objectType: string;
|
|
actionName: string;
|
|
displayName: string;
|
|
name: Name;
|
|
}
|
|
|
|
interface Name {
|
|
name: string;
|
|
}
|
|
|
|
interface ChildOperator {
|
|
label: string;
|
|
value: string;
|
|
}
|
|
|
|
interface Object {
|
|
sharedText: string;
|
|
_t: string;
|
|
name: string;
|
|
objectType: string;
|
|
type: string;
|
|
code: string;
|
|
label: string;
|
|
noLabel: boolean;
|
|
required: boolean;
|
|
minLength: string;
|
|
maxLength: string;
|
|
expression: string;
|
|
hideExpression: boolean;
|
|
unique: boolean;
|
|
defaultValue: string;
|
|
}
|
|
|
|
interface VerName {
|
|
name: string;
|
|
actionName: string;
|
|
displayName: string;
|
|
vars: Var[];
|
|
}
|
|
|
|
interface Var {
|
|
id: string;
|
|
field: Field2;
|
|
logicalOperator: LogicalOperator;
|
|
vName: string;
|
|
}
|
|
|
|
interface LogicalOperator {
|
|
operator: string;
|
|
label: string;
|
|
}
|
|
|
|
interface Field2 {
|
|
sharedText: string;
|
|
_t: string;
|
|
name: string;
|
|
objectType: string;
|
|
type: string;
|
|
code: string;
|
|
label: string;
|
|
noLabel: boolean;
|
|
required: boolean;
|
|
minLength: string;
|
|
maxLength: string;
|
|
expression: string;
|
|
hideExpression: boolean;
|
|
unique: boolean;
|
|
defaultValue: string;
|
|
}
|
|
|
|
interface Sources {
|
|
app: App;
|
|
fields: Field[];
|
|
}
|
|
|
|
interface Field {
|
|
name: string;
|
|
type: string;
|
|
code: string;
|
|
label: string;
|
|
noLabel: boolean;
|
|
required: boolean;
|
|
minLength: string;
|
|
maxLength: string;
|
|
expression: string;
|
|
hideExpression: boolean;
|
|
unique: boolean;
|
|
defaultValue: string;
|
|
}
|
|
|
|
interface App {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
createdate: string;
|
|
}
|
|
|
|
export class DataProcessingAction implements IAction {
|
|
name: string;
|
|
actionProps: IActionProperty[];
|
|
dataProcessingProps: Props | null;
|
|
constructor() {
|
|
this.name = "データ処理";
|
|
this.actionProps = [];
|
|
this.dataProcessingProps = null;
|
|
this.register();
|
|
}
|
|
|
|
async process(
|
|
nodes: IActionNode,
|
|
event: any,
|
|
context: IContext
|
|
): Promise<IActionResult> {
|
|
this.actionProps = nodes.actionProps;
|
|
this.dataProcessingProps = nodes.ActionValue as Props;
|
|
this.dataProcessingProps.conditionO = JSON.parse(
|
|
this.dataProcessingProps.condition
|
|
);
|
|
let result = {
|
|
canNext: true,
|
|
result: "",
|
|
} as IActionResult;
|
|
try {
|
|
if (!this.dataProcessingProps) {
|
|
return result;
|
|
}
|
|
|
|
const data = await selectData(
|
|
varGet(
|
|
this.dataProcessingProps.conditionO.queryString,
|
|
context.variables
|
|
)
|
|
);
|
|
console.log("data ", data);
|
|
|
|
context.variables[this.dataProcessingProps.verName.name] =
|
|
this.dataProcessingProps.verName.vars.reduce((acc, f) => {
|
|
const v = calc(f, data);
|
|
if (v) {
|
|
acc[f.vName] = calc(f, data);
|
|
}
|
|
return acc;
|
|
}, {} as AnyObject);
|
|
|
|
console.log("context ", context);
|
|
return result;
|
|
} catch (error) {
|
|
console.error(error);
|
|
event.error = error;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
register(): void {
|
|
actionAddins[this.name] = this;
|
|
}
|
|
}
|
|
|
|
new DataProcessingAction();
|
|
|
|
const varGet = (str: string, vars: any) => {
|
|
console.log(str);
|
|
|
|
const regex = /var\((.*?)\)/g;
|
|
let match;
|
|
while ((match = regex.exec(str)) !== null) {
|
|
const varName = match[1];
|
|
if (varName in vars) {
|
|
str = str.replace(match[0], vars[varName]);
|
|
} else {
|
|
throw new Error(`変数${varName}が見つかりません`);
|
|
}
|
|
}
|
|
console.log(str);
|
|
return str;
|
|
};
|
|
|
|
const selectData = async (query?: string) => {
|
|
return kintone
|
|
.api(kintone.api.url("/k/v1/records", true), "GET", {
|
|
app: kintone.app.getId(),
|
|
query: query,
|
|
})
|
|
.then((resp: Resp) => {
|
|
const result: Result = {};
|
|
resp.records.forEach((element) => {
|
|
for (const [key, value] of Object.entries(element)) {
|
|
if (!result[key]) {
|
|
result[key] = { type: value.type, value: [] };
|
|
}
|
|
result[key].value.push(value.value);
|
|
}
|
|
});
|
|
return result;
|
|
});
|
|
};
|
|
|
|
type Resp = { records: RespRecordType[] };
|
|
|
|
type RespRecordType = {
|
|
[key: string]: {
|
|
type: string;
|
|
value: any;
|
|
};
|
|
};
|
|
|
|
type Result = {
|
|
[key: string]: {
|
|
type: string;
|
|
value: any[];
|
|
};
|
|
};
|
|
|
|
type AnyObject = {
|
|
[key: string]: any;
|
|
};
|
|
|
|
const ERROR_TYPE = "ERROR_TYPE";
|
|
|
|
const calc = (f: Var, result: Result) => {
|
|
const type = typeCheck(f.field.type);
|
|
if (!type) {
|
|
return ERROR_TYPE;
|
|
}
|
|
|
|
const fun =
|
|
calcFunc[
|
|
`${type}_${Operator[f.logicalOperator.operator as keyof typeof Operator]}`
|
|
];
|
|
if (!fun) {
|
|
return ERROR_TYPE;
|
|
}
|
|
const values = result[f.field.code].value;
|
|
if (!values) {
|
|
return null;
|
|
}
|
|
return fun(values);
|
|
};
|
|
|
|
const typeCheck = (type: string) => {
|
|
switch (type) {
|
|
case "RECORD_NUMBER":
|
|
case "NUMBER":
|
|
return CalcType.NUMBER;
|
|
case "SINGLE_LINE_TEXT":
|
|
case "MULTI_LINE_TEXT":
|
|
case "RICH_TEXT":
|
|
return CalcType.STRING;
|
|
case "DATE":
|
|
return CalcType.DATE;
|
|
case "TIME":
|
|
return CalcType.TIME;
|
|
case "DATETIME":
|
|
case "UPDATED_TIME":
|
|
return CalcType.DATETIME;
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
enum Operator {
|
|
SUM = "SUM",
|
|
AVG = "AVG",
|
|
MAX = "MAX",
|
|
MIN = "MIN",
|
|
COUNT = "COUNT",
|
|
FIRST = "FIRST",
|
|
}
|
|
|
|
enum CalcType {
|
|
NUMBER = "number",
|
|
STRING = "string",
|
|
DATE = "date",
|
|
TIME = "time",
|
|
DATETIME = "datetime",
|
|
}
|
|
|
|
const calcFunc: Record<string, (value: string[]) => string | null> = {
|
|
[`${CalcType.NUMBER}_${Operator.COUNT}`]: (value: string[]) =>
|
|
value.length.toString(),
|
|
[`${CalcType.STRING}_${Operator.COUNT}`]: (value: string[]) =>
|
|
value.length.toString(),
|
|
[`${CalcType.DATE}_${Operator.COUNT}`]: (value: string[]) =>
|
|
value.length.toString(),
|
|
[`${CalcType.TIME}_${Operator.COUNT}`]: (value: string[]) =>
|
|
value.length.toString(),
|
|
[`${CalcType.DATETIME}_${Operator.COUNT}`]: (value: string[]) =>
|
|
value.length.toString(),
|
|
|
|
[`${CalcType.NUMBER}_${Operator.SUM}`]: (value: string[]) =>
|
|
value.reduce((acc, v) => acc + Number(v), 0).toString(),
|
|
[`${CalcType.NUMBER}_${Operator.AVG}`]: (value: string[]) =>
|
|
(value.reduce((acc, v) => acc + Number(v), 0) / value.length).toString(),
|
|
[`${CalcType.NUMBER}_${Operator.MAX}`]: (value: string[]) =>
|
|
Math.max(...value.map(Number)).toString(),
|
|
[`${CalcType.NUMBER}_${Operator.MIN}`]: (value: string[]) =>
|
|
Math.min(...value.map(Number)).toString(),
|
|
|
|
[`${CalcType.STRING}_${Operator.SUM}`]: (value: string[]) => value.join(" "),
|
|
|
|
[`${CalcType.DATE}_${Operator.MAX}`]: (value: string[]) =>
|
|
value.reduce((maxDate, currentDate) =>
|
|
maxDate > currentDate ? maxDate : currentDate
|
|
),
|
|
|
|
[`${CalcType.DATE}_${Operator.MIN}`]: (value: string[]) =>
|
|
value.reduce((minDate, currentDate) =>
|
|
minDate < currentDate ? minDate : currentDate
|
|
),
|
|
|
|
[`${CalcType.TIME}_${Operator.MAX}`]: (value: string[]) =>
|
|
value.reduce((maxTime, currentTime) =>
|
|
maxTime > currentTime ? maxTime : currentTime
|
|
),
|
|
[`${CalcType.TIME}_${Operator.MIN}`]: (value: string[]) =>
|
|
value.reduce((minTime, currentTime) =>
|
|
minTime < currentTime ? minTime : currentTime
|
|
),
|
|
|
|
[`${CalcType.DATETIME}_${Operator.MAX}`]: (value: string[]) =>
|
|
value.reduce((maxDateTime, currentDateTime) =>
|
|
new Date(maxDateTime) > new Date(currentDateTime)
|
|
? maxDateTime
|
|
: currentDateTime
|
|
),
|
|
|
|
[`${CalcType.DATETIME}_${Operator.MIN}`]: (value: string[]) =>
|
|
value.reduce((minDateTime, currentDateTime) =>
|
|
new Date(minDateTime) < new Date(currentDateTime)
|
|
? minDateTime
|
|
: currentDateTime
|
|
),
|
|
[`${CalcType.STRING}_${Operator.FIRST}`]: (value: string[]) => {
|
|
return value[0];
|
|
},
|
|
};
|