2
0
mirror of https://github.com/frappe/books.git synced 2024-12-23 03:19:01 +00:00

fix: transitive dependent field updates

This commit is contained in:
18alantom 2022-09-30 16:46:09 +05:30
parent 537a8f7153
commit d986471323

View File

@ -186,7 +186,8 @@ export class Doc extends Observable<DocValue | Doc[]> {
// set value and trigger change // set value and trigger change
async set( async set(
fieldname: string | DocValueMap, fieldname: string | DocValueMap,
value?: DocValue | Doc[] | DocValueMap[] value?: DocValue | Doc[] | DocValueMap[],
retriggerChildDocApplyChange: boolean = false
): Promise<boolean> { ): Promise<boolean> {
if (typeof fieldname === 'object') { if (typeof fieldname === 'object') {
return await this.setMultiple(fieldname as DocValueMap); return await this.setMultiple(fieldname as DocValueMap);
@ -216,7 +217,7 @@ export class Doc extends Observable<DocValue | Doc[]> {
await this._applyChange(fieldname); await this._applyChange(fieldname);
await this.parentdoc._applyChange(this.parentFieldname as string); await this.parentdoc._applyChange(this.parentFieldname as string);
} else { } else {
await this._applyChange(fieldname); await this._applyChange(fieldname, retriggerChildDocApplyChange);
} }
return true; return true;
@ -259,8 +260,11 @@ export class Doc extends Observable<DocValue | Doc[]> {
return !areDocValuesEqual(currentValue as DocValue, value as DocValue); return !areDocValuesEqual(currentValue as DocValue, value as DocValue);
} }
async _applyChange(fieldname: string): Promise<boolean> { async _applyChange(
await this._applyFormula(fieldname); fieldname: string,
retriggerChildDocApplyChange?: boolean
): Promise<boolean> {
await this._applyFormula(fieldname, retriggerChildDocApplyChange);
await this.trigger('change', { await this.trigger('change', {
doc: this, doc: this,
changed: fieldname, changed: fieldname,
@ -616,37 +620,62 @@ export class Doc extends Observable<DocValue | Doc[]> {
} }
} }
async _applyFormula(fieldname?: string): Promise<boolean> { async _applyFormula(
fieldname?: string,
retriggerChildDocApplyChange?: boolean
): Promise<boolean> {
const doc = this; const doc = this;
let changed = false; let changed = await this._callAllTableFieldsApplyFormula(fieldname);
changed = (await this._applyFormulaForFields(doc, fieldname)) || changed;
const childDocs = this.tableFields if (changed && retriggerChildDocApplyChange) {
.map((f) => (this.get(f.fieldname) as Doc[]) ?? []) await this._callAllTableFieldsApplyFormula(fieldname);
.flat(); await this._applyFormulaForFields(doc, fieldname);
// children
for (const row of childDocs) {
changed ||= (await row?._applyFormula()) ?? false;
} }
// parent or child row return changed;
}
async _callAllTableFieldsApplyFormula(
changedFieldname?: string
): Promise<boolean> {
let changed = false;
for (const { fieldname } of this.tableFields) {
const childDocs = this.get(fieldname) as Doc[];
if (!childDocs) {
continue;
}
changed =
(await this._callChildDocApplyFormula(childDocs, changedFieldname)) ||
changed;
}
return changed;
}
async _callChildDocApplyFormula(
childDocs: Doc[],
fieldname?: string
): Promise<boolean> {
let changed: boolean = false;
for (const childDoc of childDocs) {
if (!childDoc._applyFormula) {
continue;
}
changed = (await childDoc._applyFormula(fieldname)) || changed;
}
return changed;
}
async _applyFormulaForFields(doc: Doc, fieldname?: string) {
const formulaFields = Object.keys(this.formulas).map( const formulaFields = Object.keys(this.formulas).map(
(fn) => this.fieldMap[fn] (fn) => this.fieldMap[fn]
); );
changed ||= await this._applyFormulaForFields(
formulaFields,
doc,
fieldname
);
return changed;
}
async _applyFormulaForFields(
formulaFields: Field[],
doc: Doc,
fieldname?: string
) {
let changed = false; let changed = false;
for (const field of formulaFields) { for (const field of formulaFields) {
const shouldApply = shouldApplyFormula(field, doc, fieldname); const shouldApply = shouldApplyFormula(field, doc, fieldname);
@ -662,7 +691,7 @@ export class Doc extends Observable<DocValue | Doc[]> {
} }
doc[field.fieldname] = newVal; doc[field.fieldname] = newVal;
changed = true; changed ||= true;
} }
return changed; return changed;