mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 05:29:26 +08:00
Merge branch 'main' into next
This commit is contained in:
commit
ea64d975ed
@ -22,7 +22,7 @@ export default evaluate.bind(function (expression: string, scope = {}) {
|
||||
if (Number.isNaN(result) || !Number.isFinite(result)) {
|
||||
return null;
|
||||
}
|
||||
return round(result, 9);
|
||||
return round(result, 14);
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
|
@ -18,7 +18,7 @@ export default evaluate.bind(
|
||||
if (Number.isNaN(result) || !Number.isFinite(result)) {
|
||||
return null;
|
||||
}
|
||||
return math.round(result, 9);
|
||||
return math.round(result, 14);
|
||||
}
|
||||
if (result instanceof math.Matrix) {
|
||||
return result.toArray();
|
||||
|
@ -11,6 +11,7 @@
|
||||
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/workflow-aggregate",
|
||||
"devDependencies": {
|
||||
"antd": "5.x",
|
||||
"mathjs": "^10.6.0",
|
||||
"react": "18.x",
|
||||
"react-i18next": "^11.15.1"
|
||||
},
|
||||
|
@ -338,9 +338,9 @@ export default class extends Instruction {
|
||||
properties: {
|
||||
distinct: {
|
||||
type: 'boolean',
|
||||
title: `{{t("Distinct", { ns: "${NAMESPACE}" })}}`,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-content': `{{t("Distinct", { ns: "${NAMESPACE}" })}}`,
|
||||
'x-reactions': [
|
||||
{
|
||||
dependencies: ['collection', 'aggregator'],
|
||||
|
@ -7,6 +7,7 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { round } from 'mathjs';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import {
|
||||
AggregateNode,
|
||||
@ -350,7 +351,7 @@ test.describe('filter', () => {
|
||||
aggregateNodeCollectionData.reduce((total, currentValue) => {
|
||||
return currentValue.staffnum > 3 ? total + currentValue.staffnum : total;
|
||||
}, 0) / aggregateNodeCollectionDataCount;
|
||||
expect(aggregateNodeJobResult).toBe(aggregateNodeCollectionDataAvg);
|
||||
expect(aggregateNodeJobResult).toBe(round(aggregateNodeCollectionDataAvg, 14));
|
||||
// 4、后置处理:删除工作流
|
||||
await apiDeleteWorkflow(workflowId);
|
||||
});
|
||||
|
@ -7,6 +7,8 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { round } from 'mathjs';
|
||||
|
||||
import { parseCollectionName } from '@nocobase/data-source-manager';
|
||||
import { DataTypes } from '@nocobase/database';
|
||||
import { Processor, Instruction, JOB_STATUS, FlowNodeModel } from '@nocobase/plugin-workflow';
|
||||
@ -47,7 +49,7 @@ export default class extends Instruction {
|
||||
});
|
||||
|
||||
return {
|
||||
result: options.dataType === DataTypes.DOUBLE ? Number(result) : result,
|
||||
result: round(options.dataType === DataTypes.DOUBLE ? Number(result) : result, 14),
|
||||
status: JOB_STATUS.RESOLVED,
|
||||
};
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ describe('workflow > instructions > aggregate', () => {
|
||||
afterEach(() => app.destroy());
|
||||
|
||||
describe('based on collection', () => {
|
||||
it('count', async () => {
|
||||
it('count with data matched', async () => {
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'aggregate',
|
||||
config: {
|
||||
@ -69,6 +69,30 @@ describe('workflow > instructions > aggregate', () => {
|
||||
expect(job.result).toBe(1);
|
||||
});
|
||||
|
||||
it('count without data matched', async () => {
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'aggregate',
|
||||
config: {
|
||||
aggregator: 'count',
|
||||
collection: 'posts',
|
||||
params: {
|
||||
field: 'id',
|
||||
filter: {
|
||||
id: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const post = await PostRepo.create({ values: { title: 't1' } });
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const [execution] = await workflow.getExecutions();
|
||||
const [job] = await execution.getJobs();
|
||||
expect(job.result).toBe(0);
|
||||
});
|
||||
|
||||
it('sum', async () => {
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'aggregate',
|
||||
@ -98,6 +122,64 @@ describe('workflow > instructions > aggregate', () => {
|
||||
expect(j2.result).toBe(3);
|
||||
});
|
||||
|
||||
it('sum double field', async () => {
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'aggregate',
|
||||
config: {
|
||||
aggregator: 'sum',
|
||||
collection: 'posts',
|
||||
params: {
|
||||
field: 'score',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const p1 = await PostRepo.create({ values: { title: 't1', score: 0.1 } });
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const [e1] = await workflow.getExecutions();
|
||||
const [j1] = await e1.getJobs();
|
||||
expect(j1.result).toBe(0.1);
|
||||
|
||||
const p2 = await PostRepo.create({ values: { title: 't2', score: 0.2 } });
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const [e2] = await workflow.getExecutions({ order: [['id', 'desc']] });
|
||||
const [j2] = await e2.getJobs();
|
||||
expect(j2.result).toBe(0.3);
|
||||
});
|
||||
|
||||
it('sum number will be rounded', async () => {
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'aggregate',
|
||||
config: {
|
||||
aggregator: 'sum',
|
||||
collection: 'posts',
|
||||
params: {
|
||||
field: 'score',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const p1 = await PostRepo.create({ values: { title: 't1', score: 0.100000000000001 } });
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const [e1] = await workflow.getExecutions();
|
||||
const [j1] = await e1.getJobs();
|
||||
expect(j1.result).toBe(0.1);
|
||||
|
||||
const p2 = await PostRepo.create({ values: { title: 't2', score: 0.200000000000001 } });
|
||||
|
||||
await sleep(500);
|
||||
|
||||
const [e2] = await workflow.getExecutions({ order: [['id', 'desc']] });
|
||||
const [j2] = await e2.getJobs();
|
||||
expect(j2.result).toBe(0.3);
|
||||
});
|
||||
|
||||
it('avg', async () => {
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'aggregate',
|
||||
|
@ -571,7 +571,7 @@ export class AggregateNode {
|
||||
.getByLabel('block-item-FieldsSelect-workflows-Field to aggregate')
|
||||
.locator('.ant-select-selection-search-input');
|
||||
this.distinctCheckBox = page
|
||||
.getByLabel('block-item-Checkbox-workflows-Distinct')
|
||||
.getByLabel('block-item-Checkbox-workflows')
|
||||
.locator('input.ant-checkbox-input[type="checkbox"]');
|
||||
this.submitButton = page.getByLabel('action-Action-Submit-workflows');
|
||||
this.cancelButton = page.getByLabel('action-Action-Cancel-workflows');
|
||||
|
@ -45,6 +45,11 @@ export default {
|
||||
name: 'read',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
type: 'double',
|
||||
name: 'score',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'createdAt',
|
||||
|
Loading…
x
Reference in New Issue
Block a user