2
0
mirror of https://github.com/frappe/books.git synced 2024-11-14 09:24:04 +00:00
books/frappe/core/docHandler.ts

181 lines
3.9 KiB
TypeScript
Raw Normal View History

import Doc from 'frappe/model/doc';
import { DocMap, ModelMap } from 'frappe/model/types';
import { getRandomString } from 'frappe/utils';
2022-03-22 09:28:36 +00:00
import Observable from 'frappe/utils/observable';
import { Frappe } from '..';
import { DocValue, DocValueMap } from './types';
2022-03-22 09:28:36 +00:00
export class DocHandler {
frappe: Frappe;
singles: DocMap = {};
docs: Observable<DocMap> = new Observable();
models: ModelMap = {};
2022-03-22 09:28:36 +00:00
constructor(frappe: Frappe) {
this.frappe = frappe;
}
init() {
this.models = {};
this.docs = new Observable();
}
registerModels(models: ModelMap) {
for (const schemaName in models) {
this.models[schemaName] = models[schemaName];
2022-03-22 09:28:36 +00:00
}
}
/**
* Cache operations
*/
addToCache(doc: Doc) {
if (!this.docs) {
return;
}
2022-03-22 09:28:36 +00:00
// add to `docs` cache
const name = doc.name;
const schemaName = doc.schemaName;
2022-03-22 09:28:36 +00:00
if (!name) {
2022-03-22 09:28:36 +00:00
return;
}
if (!this.docs[schemaName]) {
this.docs[schemaName] = {};
2022-03-22 09:28:36 +00:00
}
(this.docs[schemaName] as DocMap)[name] = doc;
2022-03-22 09:28:36 +00:00
// singles available as first level objects too
if (schemaName === doc.name) {
2022-03-22 09:28:36 +00:00
this.singles[name] = doc;
}
// propagate change to `docs`
2022-03-22 09:28:36 +00:00
doc.on('change', (params: unknown) => {
this.docs!.trigger('change', params);
});
}
removeFromCache(schemaName: string, name: string) {
const docMap = this.docs[schemaName] as DocMap | undefined;
delete docMap?.[name];
2022-03-22 09:28:36 +00:00
}
getFromCache(schemaName: string, name: string): Doc | undefined {
const docMap = this.docs[schemaName] as DocMap | undefined;
return docMap?.[name];
2022-03-22 09:28:36 +00:00
}
getCachedValue(
schemaName: string,
name: string,
fieldname: string
): DocValue | Doc[] | undefined {
const docMap = this.docs[schemaName] as DocMap;
const doc = docMap[name];
2022-03-22 09:28:36 +00:00
if (doc === undefined) {
return;
2022-03-22 09:28:36 +00:00
}
return doc.get(fieldname);
2022-03-22 09:28:36 +00:00
}
isDirty(schemaName: string, name: string): boolean {
const doc = (this.docs?.[schemaName] as DocMap)?.[name];
if (doc === undefined) {
return false;
2022-03-22 09:28:36 +00:00
}
return doc.dirty;
2022-03-22 09:28:36 +00:00
}
/**
* Doc Operations
*/
async getDoc(
schemaName: string,
2022-03-22 09:28:36 +00:00
name: string,
options = { skipDocumentCache: false }
) {
let doc: Doc | undefined;
2022-03-22 09:28:36 +00:00
if (!options?.skipDocumentCache) {
doc = this.getFromCache(schemaName, name);
2022-03-22 09:28:36 +00:00
}
if (doc) {
return doc;
}
doc = this.getNewDoc(schemaName, { name });
2022-03-22 09:28:36 +00:00
await doc.load();
this.addToCache(doc);
return doc;
}
getModel(schemaName: string): typeof Doc {
const Model = this.models[schemaName];
if (Model === undefined) {
return Doc;
2022-03-22 09:28:36 +00:00
}
return Model;
2022-03-22 09:28:36 +00:00
}
async getSingle(schemaName: string) {
return await this.getDoc(schemaName, schemaName);
2022-03-22 09:28:36 +00:00
}
async getDuplicate(doc: Doc): Promise<Doc> {
const newDoc = await doc.duplicate(false);
delete newDoc.name;
2022-03-22 09:28:36 +00:00
return newDoc;
}
getEmptyDoc(schemaName: string, cacheDoc: boolean = true): Doc {
const doc = this.getNewDoc(schemaName);
2022-03-22 09:28:36 +00:00
doc.name = getRandomString();
if (cacheDoc) {
this.addToCache(doc);
}
return doc;
}
getNewDoc(schemaName: string, data: DocValueMap = {}): Doc {
const Model = this.getModel(schemaName);
const schema = this.frappe.schemaMap[schemaName];
if (schema === undefined) {
throw new Error(`Schema not found for ${schemaName}`);
}
const doc = new Model(schema, data);
2022-03-22 09:28:36 +00:00
doc.setDefaults();
return doc;
}
async syncDoc(schemaName: string, data: DocValueMap) {
const name = data.name as string | undefined;
if (name === undefined) {
2022-03-22 09:28:36 +00:00
return;
}
const docExists = await this.frappe.db.exists(schemaName, name);
if (!docExists) {
const doc = this.getNewDoc(schemaName, data);
await doc.insert;
return;
2022-03-22 09:28:36 +00:00
}
const doc = await this.getDoc(schemaName, name);
await doc.setMultiple(data);
await doc.update();
}
2022-03-22 09:28:36 +00:00
}