@bgroup/wise-form 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/components/ui/Checkbox.d.ts +14 -0
- package/dist/components/ui/Checkbox.d.ts.map +1 -0
- package/dist/components/ui/Checkbox.js +43 -0
- package/dist/components/ui/Checkbox.js.map +1 -0
- package/dist/components/ui/CheckboxGroup.d.ts +15 -0
- package/dist/components/ui/CheckboxGroup.d.ts.map +1 -0
- package/dist/components/ui/CheckboxGroup.js +33 -0
- package/dist/components/ui/CheckboxGroup.js.map +1 -0
- package/dist/components/ui/Input.d.ts +14 -0
- package/dist/components/ui/Input.d.ts.map +1 -0
- package/dist/components/ui/Input.js +49 -0
- package/dist/components/ui/Input.js.map +1 -0
- package/dist/components/ui/Radio.d.ts +14 -0
- package/dist/components/ui/Radio.d.ts.map +1 -0
- package/dist/components/ui/Radio.js +43 -0
- package/dist/components/ui/Radio.js.map +1 -0
- package/dist/components/ui/Select.d.ts +18 -0
- package/dist/components/ui/Select.d.ts.map +1 -0
- package/dist/components/ui/Select.js +44 -0
- package/dist/components/ui/Select.js.map +1 -0
- package/dist/components/ui/Textarea.d.ts +13 -0
- package/dist/components/ui/Textarea.d.ts.map +1 -0
- package/dist/components/ui/Textarea.js +42 -0
- package/dist/components/ui/Textarea.js.map +1 -0
- package/dist/components/ui/index.d.ts +13 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/index.js +7 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/form/index.d.ts +10 -0
- package/dist/form/index.d.ts.map +1 -0
- package/dist/form/index.js +5 -0
- package/dist/form/index.js.map +1 -0
- package/dist/form/interfaces/field-container.d.ts +8 -0
- package/dist/form/interfaces/field-container.d.ts.map +1 -0
- package/dist/form/interfaces/field-container.js +2 -0
- package/dist/form/interfaces/field-container.js.map +1 -0
- package/dist/form/interfaces/interfaces.d.ts +8 -0
- package/dist/form/interfaces/interfaces.d.ts.map +1 -0
- package/dist/form/interfaces/interfaces.js +2 -0
- package/dist/form/interfaces/interfaces.js.map +1 -0
- package/dist/form/interfaces/settings.d.ts +10 -0
- package/dist/form/interfaces/settings.d.ts.map +1 -0
- package/dist/form/interfaces/settings.js +2 -0
- package/dist/form/interfaces/settings.js.map +1 -0
- package/dist/form/interfaces/template.d.ts +6 -0
- package/dist/form/interfaces/template.d.ts.map +1 -0
- package/dist/form/interfaces/template.js +2 -0
- package/dist/form/interfaces/template.js.map +1 -0
- package/dist/form/interfaces/wise-form-specs.d.ts +9 -0
- package/dist/form/interfaces/wise-form-specs.d.ts.map +1 -0
- package/dist/form/interfaces/wise-form-specs.js +2 -0
- package/dist/form/interfaces/wise-form-specs.js.map +1 -0
- package/dist/form/view/components/containers/index.d.ts +3 -0
- package/dist/form/view/components/containers/index.d.ts.map +1 -0
- package/dist/form/view/components/containers/index.js +12 -0
- package/dist/form/view/components/containers/index.js.map +1 -0
- package/dist/form/view/components/error.d.ts +5 -0
- package/dist/form/view/components/error.d.ts.map +1 -0
- package/dist/form/view/components/error.js +8 -0
- package/dist/form/view/components/error.js.map +1 -0
- package/dist/form/view/components/field/container.d.ts +5 -0
- package/dist/form/view/components/field/container.d.ts.map +1 -0
- package/dist/form/view/components/field/container.js +5 -0
- package/dist/form/view/components/field/container.js.map +1 -0
- package/dist/form/view/components/field/index.d.ts +18 -0
- package/dist/form/view/components/field/index.d.ts.map +1 -0
- package/dist/form/view/components/field/index.js +89 -0
- package/dist/form/view/components/field/index.js.map +1 -0
- package/dist/form/view/components/field/selection.d.ts +2 -0
- package/dist/form/view/components/field/selection.d.ts.map +1 -0
- package/dist/form/view/components/field/selection.js +35 -0
- package/dist/form/view/components/field/selection.js.map +1 -0
- package/dist/form/view/components/field/use-field.d.ts +4 -0
- package/dist/form/view/components/field/use-field.d.ts.map +1 -0
- package/dist/form/view/components/field/use-field.js +41 -0
- package/dist/form/view/components/field/use-field.js.map +1 -0
- package/dist/form/view/components/rows/row-container.d.ts +18 -0
- package/dist/form/view/components/rows/row-container.d.ts.map +1 -0
- package/dist/form/view/components/rows/row-container.js +89 -0
- package/dist/form/view/components/rows/row-container.js.map +1 -0
- package/dist/form/view/components/rows/wrapper.d.ts +12 -0
- package/dist/form/view/components/rows/wrapper.d.ts.map +1 -0
- package/dist/form/view/components/rows/wrapper.js +27 -0
- package/dist/form/view/components/rows/wrapper.js.map +1 -0
- package/dist/form/view/components/wrapped-form.d.ts +6 -0
- package/dist/form/view/components/wrapped-form.d.ts.map +1 -0
- package/dist/form/view/components/wrapped-form.js +26 -0
- package/dist/form/view/components/wrapped-form.js.map +1 -0
- package/dist/form/view/context.d.ts +23 -0
- package/dist/form/view/context.d.ts.map +1 -0
- package/dist/form/view/context.js +7 -0
- package/dist/form/view/context.js.map +1 -0
- package/dist/form/view/hooks/use-model.d.ts +10 -0
- package/dist/form/view/hooks/use-model.d.ts.map +1 -0
- package/dist/form/view/hooks/use-model.js +31 -0
- package/dist/form/view/hooks/use-model.js.map +1 -0
- package/dist/form/view/hooks/use-template.d.ts +14 -0
- package/dist/form/view/hooks/use-template.d.ts.map +1 -0
- package/dist/form/view/hooks/use-template.js +57 -0
- package/dist/form/view/hooks/use-template.js.map +1 -0
- package/dist/form/view/hooks/use-types.d.ts +2 -0
- package/dist/form/view/hooks/use-types.d.ts.map +1 -0
- package/dist/form/view/hooks/use-types.js +19 -0
- package/dist/form/view/hooks/use-types.js.map +1 -0
- package/dist/form/view/index.d.ts +3 -0
- package/dist/form/view/index.d.ts.map +1 -0
- package/dist/form/view/index.js +38 -0
- package/dist/form/view/index.js.map +1 -0
- package/dist/formulas/helpers/condition-types.d.ts +5 -0
- package/dist/formulas/helpers/condition-types.d.ts.map +1 -0
- package/dist/formulas/helpers/condition-types.js +5 -0
- package/dist/formulas/helpers/condition-types.js.map +1 -0
- package/dist/formulas/helpers/evaluations.d.ts +15 -0
- package/dist/formulas/helpers/evaluations.d.ts.map +1 -0
- package/dist/formulas/helpers/evaluations.js +44 -0
- package/dist/formulas/helpers/evaluations.js.map +1 -0
- package/dist/formulas/helpers/formula.d.ts +6 -0
- package/dist/formulas/helpers/formula.d.ts.map +1 -0
- package/dist/formulas/helpers/formula.js +26 -0
- package/dist/formulas/helpers/formula.js.map +1 -0
- package/dist/formulas/helpers/lexer.d.ts +10 -0
- package/dist/formulas/helpers/lexer.d.ts.map +1 -0
- package/dist/formulas/helpers/lexer.js +73 -0
- package/dist/formulas/helpers/lexer.js.map +1 -0
- package/dist/formulas/helpers/parser.d.ts +24 -0
- package/dist/formulas/helpers/parser.d.ts.map +1 -0
- package/dist/formulas/helpers/parser.js +48 -0
- package/dist/formulas/helpers/parser.js.map +1 -0
- package/dist/formulas/helpers/token.d.ts +14 -0
- package/dist/formulas/helpers/token.d.ts.map +1 -0
- package/dist/formulas/helpers/token.js +14 -0
- package/dist/formulas/helpers/token.js.map +1 -0
- package/dist/formulas/index.d.ts +59 -0
- package/dist/formulas/index.d.ts.map +1 -0
- package/dist/formulas/index.js +186 -0
- package/dist/formulas/index.js.map +1 -0
- package/dist/formulas/types/formulas.d.ts +68 -0
- package/dist/formulas/types/formulas.d.ts.map +1 -0
- package/dist/formulas/types/formulas.js +2 -0
- package/dist/formulas/types/formulas.js.map +1 -0
- package/dist/formulas/types/index.d.ts +5 -0
- package/dist/formulas/types/index.d.ts.map +1 -0
- package/dist/formulas/types/index.js +2 -0
- package/dist/formulas/types/index.js.map +1 -0
- package/dist/formulas/variants/array-formula.d.ts +24 -0
- package/dist/formulas/variants/array-formula.d.ts.map +1 -0
- package/dist/formulas/variants/array-formula.js +142 -0
- package/dist/formulas/variants/array-formula.js.map +1 -0
- package/dist/formulas/variants/base.d.ts +6 -0
- package/dist/formulas/variants/base.d.ts.map +1 -0
- package/dist/formulas/variants/base.js +3 -0
- package/dist/formulas/variants/base.js.map +1 -0
- package/dist/formulas/variants/basic.d.ts +18 -0
- package/dist/formulas/variants/basic.d.ts.map +1 -0
- package/dist/formulas/variants/basic.js +128 -0
- package/dist/formulas/variants/basic.js.map +1 -0
- package/dist/formulas/variants/comparison.d.ts +25 -0
- package/dist/formulas/variants/comparison.d.ts.map +1 -0
- package/dist/formulas/variants/comparison.js +153 -0
- package/dist/formulas/variants/comparison.js.map +1 -0
- package/dist/formulas/variants/conditional.d.ts +18 -0
- package/dist/formulas/variants/conditional.d.ts.map +1 -0
- package/dist/formulas/variants/conditional.js +183 -0
- package/dist/formulas/variants/conditional.js.map +1 -0
- package/dist/formulas/variants/iterative-array.d.ts +20 -0
- package/dist/formulas/variants/iterative-array.d.ts.map +1 -0
- package/dist/formulas/variants/iterative-array.js +155 -0
- package/dist/formulas/variants/iterative-array.js.map +1 -0
- package/dist/formulas/variants/per-value.d.ts +20 -0
- package/dist/formulas/variants/per-value.d.ts.map +1 -0
- package/dist/formulas/variants/per-value.js +154 -0
- package/dist/formulas/variants/per-value.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/models/base.d.ts +55 -0
- package/dist/models/base.d.ts.map +1 -0
- package/dist/models/base.js +146 -0
- package/dist/models/base.js.map +1 -0
- package/dist/models/callback-manager.d.ts +7 -0
- package/dist/models/callback-manager.d.ts.map +1 -0
- package/dist/models/callback-manager.js +89 -0
- package/dist/models/callback-manager.js.map +1 -0
- package/dist/models/field.d.ts +121 -0
- package/dist/models/field.d.ts.map +1 -0
- package/dist/models/field.js +374 -0
- package/dist/models/field.js.map +1 -0
- package/dist/models/index.d.ts +13 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +7 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/model.d.ts +37 -0
- package/dist/models/model.d.ts.map +1 -0
- package/dist/models/model.js +245 -0
- package/dist/models/model.js.map +1 -0
- package/dist/models/plugins/base.d.ts +9 -0
- package/dist/models/plugins/base.d.ts.map +1 -0
- package/dist/models/plugins/base.js +3 -0
- package/dist/models/plugins/base.js.map +1 -0
- package/dist/models/plugins/formula.d.ts +18 -0
- package/dist/models/plugins/formula.d.ts.map +1 -0
- package/dist/models/plugins/formula.js +82 -0
- package/dist/models/plugins/formula.js.map +1 -0
- package/dist/models/plugins/index.d.ts +11 -0
- package/dist/models/plugins/index.d.ts.map +1 -0
- package/dist/models/plugins/index.js +52 -0
- package/dist/models/plugins/index.js.map +1 -0
- package/dist/models/plugins/plugins.d.ts +7 -0
- package/dist/models/plugins/plugins.d.ts.map +1 -0
- package/dist/models/plugins/plugins.js +7 -0
- package/dist/models/plugins/plugins.js.map +1 -0
- package/dist/models/types/base-wise-model.d.ts +7 -0
- package/dist/models/types/base-wise-model.d.ts.map +1 -0
- package/dist/models/types/base-wise-model.js +2 -0
- package/dist/models/types/base-wise-model.js.map +1 -0
- package/dist/models/types/callbacks.d.ts +19 -0
- package/dist/models/types/callbacks.d.ts.map +1 -0
- package/dist/models/types/callbacks.js +2 -0
- package/dist/models/types/callbacks.js.map +1 -0
- package/dist/models/types/disabled.d.ts +8 -0
- package/dist/models/types/disabled.d.ts.map +1 -0
- package/dist/models/types/disabled.js +2 -0
- package/dist/models/types/disabled.js.map +1 -0
- package/dist/models/types/form-field.d.ts +25 -0
- package/dist/models/types/form-field.d.ts.map +1 -0
- package/dist/models/types/form-field.js +2 -0
- package/dist/models/types/form-field.js.map +1 -0
- package/dist/models/types/model.d.ts +13 -0
- package/dist/models/types/model.d.ts.map +1 -0
- package/dist/models/types/model.js +2 -0
- package/dist/models/types/model.js.map +1 -0
- package/dist/models/types/plugins.d.ts +13 -0
- package/dist/models/types/plugins.d.ts.map +1 -0
- package/dist/models/types/plugins.js +2 -0
- package/dist/models/types/plugins.js.map +1 -0
- package/dist/models/types/wrapped-form-model-props.d.ts +11 -0
- package/dist/models/types/wrapped-form-model-props.d.ts.map +1 -0
- package/dist/models/types/wrapped-form-model-props.js +2 -0
- package/dist/models/types/wrapped-form-model-props.js.map +1 -0
- package/dist/models/wrapper.d.ts +30 -0
- package/dist/models/wrapper.d.ts.map +1 -0
- package/dist/models/wrapper.js +213 -0
- package/dist/models/wrapper.js.map +1 -0
- package/dist/settings/index.d.ts +7 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +26 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/utils/pending-promise.d.ts +6 -0
- package/dist/utils/pending-promise.d.ts.map +1 -0
- package/dist/utils/pending-promise.js +24 -0
- package/dist/utils/pending-promise.js.map +1 -0
- package/package.json +38 -0
- package/src/components/ui/Checkbox.tsx +68 -0
- package/src/components/ui/CheckboxGroup.tsx +60 -0
- package/src/components/ui/Input.tsx +72 -0
- package/src/components/ui/Radio.tsx +68 -0
- package/src/components/ui/Select.tsx +73 -0
- package/src/components/ui/Textarea.tsx +63 -0
- package/src/components/ui/index.ts +14 -0
- package/src/form/index.ts +11 -0
- package/src/form/interfaces/field-container.ts +9 -0
- package/src/form/interfaces/interfaces.ts +12 -0
- package/src/form/interfaces/settings.ts +11 -0
- package/src/form/interfaces/template.ts +7 -0
- package/src/form/interfaces/wise-form-specs.ts +10 -0
- package/src/form/styles.css +40 -0
- package/src/form/view/components/containers/index.tsx +18 -0
- package/src/form/view/components/error.tsx +9 -0
- package/src/form/view/components/field/container.tsx +6 -0
- package/src/form/view/components/field/index.tsx +107 -0
- package/src/form/view/components/field/selection.tsx +39 -0
- package/src/form/view/components/field/use-field.tsx +49 -0
- package/src/form/view/components/rows/row-container.tsx +96 -0
- package/src/form/view/components/rows/wrapper.tsx +28 -0
- package/src/form/view/components/wrapped-form.tsx +32 -0
- package/src/form/view/context.tsx +26 -0
- package/src/form/view/hooks/use-model.ts +37 -0
- package/src/form/view/hooks/use-template.tsx +64 -0
- package/src/form/view/hooks/use-types.ts +21 -0
- package/src/form/view/index.tsx +48 -0
- package/src/formulas/helpers/condition-types.ts +5 -0
- package/src/formulas/helpers/evaluations.ts +48 -0
- package/src/formulas/helpers/formula.ts +27 -0
- package/src/formulas/helpers/lexer.ts +82 -0
- package/src/formulas/helpers/parser.ts +55 -0
- package/src/formulas/helpers/token.ts +22 -0
- package/src/formulas/index.ts +198 -0
- package/src/formulas/types/formulas.ts +72 -0
- package/src/formulas/types/index.ts +5 -0
- package/src/formulas/variants/array-formula.ts +138 -0
- package/src/formulas/variants/base.ts +6 -0
- package/src/formulas/variants/basic.ts +141 -0
- package/src/formulas/variants/comparison.ts +156 -0
- package/src/formulas/variants/conditional.ts +208 -0
- package/src/formulas/variants/iterative-array.ts +152 -0
- package/src/formulas/variants/per-value.ts +152 -0
- package/src/index.ts +6 -0
- package/src/models/base.ts +164 -0
- package/src/models/callback-manager.ts +102 -0
- package/src/models/field.ts +426 -0
- package/src/models/index.ts +14 -0
- package/src/models/model.ts +260 -0
- package/src/models/plugins/base.ts +11 -0
- package/src/models/plugins/formula.ts +80 -0
- package/src/models/plugins/index.ts +48 -0
- package/src/models/plugins/plugins.ts +8 -0
- package/src/models/types/base-wise-model.ts +7 -0
- package/src/models/types/callbacks.ts +23 -0
- package/src/models/types/disabled.ts +8 -0
- package/src/models/types/form-field.ts +22 -0
- package/src/models/types/model.ts +14 -0
- package/src/models/types/plugins.ts +15 -0
- package/src/models/types/wrapped-form-model-props.ts +9 -0
- package/src/models/wrapper.ts +242 -0
- package/src/settings/index.ts +11 -0
- package/src/utils/pending-promise.ts +29 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { FormulaManager } from "..";
|
|
2
|
+
import { EvaluationsManager } from "../helpers/evaluations";
|
|
3
|
+
|
|
4
|
+
import { Token } from "../helpers/token";
|
|
5
|
+
import { FormulaObserver, IComplexCondition, IConditionalField } from "../types/formulas";
|
|
6
|
+
import { number, parse } from "mathjs";
|
|
7
|
+
|
|
8
|
+
export class FormulaComparison {
|
|
9
|
+
#plugin: any;
|
|
10
|
+
#specs: FormulaObserver;
|
|
11
|
+
#emptyValue: undefined;
|
|
12
|
+
#tokens: Token[];
|
|
13
|
+
get formula() {
|
|
14
|
+
return this.#specs.formula;
|
|
15
|
+
}
|
|
16
|
+
get base() {
|
|
17
|
+
const formula = <IComplexCondition>this.#specs.formula;
|
|
18
|
+
return formula.base;
|
|
19
|
+
}
|
|
20
|
+
#value: string | number | undefined | 0;
|
|
21
|
+
get value() {
|
|
22
|
+
return this.#value;
|
|
23
|
+
}
|
|
24
|
+
get name() {
|
|
25
|
+
return this.#specs.name;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Represents the fields defined in the plugin settings
|
|
29
|
+
*/
|
|
30
|
+
get fields() {
|
|
31
|
+
const formula = <IComplexCondition>this.formula;
|
|
32
|
+
return typeof formula?.fields === "string" ? [formula?.fields] : formula?.fields;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get conditions() {
|
|
36
|
+
if (typeof this.#specs.formula === "string") return;
|
|
37
|
+
const formula = this.#specs.formula as IComplexCondition;
|
|
38
|
+
return formula.conditions;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#variables: string[] = [];
|
|
42
|
+
get variables() {
|
|
43
|
+
return this.#variables;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
#observers: string[];
|
|
47
|
+
get observers() {
|
|
48
|
+
return this.#observers;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#isNotListenToChanges = false
|
|
52
|
+
|
|
53
|
+
#parent: FormulaManager;
|
|
54
|
+
constructor(parent, plugin, specs) {
|
|
55
|
+
this.#parent = parent;
|
|
56
|
+
this.#plugin = plugin;
|
|
57
|
+
this.#specs = specs;
|
|
58
|
+
this.#isNotListenToChanges = specs.isNotListenToChanges;
|
|
59
|
+
this.#observers = specs.formula.observers;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
initialize() {
|
|
63
|
+
if (!Array.isArray(this.#specs.fields)) {
|
|
64
|
+
throw new Error("The fields property must be an array");
|
|
65
|
+
}
|
|
66
|
+
if (!this.#isNotListenToChanges && this.#observers && Array.isArray(this.#observers) && !!this.#observers.length) {
|
|
67
|
+
const fields = this.#parent.getModels(this.#observers);
|
|
68
|
+
fields.forEach(field => {
|
|
69
|
+
if (!field) return;
|
|
70
|
+
field.on('change', this.calculate.bind(this));
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const models = this.#parent.getModels(this.#specs.fields);
|
|
74
|
+
if (!this.#isNotListenToChanges) models.forEach(model => model.on("change", this.calculate.bind(this)));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
start() { }
|
|
79
|
+
|
|
80
|
+
evaluate() {
|
|
81
|
+
const formula = <IComplexCondition>this.#specs.formula;
|
|
82
|
+
|
|
83
|
+
if (typeof formula === "string" || !formula.conditions) {
|
|
84
|
+
console.error("Invalid formula configuration");
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const models = this.#parent.getModels(this.#specs.fields);
|
|
88
|
+
let fieldValues = models.map(fieldModel => {
|
|
89
|
+
if (!fieldModel) return;
|
|
90
|
+
return { name: fieldModel.name, value: fieldModel ? fieldModel.value : null };
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Utilizar reduce para comparar cada par de valores consecutivos y determinar cuál cumple la condición
|
|
94
|
+
const resultField = fieldValues.reduce((prevField, currentField) => {
|
|
95
|
+
if (!prevField) return currentField;
|
|
96
|
+
|
|
97
|
+
// Si el campo previo cumple la condición con respecto al actual, se mantiene como el campo elegido
|
|
98
|
+
if (EvaluationsManager.validate(formula.condition, prevField.value, currentField.value)) {
|
|
99
|
+
return prevField;
|
|
100
|
+
}
|
|
101
|
+
// De lo contrario, el campo actual se convierte en el nuevo campo elegido
|
|
102
|
+
return currentField;
|
|
103
|
+
}, null);
|
|
104
|
+
|
|
105
|
+
if (resultField) {
|
|
106
|
+
// Ajustar según la lógica específica deseada, como devolver una fórmula particular basada en el resultado
|
|
107
|
+
return resultField;
|
|
108
|
+
} else {
|
|
109
|
+
// Manejar el caso de que ninguno cumpla la condición
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async calculate() {
|
|
115
|
+
let applied = this.evaluate();
|
|
116
|
+
|
|
117
|
+
if (!applied || !applied?.value) {
|
|
118
|
+
// any formula apply, so we need to reset the value
|
|
119
|
+
this.#value = 0;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the formula analyzer
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
const specsFormula = this.#specs.formula as IComplexCondition;
|
|
127
|
+
const formulaString = specsFormula.conditions[applied.name];
|
|
128
|
+
const formula = this.#parent.getParser({ formula: formulaString });
|
|
129
|
+
const variables = formula.tokens.filter(token => token.type === "variable").map(item => item.value);
|
|
130
|
+
const params = await this.#parent.getParams(variables);
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const keys = Object.keys(params);
|
|
134
|
+
const result = keys.length === 1 ? params[keys[0]] : parse(this.formula as string).evaluate(params);
|
|
135
|
+
|
|
136
|
+
this.#value = [-Infinity, Infinity, undefined, null, NaN].includes(result)
|
|
137
|
+
? this.#emptyValue
|
|
138
|
+
: Number(result.toFixed(2));
|
|
139
|
+
this.#parent.trigger("change");
|
|
140
|
+
return this.#value;
|
|
141
|
+
} catch (e) {
|
|
142
|
+
console.log("formula", this.name, this.formula, params);
|
|
143
|
+
throw new Error("Error calculating the formula");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
calculateUpper(models) {
|
|
148
|
+
let glue;
|
|
149
|
+
models.forEach(item => {
|
|
150
|
+
if (Number(item.value) > Number(glue?.value ?? 0)) glue = item;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return glue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import type { FormulaManager } from '..';
|
|
2
|
+
import { conditionsTypes } from '../helpers/condition-types';
|
|
3
|
+
import { EvaluationsManager } from '../helpers/evaluations';
|
|
4
|
+
import {
|
|
5
|
+
EvaluatedFormula,
|
|
6
|
+
FormulaObserver,
|
|
7
|
+
IComplexCondition,
|
|
8
|
+
IConditionalField,
|
|
9
|
+
} from '../types/formulas';
|
|
10
|
+
import { parse } from 'mathjs';
|
|
11
|
+
|
|
12
|
+
export class FormulaConditional {
|
|
13
|
+
#plugin: any;
|
|
14
|
+
#specs: FormulaObserver;
|
|
15
|
+
#emptyValue: undefined;
|
|
16
|
+
get formula() {
|
|
17
|
+
return this.#specs.formula;
|
|
18
|
+
}
|
|
19
|
+
get base() {
|
|
20
|
+
const formula = <IComplexCondition>this.#specs.formula;
|
|
21
|
+
return formula.base;
|
|
22
|
+
}
|
|
23
|
+
#value: string | number | undefined | 0;
|
|
24
|
+
get value() {
|
|
25
|
+
return this.#value;
|
|
26
|
+
}
|
|
27
|
+
get name() {
|
|
28
|
+
return this.#specs.name;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Represents the fields defined in the plugin settings
|
|
32
|
+
*/
|
|
33
|
+
get fields() {
|
|
34
|
+
const formula = <IComplexCondition>this.formula;
|
|
35
|
+
return typeof formula?.fields === 'string'
|
|
36
|
+
? [formula?.fields]
|
|
37
|
+
: formula?.fields;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get conditions() {
|
|
41
|
+
if (typeof this.#specs.formula === 'string') return;
|
|
42
|
+
const formula = this.#specs.formula as IComplexCondition;
|
|
43
|
+
return formula.conditions;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* FormField type
|
|
48
|
+
*/
|
|
49
|
+
#fields: any;
|
|
50
|
+
|
|
51
|
+
#parent: FormulaManager;
|
|
52
|
+
#ceil: boolean;
|
|
53
|
+
#round: boolean;
|
|
54
|
+
#isNotListenToChanges = false;
|
|
55
|
+
constructor(parent, plugin, specs) {
|
|
56
|
+
this.#parent = parent;
|
|
57
|
+
this.#plugin = plugin;
|
|
58
|
+
this.#specs = specs;
|
|
59
|
+
this.#round = specs.round;
|
|
60
|
+
this.#ceil = specs.ceil;
|
|
61
|
+
this.#emptyValue = specs.emptyValue;
|
|
62
|
+
|
|
63
|
+
if (specs.isNotListenToChanges)
|
|
64
|
+
this.#isNotListenToChanges = specs.isNotListenToChanges;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
initialize() {
|
|
68
|
+
try {
|
|
69
|
+
const { form } = this.#plugin;
|
|
70
|
+
|
|
71
|
+
if (!this.fields) {
|
|
72
|
+
throw new Error(`Fields not found in formula ${this.name}`);
|
|
73
|
+
}
|
|
74
|
+
const fields = this.fields.map((name) => {
|
|
75
|
+
const formula = this.#plugin.formulas.get(name);
|
|
76
|
+
if (formula) return formula;
|
|
77
|
+
const field = form.getField(name);
|
|
78
|
+
return field;
|
|
79
|
+
});
|
|
80
|
+
this.#fields = fields;
|
|
81
|
+
if (this.name === 'costoTotalGrafico') {
|
|
82
|
+
console.log('fields', fields);
|
|
83
|
+
}
|
|
84
|
+
if (!this.#isNotListenToChanges)
|
|
85
|
+
fields.forEach((field) => {
|
|
86
|
+
if (!field) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Field ${this.name} not found in form ${form.name}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
field.on('change', this.calculate.bind(this));
|
|
92
|
+
});
|
|
93
|
+
} catch (e) {}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
evaluate() {
|
|
97
|
+
const formula = <IComplexCondition>this.#specs.formula;
|
|
98
|
+
let evaluatedFormula: any = { formula: formula.base }; // Use the base formula by default
|
|
99
|
+
if (formula.conditions) {
|
|
100
|
+
const conditionsArray = Array.isArray(formula.conditions) ? formula.conditions : [formula.conditions];
|
|
101
|
+
for (const condition of conditionsArray) {
|
|
102
|
+
let conditionMet = false;
|
|
103
|
+
if (condition.conditions) {
|
|
104
|
+
// If there are nested conditions, all must be met
|
|
105
|
+
conditionMet = condition.conditions.every(
|
|
106
|
+
(subCondition) => {
|
|
107
|
+
const fieldValues = subCondition.fields.map(
|
|
108
|
+
(fieldName) => {
|
|
109
|
+
const field = this.#fields.find(
|
|
110
|
+
(f) => f.name === fieldName
|
|
111
|
+
);
|
|
112
|
+
return field
|
|
113
|
+
? field.value
|
|
114
|
+
: this.#emptyValue;
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
return EvaluationsManager.validateAll(
|
|
118
|
+
subCondition.condition,
|
|
119
|
+
fieldValues,
|
|
120
|
+
subCondition.value
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
} else {
|
|
125
|
+
const fieldValues = condition.fields.map((fieldName) => {
|
|
126
|
+
const field = this.#fields.find(
|
|
127
|
+
(f) => f.name === fieldName
|
|
128
|
+
);
|
|
129
|
+
return field ? field.value : this.#emptyValue;
|
|
130
|
+
});
|
|
131
|
+
const conditionType =
|
|
132
|
+
!!condition.type && conditionsTypes[condition.type]
|
|
133
|
+
? conditionsTypes[condition.type]
|
|
134
|
+
: conditionsTypes.some;
|
|
135
|
+
// Check if any of the specified fields meet the condition
|
|
136
|
+
conditionMet = EvaluationsManager[conditionType](
|
|
137
|
+
condition.condition,
|
|
138
|
+
fieldValues,
|
|
139
|
+
condition.value
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (conditionMet) {
|
|
144
|
+
evaluatedFormula.formula = condition.formula;
|
|
145
|
+
evaluatedFormula.fi = condition;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return evaluatedFormula;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async calculate() {
|
|
154
|
+
/**
|
|
155
|
+
* the formula is taken from the evaluate method since the conditions are evaluated there and
|
|
156
|
+
* can change the formula to be applied
|
|
157
|
+
*/
|
|
158
|
+
const model = this.#plugin.form.getField(this.name);
|
|
159
|
+
const formula = this.evaluate();
|
|
160
|
+
|
|
161
|
+
if (!formula.formula) {
|
|
162
|
+
this.#value =
|
|
163
|
+
this.#emptyValue !== undefined ? this.#emptyValue : '';
|
|
164
|
+
model && model.set({ value: this.#value });
|
|
165
|
+
this.#parent.trigger('change');
|
|
166
|
+
return this.#value;
|
|
167
|
+
}
|
|
168
|
+
// todo: Review if this section can be replaced by formulaManager.variables property.
|
|
169
|
+
const { tokens } = this.#parent.getParser(formula);
|
|
170
|
+
const variables = tokens
|
|
171
|
+
.filter((token) => token.type === 'variable')
|
|
172
|
+
.map((item) => item.value);
|
|
173
|
+
|
|
174
|
+
const params = await this.#parent.getParams(variables);
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const keys = Object.keys(params);
|
|
178
|
+
let result =
|
|
179
|
+
keys.length === 1
|
|
180
|
+
? params[keys[0]]
|
|
181
|
+
: parse(formula.formula as string).evaluate(params);
|
|
182
|
+
|
|
183
|
+
const isInvalidResult = [
|
|
184
|
+
-Infinity,
|
|
185
|
+
Infinity,
|
|
186
|
+
undefined,
|
|
187
|
+
null,
|
|
188
|
+
NaN,
|
|
189
|
+
].includes(result);
|
|
190
|
+
if (this.#round && !isInvalidResult) result = Math.round(result);
|
|
191
|
+
if (this.#ceil && !isInvalidResult) result = Math.ceil(result);
|
|
192
|
+
this.#value =
|
|
193
|
+
isInvalidResult || typeof result === 'object'
|
|
194
|
+
? this.#emptyValue
|
|
195
|
+
: Number(result.toFixed(2));
|
|
196
|
+
|
|
197
|
+
this.#parent.trigger('change');
|
|
198
|
+
|
|
199
|
+
model && model.set({ value: this.#value });
|
|
200
|
+
return this.#value;
|
|
201
|
+
} catch (e) {
|
|
202
|
+
console.log('formula', this.name, formula.formula, params);
|
|
203
|
+
console.error(e);
|
|
204
|
+
throw new Error('Error calculating the formula');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { FormulaManager } from '..';
|
|
2
|
+
import { EvaluationsManager } from '../helpers/evaluations';
|
|
3
|
+
import { Token } from '../helpers/token';
|
|
4
|
+
import { FormulaObserver, IComplexCondition } from '../types/formulas';
|
|
5
|
+
import { parse } from 'mathjs';
|
|
6
|
+
|
|
7
|
+
export class IterativeArrayFormula {
|
|
8
|
+
#plugin: any;
|
|
9
|
+
#specs: FormulaObserver;
|
|
10
|
+
#tokens: Token[];
|
|
11
|
+
get formula() {
|
|
12
|
+
return this.#specs.formula;
|
|
13
|
+
}
|
|
14
|
+
get base() {
|
|
15
|
+
const formula = <IComplexCondition>this.#specs.formula;
|
|
16
|
+
return formula.base;
|
|
17
|
+
}
|
|
18
|
+
#value: string | number | undefined | 0;
|
|
19
|
+
get value() {
|
|
20
|
+
return this.#value;
|
|
21
|
+
}
|
|
22
|
+
get name() {
|
|
23
|
+
return this.#specs.name;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Represents the fields defined in the plugin settings
|
|
27
|
+
*/
|
|
28
|
+
get fields() {
|
|
29
|
+
const formula = <IComplexCondition>this.formula;
|
|
30
|
+
return typeof formula?.fields === 'string' ? [formula?.fields] : formula?.fields;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get conditions() {
|
|
34
|
+
if (typeof this.#specs.formula === 'string') return;
|
|
35
|
+
const formula = this.#specs.formula as IComplexCondition;
|
|
36
|
+
return formula.conditions;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#emptyValue: string | number;
|
|
40
|
+
#variables: string[] = [];
|
|
41
|
+
get variables() {
|
|
42
|
+
return this.#variables;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#round: boolean;
|
|
46
|
+
#ceil: boolean
|
|
47
|
+
|
|
48
|
+
#parent: FormulaManager;
|
|
49
|
+
|
|
50
|
+
#isNotListenToChanges = false
|
|
51
|
+
constructor(parent, plugin, specs) {
|
|
52
|
+
this.#parent = parent;
|
|
53
|
+
this.#plugin = plugin;
|
|
54
|
+
this.#specs = specs;
|
|
55
|
+
this.#round = specs.round;
|
|
56
|
+
this.#ceil = specs.ceil;
|
|
57
|
+
this.#emptyValue = this.#specs.emptyValue;
|
|
58
|
+
this.#isNotListenToChanges = specs.isNotListenToChanges
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
initialize() {
|
|
62
|
+
const fieldArray = this.#plugin.form.getField(this.#specs.arrayFieldName);
|
|
63
|
+
if (!fieldArray) {
|
|
64
|
+
console.error(`Field ${this.#specs.arrayFieldName} does NOT exist.`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
fieldArray.on('change', this.calculate.bind(this));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async calculate() {
|
|
71
|
+
|
|
72
|
+
const formulaField = this.#plugin.form.getField(this.name);
|
|
73
|
+
|
|
74
|
+
const fieldArray = this.#plugin.form.getField(this.#specs.arrayFieldName);
|
|
75
|
+
|
|
76
|
+
if (!fieldArray) {
|
|
77
|
+
console.error(`Field ${this.#specs.arrayFieldName} does NOT exist.`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const entries = fieldArray[this.#specs.arrayFieldProperty];
|
|
82
|
+
|
|
83
|
+
if (!Array.isArray(entries)) {
|
|
84
|
+
console.error(`Property ${this.#specs.arrayFieldProperty} is not an array.`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const empty = !entries.length;
|
|
89
|
+
const formula: any = this.#specs.formula;
|
|
90
|
+
let formulaEvaluate = formula?.formula || formula
|
|
91
|
+
if (empty) {
|
|
92
|
+
// If all models are empty, set the input to empty if exists.
|
|
93
|
+
if (formulaField) formulaField.set({ value: this.#emptyValue !== undefined ? this.#emptyValue : '' });
|
|
94
|
+
this.#value = undefined;
|
|
95
|
+
this.#parent.trigger('change');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
let totalResult: string | number = 0;
|
|
101
|
+
for (let item of entries) {
|
|
102
|
+
if (formula.conditions) {
|
|
103
|
+
for (const condition of formula.conditions) {
|
|
104
|
+
const comparisonValue = item[condition.property]
|
|
105
|
+
let conditionMet = EvaluationsManager.validate(condition.condition, comparisonValue, condition.value);
|
|
106
|
+
if (conditionMet) {
|
|
107
|
+
formulaEvaluate = condition.formula;
|
|
108
|
+
break
|
|
109
|
+
} else {
|
|
110
|
+
formulaEvaluate = formula.base
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const attrs = this.sanitizeData(item);
|
|
115
|
+
let result = parse(formulaEvaluate as string).evaluate(attrs);
|
|
116
|
+
const isInvalidResult = [-Infinity, Infinity, undefined, null, NaN].includes(result);
|
|
117
|
+
if (this.#round && !isInvalidResult) result = Math.round(result);
|
|
118
|
+
if (this.#ceil && !isInvalidResult) result = Math.ceil(result);
|
|
119
|
+
totalResult = isInvalidResult ? totalResult : Number(totalResult) + Number(result.toFixed(2))
|
|
120
|
+
}
|
|
121
|
+
const isInvalidResult = [-Infinity, Infinity, undefined, null, NaN, ''].includes(totalResult);
|
|
122
|
+
this.#value = isInvalidResult ? this.#emptyValue : totalResult
|
|
123
|
+
if (formulaField) formulaField.set({ value: this.#value });
|
|
124
|
+
this.#parent.trigger('change');
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.log('formula', this.name, this.formula);
|
|
127
|
+
console.trace(e);
|
|
128
|
+
throw new Error(`Error calculating the formula: ${e.message} ${this.name}`);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
private sanitizeData(data: any): any {
|
|
133
|
+
if (Array.isArray(data)) {
|
|
134
|
+
return data.map(item => this.sanitizeData(item));
|
|
135
|
+
} else if (typeof data === 'object' && data !== null) {
|
|
136
|
+
const sanitizedData: any = {};
|
|
137
|
+
for (const key in data) {
|
|
138
|
+
if (data.hasOwnProperty(key)) {
|
|
139
|
+
sanitizedData[key] = this.sanitizeData(data[key]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return sanitizedData;
|
|
143
|
+
} else {
|
|
144
|
+
return this.sanitizeValue(data);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private sanitizeValue(value: any, defaultValue: number = 0): number {
|
|
149
|
+
return (value === null || value === undefined || isNaN(value)) ? defaultValue : Number(value);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { FormulaManager } from '../';
|
|
2
|
+
import { EvaluationsManager } from '../helpers/evaluations';
|
|
3
|
+
import { Parser } from '../helpers/parser';
|
|
4
|
+
import { FormulaObserver, IComplexCondition, ParserData } from '../types/formulas';
|
|
5
|
+
import { filter, parse } from 'mathjs';
|
|
6
|
+
|
|
7
|
+
export class FormulaPerValue {
|
|
8
|
+
#plugin: any;
|
|
9
|
+
#emptyValue: undefined;
|
|
10
|
+
#specs: FormulaObserver;
|
|
11
|
+
get formula() {
|
|
12
|
+
return this.#specs.formula;
|
|
13
|
+
}
|
|
14
|
+
#value: string | number | undefined | 0;
|
|
15
|
+
get value() {
|
|
16
|
+
return this.#value;
|
|
17
|
+
}
|
|
18
|
+
get name() {
|
|
19
|
+
return this.#specs.name;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#observers: string[];
|
|
23
|
+
get observers() {
|
|
24
|
+
return this.#observers;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Represents the fields defined in the plugin settings
|
|
28
|
+
*/
|
|
29
|
+
get fields() {
|
|
30
|
+
const formula = <IComplexCondition>this.formula;
|
|
31
|
+
return typeof formula?.fields === 'string' ? [formula?.fields] : formula?.fields;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get conditions() {
|
|
35
|
+
if (typeof this.#specs.formula === 'string') return;
|
|
36
|
+
const formula = this.#specs.formula as IComplexCondition;
|
|
37
|
+
return formula.conditions;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#parent: FormulaManager;
|
|
41
|
+
#parsers: ParserData[];
|
|
42
|
+
#mainFields: any[];
|
|
43
|
+
#isNotListenToChanges = false
|
|
44
|
+
constructor(parent, plugin, specs) {
|
|
45
|
+
this.#parent = parent;
|
|
46
|
+
this.#plugin = plugin;
|
|
47
|
+
this.#specs = specs;
|
|
48
|
+
this.#observers = specs.formula.observers;
|
|
49
|
+
this.#isNotListenToChanges = specs.isNotListenToChanges
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
initialize() {
|
|
53
|
+
const { form } = this.#plugin;
|
|
54
|
+
const fields = new Set<string>();
|
|
55
|
+
|
|
56
|
+
this.#mainFields = this.#parent.getModels(this.fields);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The method will iterate over the conditions to get the parser for each value
|
|
60
|
+
* and get access to the fields that are part of the formula and be able to evaluate it
|
|
61
|
+
* changes.
|
|
62
|
+
*/
|
|
63
|
+
const conditionsArray = Array.isArray(this.conditions) ? this.conditions : [];
|
|
64
|
+
conditionsArray.forEach(condition => {
|
|
65
|
+
if (!condition.condition) {
|
|
66
|
+
throw new Error('the formula per value must contain a condition property in the condition`s item');
|
|
67
|
+
}
|
|
68
|
+
if (!condition.values) {
|
|
69
|
+
throw new Error('the formula per value must contain a values property in the condition`s item');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const parsers = condition.values.map(item => this.#parent.getParser(item));
|
|
73
|
+
this.#parsers = parsers;
|
|
74
|
+
parsers.forEach(parser => {
|
|
75
|
+
parser.tokens.filter(token => token.type === 'variable').forEach(token => fields.add(token.value));
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
fields.forEach(field => {
|
|
80
|
+
const model = form.getField(field);
|
|
81
|
+
if (model) model.on('change', this.listenConditionals.bind(this));
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
this.listenConditionals();
|
|
85
|
+
if (!this.#isNotListenToChanges) this.#mainFields.forEach(item => item.on('change', this.calculate.bind(this)));
|
|
86
|
+
if (!this.#isNotListenToChanges) if (this.#observers && Array.isArray(this.#observers) && !!this.#observers.length) {
|
|
87
|
+
const fields = this.#parent.getModels(this.#observers);
|
|
88
|
+
fields.forEach(field => {
|
|
89
|
+
if (!field) return;
|
|
90
|
+
field.on('change', this.calculateAll.bind(this));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
calculateAll() {
|
|
96
|
+
this.#mainFields.forEach(field => this.calculate(field));
|
|
97
|
+
}
|
|
98
|
+
listenConditionals() {
|
|
99
|
+
this.#mainFields.forEach(field => {
|
|
100
|
+
if (!field) return;
|
|
101
|
+
field.on('change', this.calculate.bind(this));
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async calculate(field) {
|
|
106
|
+
if (!field) return;
|
|
107
|
+
const { form } = this.#plugin;
|
|
108
|
+
const formula = this.evaluate(field.value);
|
|
109
|
+
|
|
110
|
+
if (!formula) return;
|
|
111
|
+
|
|
112
|
+
const variables = formula.tokens.filter(token => token.type === 'variable').map(item => item.value);
|
|
113
|
+
const params = await this.#parent.getParams(variables);
|
|
114
|
+
const formulaField = form.getField(this.name);
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const keys = Object.keys(params);
|
|
118
|
+
const result = keys.length === 1 ? params[keys[0]] : parse(formula.formula as string).evaluate(params);
|
|
119
|
+
this.#value = [-Infinity, Infinity, undefined, null, NaN].includes(result)
|
|
120
|
+
? this.#emptyValue
|
|
121
|
+
: Number(result.toFixed(2));
|
|
122
|
+
formulaField && formulaField.set({ value: this.#value });
|
|
123
|
+
this.#parent.trigger('change');
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.log(e);
|
|
126
|
+
throw new Error('Error calculating the formula');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
evaluate(value) {
|
|
131
|
+
let formula = undefined;
|
|
132
|
+
if ([null, undefined].includes(value)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const conditionsArray = Array.isArray(this.conditions) ? this.conditions : [];
|
|
136
|
+
conditionsArray.forEach(item => {
|
|
137
|
+
const { condition, values } = item;
|
|
138
|
+
if (!condition) {
|
|
139
|
+
throw new Error('the formula per value must contain a condition property in the condition`s item');
|
|
140
|
+
}
|
|
141
|
+
if (!values) {
|
|
142
|
+
throw new Error('the formula per value must contain a values property in the condition`s item');
|
|
143
|
+
}
|
|
144
|
+
const index = values.findIndex(item => EvaluationsManager.validate(condition, value, item.value));
|
|
145
|
+
|
|
146
|
+
if (index > -1) formula = this.#parent.getParser(values[index]);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return formula;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|