mirror of
https://github.com/frappe/books.git
synced 2024-12-23 03:19:01 +00:00
incr: type observable
- convert several to ES6
This commit is contained in:
parent
507a500edb
commit
47e6493699
@ -1,15 +1,13 @@
|
||||
const utils = require('../utils');
|
||||
const format = require('../utils/format');
|
||||
const errors = require('./errors');
|
||||
const BaseDocument = require('frappe/model/document');
|
||||
const BaseMeta = require('frappe/model/meta');
|
||||
export default async function initLibs(frappe) {
|
||||
const utils = await import('../utils');
|
||||
const format = await import('../utils/format');
|
||||
const errors = await import('./errors');
|
||||
const BaseMeta = await import('frappe/model/meta');
|
||||
const BaseDocument = await import('frappe/model/document');
|
||||
|
||||
module.exports = {
|
||||
initLibs(frappe) {
|
||||
Object.assign(frappe, utils);
|
||||
Object.assign(frappe, format);
|
||||
frappe.errors = errors;
|
||||
frappe.BaseDocument = BaseDocument;
|
||||
frappe.BaseMeta = BaseMeta;
|
||||
},
|
||||
};
|
||||
Object.assign(frappe, utils.default);
|
||||
Object.assign(frappe, format.default);
|
||||
frappe.errors = errors.default;
|
||||
frappe.BaseDocument = BaseDocument.default;
|
||||
frappe.BaseMeta = BaseMeta.default;
|
||||
}
|
||||
|
118
frappe/index.js
118
frappe/index.js
@ -1,25 +1,25 @@
|
||||
const Observable = require('./utils/observable');
|
||||
const { T, t } = require('./utils/translation');
|
||||
const utils = require('./utils');
|
||||
const { getMoneyMaker } = require('pesa');
|
||||
const {
|
||||
DEFAULT_INTERNAL_PRECISION,
|
||||
import initLibs from 'frappe/common';
|
||||
import { getMoneyMaker } from 'pesa';
|
||||
import { markRaw } from 'vue';
|
||||
import utils from './utils';
|
||||
import {
|
||||
DEFAULT_DISPLAY_PRECISION,
|
||||
} = require('./utils/consts');
|
||||
const { markRaw } = require('vue');
|
||||
DEFAULT_INTERNAL_PRECISION,
|
||||
} from './utils/consts';
|
||||
import Observable from './utils/observable';
|
||||
import { t, T } from './utils/translation';
|
||||
|
||||
module.exports = {
|
||||
isElectron: false,
|
||||
isServer: false,
|
||||
class Frappe {
|
||||
isElectron = false;
|
||||
isServer = false;
|
||||
|
||||
initializeAndRegister(customModels = {}, force = false) {
|
||||
async initializeAndRegister(customModels = {}, force = false) {
|
||||
this.init(force);
|
||||
const common = require('frappe/common');
|
||||
this.registerLibs(common);
|
||||
const coreModels = require('frappe/models');
|
||||
this.registerModels(coreModels);
|
||||
await initLibs(this);
|
||||
const coreModels = await import('frappe/models');
|
||||
this.registerModels(coreModels.default);
|
||||
this.registerModels(customModels);
|
||||
},
|
||||
}
|
||||
|
||||
async initializeMoneyMaker(currency) {
|
||||
currency ??= 'XXX';
|
||||
@ -65,26 +65,19 @@ module.exports = {
|
||||
display,
|
||||
wrapper: markRaw,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
init(force) {
|
||||
if (this._initialized && !force) return;
|
||||
this.initConfig();
|
||||
this.initGlobals();
|
||||
this.docs = new Observable();
|
||||
this.events = new Observable();
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
initConfig() {
|
||||
// Initialize Config
|
||||
this.config = {
|
||||
serverURL: '',
|
||||
backend: 'sqlite',
|
||||
port: 8000,
|
||||
};
|
||||
},
|
||||
|
||||
initGlobals() {
|
||||
// Initialize Globals
|
||||
this.metaCache = {};
|
||||
this.models = {};
|
||||
this.forms = {};
|
||||
@ -92,15 +85,15 @@ module.exports = {
|
||||
this.flags = {};
|
||||
this.methods = {};
|
||||
this.errorLog = [];
|
||||
|
||||
// temp params while calling routes
|
||||
this.temp = {};
|
||||
this.params = {};
|
||||
},
|
||||
|
||||
registerLibs(common) {
|
||||
// add standard libs and utils to frappe
|
||||
common.initLibs(this);
|
||||
},
|
||||
this.docs = new Observable();
|
||||
this.events = new Observable();
|
||||
this._initialized = true;
|
||||
}
|
||||
|
||||
registerModels(models) {
|
||||
// register models from app/models/index.js
|
||||
@ -126,7 +119,7 @@ module.exports = {
|
||||
|
||||
this.models[doctype] = metaDefinition;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getModels(filterFunction) {
|
||||
let models = [];
|
||||
@ -134,12 +127,12 @@ module.exports = {
|
||||
models.push(this.models[doctype]);
|
||||
}
|
||||
return filterFunction ? models.filter(filterFunction) : models;
|
||||
},
|
||||
}
|
||||
|
||||
registerView(view, name, module) {
|
||||
if (!this.views[view]) this.views[view] = {};
|
||||
this.views[view][name] = module;
|
||||
},
|
||||
}
|
||||
|
||||
registerMethod({ method, handler }) {
|
||||
this.methods[method] = handler;
|
||||
@ -156,7 +149,7 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
async call({ method, args }) {
|
||||
if (this.isServer) {
|
||||
@ -177,7 +170,7 @@ module.exports = {
|
||||
body: JSON.stringify(args || {}),
|
||||
});
|
||||
return await response.json();
|
||||
},
|
||||
}
|
||||
|
||||
addToCache(doc) {
|
||||
if (!this.docs) return;
|
||||
@ -199,7 +192,7 @@ module.exports = {
|
||||
this.docs.trigger('change', params);
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
removeFromCache(doctype, name) {
|
||||
try {
|
||||
@ -207,7 +200,7 @@ module.exports = {
|
||||
} catch (e) {
|
||||
console.warn(`Document ${doctype} ${name} does not exist`);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
isDirty(doctype, name) {
|
||||
return (
|
||||
@ -217,13 +210,13 @@ module.exports = {
|
||||
this.docs[doctype][name]._dirty) ||
|
||||
false
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
getDocFromCache(doctype, name) {
|
||||
if (this.docs && this.docs[doctype] && this.docs[doctype][name]) {
|
||||
return this.docs[doctype][name];
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getMeta(doctype) {
|
||||
if (!this.metaCache[doctype]) {
|
||||
@ -231,12 +224,13 @@ module.exports = {
|
||||
if (!model) {
|
||||
throw new Error(`${doctype} is not a registered doctype`);
|
||||
}
|
||||
|
||||
let metaClass = model.metaClass || this.BaseMeta;
|
||||
this.metaCache[doctype] = new metaClass(model);
|
||||
}
|
||||
|
||||
return this.metaCache[doctype];
|
||||
},
|
||||
}
|
||||
|
||||
async getDoc(doctype, name, options = { skipDocumentCache: false }) {
|
||||
let doc = options.skipDocumentCache
|
||||
@ -251,16 +245,16 @@ module.exports = {
|
||||
this.addToCache(doc);
|
||||
}
|
||||
return doc;
|
||||
},
|
||||
}
|
||||
|
||||
getDocumentClass(doctype) {
|
||||
const meta = this.getMeta(doctype);
|
||||
return meta.documentClass || this.BaseDocument;
|
||||
},
|
||||
}
|
||||
|
||||
async getSingle(doctype) {
|
||||
return await this.getDoc(doctype, doctype);
|
||||
},
|
||||
}
|
||||
|
||||
async getDuplicate(doc) {
|
||||
const newDoc = await this.getNewDoc(doc.doctype);
|
||||
@ -277,7 +271,7 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
return newDoc;
|
||||
},
|
||||
}
|
||||
|
||||
getNewDoc(doctype, cacheDoc = true) {
|
||||
let doc = this.newDoc({ doctype: doctype });
|
||||
@ -287,7 +281,7 @@ module.exports = {
|
||||
this.addToCache(doc);
|
||||
}
|
||||
return doc;
|
||||
},
|
||||
}
|
||||
|
||||
async newCustomDoc(fields) {
|
||||
let doc = new this.BaseDocument({ isCustom: 1, fields });
|
||||
@ -295,22 +289,22 @@ module.exports = {
|
||||
doc.name = this.getRandomString();
|
||||
this.addToCache(doc);
|
||||
return doc;
|
||||
},
|
||||
}
|
||||
|
||||
createMeta(fields) {
|
||||
let meta = new this.BaseMeta({ isCustom: 1, fields });
|
||||
return meta;
|
||||
},
|
||||
}
|
||||
|
||||
newDoc(data) {
|
||||
let doc = new (this.getDocumentClass(data.doctype))(data);
|
||||
doc.setDefaults();
|
||||
return doc;
|
||||
},
|
||||
}
|
||||
|
||||
async insert(data) {
|
||||
return await this.newDoc(data).insert();
|
||||
},
|
||||
}
|
||||
|
||||
async syncDoc(data) {
|
||||
let doc;
|
||||
@ -322,7 +316,7 @@ module.exports = {
|
||||
doc = this.newDoc(data);
|
||||
await doc.insert();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// only for client side
|
||||
async login(email, password) {
|
||||
@ -354,7 +348,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
return response;
|
||||
},
|
||||
}
|
||||
|
||||
async signup(email, fullName, password) {
|
||||
let response = await fetch(this.getServerURL() + '/api/signup', {
|
||||
@ -371,11 +365,11 @@ module.exports = {
|
||||
}
|
||||
|
||||
return response;
|
||||
},
|
||||
}
|
||||
|
||||
getServerURL() {
|
||||
return this.config.serverURL || '';
|
||||
},
|
||||
}
|
||||
|
||||
close() {
|
||||
this.db.close();
|
||||
@ -383,11 +377,15 @@ module.exports = {
|
||||
if (this.server) {
|
||||
this.server.close();
|
||||
}
|
||||
},
|
||||
t,
|
||||
T,
|
||||
store: {
|
||||
}
|
||||
|
||||
store = {
|
||||
isDevelopment: false,
|
||||
appVersion: '',
|
||||
},
|
||||
};
|
||||
t = t;
|
||||
T = T;
|
||||
}
|
||||
|
||||
export { T, t };
|
||||
export default new Frappe();
|
||||
|
@ -1,12 +1,12 @@
|
||||
const frappe = require('frappe');
|
||||
const Observable = require('frappe/utils/observable');
|
||||
const naming = require('./naming');
|
||||
const { isPesa } = require('../utils/index');
|
||||
const { DEFAULT_INTERNAL_PRECISION } = require('../utils/consts');
|
||||
const { Verb } = require('@/telemetry/types');
|
||||
const { default: telemetry } = require('@/telemetry/telemetry');
|
||||
import telemetry from '@/telemetry/telemetry';
|
||||
import { Verb } from '@/telemetry/types';
|
||||
import frappe from 'frappe';
|
||||
import Observable from 'frappe/utils/observable';
|
||||
import { DEFAULT_INTERNAL_PRECISION } from '../utils/consts';
|
||||
import { isPesa } from '../utils/index';
|
||||
import { setName } from './naming';
|
||||
|
||||
module.exports = class BaseDocument extends Observable {
|
||||
export default class Document extends Observable {
|
||||
constructor(data) {
|
||||
super();
|
||||
this.fetchValuesCache = {};
|
||||
@ -171,7 +171,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
}
|
||||
|
||||
_initChild(data, key) {
|
||||
if (data instanceof BaseDocument) {
|
||||
if (data instanceof Document) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
data.name = frappe.getRandomString();
|
||||
}
|
||||
|
||||
const childDoc = new BaseDocument(data);
|
||||
const childDoc = new Document(data);
|
||||
childDoc.setDefaults();
|
||||
return childDoc;
|
||||
}
|
||||
@ -549,10 +549,6 @@ module.exports = class BaseDocument extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
async setName() {
|
||||
await naming.setName(this);
|
||||
}
|
||||
|
||||
async commit() {
|
||||
// re-run triggers
|
||||
this.setKeywords();
|
||||
@ -562,7 +558,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
}
|
||||
|
||||
async insert() {
|
||||
await this.setName();
|
||||
await setName(this);
|
||||
this.setStandardValues();
|
||||
await this.commit();
|
||||
await this.validateInsert();
|
||||
@ -745,7 +741,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
await doc.set(updateMap);
|
||||
await doc.insert();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getPreDefaultValues(fieldtype) {
|
||||
switch (fieldtype) {
|
||||
|
@ -1,16 +1,16 @@
|
||||
const BaseDocument = require('./document');
|
||||
const frappe = require('frappe');
|
||||
const model = require('./index');
|
||||
const { indicators: indicatorColor } = require('../../src/colors');
|
||||
import frappe from 'frappe';
|
||||
import { indicators as indicatorColor } from '../../src/colors';
|
||||
import Document from './document';
|
||||
import model from './index';
|
||||
|
||||
module.exports = class BaseMeta extends BaseDocument {
|
||||
export default class BaseMeta extends Document {
|
||||
constructor(data) {
|
||||
if (data.basedOn) {
|
||||
let config = frappe.models[data.basedOn];
|
||||
Object.assign(data, config, {
|
||||
name: data.name,
|
||||
label: data.label,
|
||||
filters: data.filters
|
||||
filters: data.filters,
|
||||
});
|
||||
}
|
||||
super(data);
|
||||
@ -30,7 +30,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
|
||||
processFields() {
|
||||
// add name field
|
||||
if (!this.fields.find(df => df.fieldname === 'name') && !this.isSingle) {
|
||||
if (!this.fields.find((df) => df.fieldname === 'name') && !this.isSingle) {
|
||||
this.fields = [
|
||||
{
|
||||
label: frappe.t`ID`,
|
||||
@ -42,7 +42,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
].concat(this.fields);
|
||||
}
|
||||
|
||||
this.fields = this.fields.map(df => {
|
||||
this.fields = this.fields.map((df) => {
|
||||
// name field is always required
|
||||
if (df.fieldname === 'name') {
|
||||
df.required = 1;
|
||||
@ -75,7 +75,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
* dataFields = meta.getFieldsWith({ fieldtype: 'Data' })
|
||||
*/
|
||||
getFieldsWith(filters) {
|
||||
return this.fields.filter(df => {
|
||||
return this.fields.filter((df) => {
|
||||
let match = true;
|
||||
for (const key in filters) {
|
||||
const value = filters[key];
|
||||
@ -93,7 +93,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
getTableFields() {
|
||||
if (this._tableFields === undefined) {
|
||||
this._tableFields = this.fields.filter(
|
||||
field => field.fieldtype === 'Table'
|
||||
(field) => field.fieldtype === 'Table'
|
||||
);
|
||||
}
|
||||
return this._tableFields;
|
||||
@ -101,7 +101,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
|
||||
getFormulaFields() {
|
||||
if (this._formulaFields === undefined) {
|
||||
this._formulaFields = this.fields.filter(field => field.formula);
|
||||
this._formulaFields = this.fields.filter((field) => field.formula);
|
||||
}
|
||||
return this._formulaFields;
|
||||
}
|
||||
@ -141,7 +141,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
this._validFields = [];
|
||||
this._validFieldsWithChildren = [];
|
||||
|
||||
const _add = field => {
|
||||
const _add = (field) => {
|
||||
this._validFields.push(field);
|
||||
this._validFieldsWithChildren.push(field);
|
||||
};
|
||||
@ -160,7 +160,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
}
|
||||
});
|
||||
|
||||
const doctypeFields = this.fields.map(field => field.fieldname);
|
||||
const doctypeFields = this.fields.map((field) => field.fieldname);
|
||||
|
||||
// standard fields
|
||||
for (let field of model.commonFields) {
|
||||
@ -176,7 +176,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
_add({
|
||||
fieldtype: 'Check',
|
||||
fieldname: 'submitted',
|
||||
label: frappe.t`Submitted`
|
||||
label: frappe.t`Submitted`,
|
||||
});
|
||||
}
|
||||
|
||||
@ -241,8 +241,8 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
this._keywordFields = this.keywordFields;
|
||||
if (!(this._keywordFields && this._keywordFields.length && this.fields)) {
|
||||
this._keywordFields = this.fields
|
||||
.filter(field => field.fieldtype !== 'Table' && field.required)
|
||||
.map(field => field.fieldname);
|
||||
.filter((field) => field.fieldtype !== 'Table' && field.required)
|
||||
.map((field) => field.fieldname);
|
||||
}
|
||||
if (!(this._keywordFields && this._keywordFields.length)) {
|
||||
this._keywordFields = ['name'];
|
||||
@ -253,7 +253,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
|
||||
getQuickEditFields() {
|
||||
if (this.quickEditFields) {
|
||||
return this.quickEditFields.map(fieldname => this.getField(fieldname));
|
||||
return this.quickEditFields.map((fieldname) => this.getField(fieldname));
|
||||
}
|
||||
return this.getFieldsWith({ required: 1 });
|
||||
}
|
||||
@ -271,10 +271,12 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
// values given as string
|
||||
validValues = options.split('\n');
|
||||
}
|
||||
|
||||
if (typeof options[0] === 'object') {
|
||||
// options as array of {label, value} pairs
|
||||
validValues = options.map(o => o.value);
|
||||
validValues = options.map((o) => o.value);
|
||||
}
|
||||
|
||||
if (!validValues.includes(value)) {
|
||||
throw new frappe.errors.ValueError(
|
||||
// prettier-ignore
|
||||
@ -287,7 +289,7 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
async trigger(event, params = {}) {
|
||||
Object.assign(params, {
|
||||
doc: this,
|
||||
name: event
|
||||
name: event,
|
||||
});
|
||||
|
||||
await super.trigger(event, params);
|
||||
@ -300,8 +302,8 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
key: 'submitted',
|
||||
colors: {
|
||||
0: indicatorColor.GRAY,
|
||||
1: indicatorColor.BLUE
|
||||
}
|
||||
1: indicatorColor.BLUE,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -323,4 +325,4 @@ module.exports = class BaseMeta extends BaseDocument {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
const { getPaddedName } = require('@/utils');
|
||||
const frappe = require('frappe');
|
||||
const { getRandomString } = require('frappe/utils');
|
||||
import frappe from 'frappe';
|
||||
import { getRandomString } from 'frappe/utils';
|
||||
|
||||
module.exports = {
|
||||
async isNameAutoSet(doctype) {
|
||||
export async function isNameAutoSet(doctype) {
|
||||
const doc = frappe.getNewDoc(doctype);
|
||||
if (doc.meta.naming === 'autoincrement') {
|
||||
return true;
|
||||
@ -19,19 +17,19 @@ module.exports = {
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
async setName(doc) {
|
||||
export async function setName(doc) {
|
||||
if (frappe.isServer) {
|
||||
// if is server, always name again if autoincrement or other
|
||||
if (doc.meta.naming === 'autoincrement') {
|
||||
doc.name = await this.getNextId(doc.doctype);
|
||||
doc.name = await getNextId(doc.doctype);
|
||||
return;
|
||||
}
|
||||
|
||||
// Current, per doc number series
|
||||
if (doc.numberSeries) {
|
||||
doc.name = await this.getSeriesNext(doc.numberSeries, doc.doctype);
|
||||
doc.name = await getSeriesNext(doc.numberSeries, doc.doctype);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -42,7 +40,7 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.name = await this.getSeriesNext(numberSeries, doc.doctype);
|
||||
doc.name = await getSeriesNext(numberSeries, doc.doctype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -62,11 +60,11 @@ module.exports = {
|
||||
if (!doc.name) {
|
||||
doc.name = getRandomString();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
async getNextId(doctype) {
|
||||
export async function getNextId(doctype) {
|
||||
// get the last inserted row
|
||||
let lastInserted = await this.getLastInserted(doctype);
|
||||
let lastInserted = await getLastInserted(doctype);
|
||||
let name = 1;
|
||||
if (lastInserted) {
|
||||
let lastNumber = parseInt(lastInserted.name);
|
||||
@ -74,9 +72,9 @@ module.exports = {
|
||||
name = lastNumber + 1;
|
||||
}
|
||||
return (name + '').padStart(9, '0');
|
||||
},
|
||||
}
|
||||
|
||||
async getLastInserted(doctype) {
|
||||
export async function getLastInserted(doctype) {
|
||||
const lastInserted = await frappe.db.getAll({
|
||||
doctype: doctype,
|
||||
fields: ['name'],
|
||||
@ -85,9 +83,9 @@ module.exports = {
|
||||
order: 'desc',
|
||||
});
|
||||
return lastInserted && lastInserted.length ? lastInserted[0] : null;
|
||||
},
|
||||
}
|
||||
|
||||
async getSeriesNext(prefix, doctype) {
|
||||
export async function getSeriesNext(prefix, doctype) {
|
||||
let series;
|
||||
|
||||
try {
|
||||
@ -97,14 +95,14 @@ module.exports = {
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.createNumberSeries(prefix, doctype);
|
||||
await createNumberSeries(prefix, doctype);
|
||||
series = await frappe.getDoc('NumberSeries', prefix);
|
||||
}
|
||||
|
||||
return await series.next(doctype);
|
||||
},
|
||||
}
|
||||
|
||||
async createNumberSeries(prefix, referenceType, start = 1001) {
|
||||
export async function createNumberSeries(prefix, referenceType, start = 1001) {
|
||||
const exists = await frappe.db.exists('NumberSeries', prefix);
|
||||
if (exists) {
|
||||
return;
|
||||
@ -118,5 +116,4 @@ module.exports = {
|
||||
});
|
||||
|
||||
await series.insert();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
const frappe = require('frappe');
|
||||
import frappe from 'frappe';
|
||||
|
||||
module.exports = async function runPatches(patchList) {
|
||||
export default async function runPatches(patchList) {
|
||||
const patchesAlreadyRun = (
|
||||
await frappe.db.knex('PatchRun').select('name')
|
||||
).map(({ name }) => name);
|
||||
@ -12,7 +12,7 @@ module.exports = async function runPatches(patchList) {
|
||||
|
||||
await runPatch(patch);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function runPatch({ patchName, patchFunction }) {
|
||||
try {
|
||||
|
@ -1,4 +1,5 @@
|
||||
const { t } = require('frappe');
|
||||
import { t } from 'frappe';
|
||||
import NumberSeries from './NumberSeriesDocument.js';
|
||||
|
||||
const referenceTypeMap = {
|
||||
SalesInvoice: t`Invoice`,
|
||||
@ -13,9 +14,10 @@ const referenceTypeMap = {
|
||||
'-': t`None`,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
name: 'NumberSeries',
|
||||
documentClass: require('./NumberSeriesDocument.js'),
|
||||
label: t`Number Series`,
|
||||
documentClass: NumberSeries,
|
||||
doctype: 'DocType',
|
||||
isSingle: 0,
|
||||
isChild: 0,
|
||||
|
@ -1,8 +1,8 @@
|
||||
const { getPaddedName } = require('@/utils');
|
||||
const frappe = require('frappe');
|
||||
const BaseDocument = require('frappe/model/document');
|
||||
import { getPaddedName } from '@/utils';
|
||||
import frappe from 'frappe';
|
||||
import BaseDocument from 'frappe/model/document';
|
||||
|
||||
module.exports = class NumberSeries extends BaseDocument {
|
||||
export default class NumberSeries extends BaseDocument {
|
||||
validate() {
|
||||
if (!this.current) {
|
||||
this.current = this.start;
|
||||
@ -34,4 +34,4 @@ module.exports = class NumberSeries extends BaseDocument {
|
||||
getPaddedName(next) {
|
||||
return getPaddedName(this.name, next, this.padZeros);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,25 @@
|
||||
module.exports = {
|
||||
NumberSeries: require('./doctype/NumberSeries/NumberSeries.js'),
|
||||
PrintFormat: require('./doctype/PrintFormat/PrintFormat.js'),
|
||||
Role: require('./doctype/Role/Role.js'),
|
||||
Session: require('./doctype/Session/Session.js'),
|
||||
SingleValue: require('./doctype/SingleValue/SingleValue.js'),
|
||||
SystemSettings: require('./doctype/SystemSettings/SystemSettings.js'),
|
||||
ToDo: require('./doctype/ToDo/ToDo.js'),
|
||||
User: require('./doctype/User/User.js'),
|
||||
UserRole: require('./doctype/UserRole/UserRole.js'),
|
||||
File: require('./doctype/File/File.js'),
|
||||
PatchRun: require('./doctype/PatchRun/PatchRun.js')
|
||||
import File from './doctype/File/File.js';
|
||||
import NumberSeries from './doctype/NumberSeries/NumberSeries.js';
|
||||
import PatchRun from './doctype/PatchRun/PatchRun.js';
|
||||
import PrintFormat from './doctype/PrintFormat/PrintFormat.js';
|
||||
import Role from './doctype/Role/Role.js';
|
||||
import Session from './doctype/Session/Session.js';
|
||||
import SingleValue from './doctype/SingleValue/SingleValue.js';
|
||||
import SystemSettings from './doctype/SystemSettings/SystemSettings.js';
|
||||
import ToDo from './doctype/ToDo/ToDo.js';
|
||||
import User from './doctype/User/User.js';
|
||||
import UserRole from './doctype/UserRole/UserRole.js';
|
||||
|
||||
export default {
|
||||
NumberSeries,
|
||||
PrintFormat,
|
||||
Role,
|
||||
Session,
|
||||
SingleValue,
|
||||
SystemSettings,
|
||||
ToDo,
|
||||
User,
|
||||
UserRole,
|
||||
File,
|
||||
PatchRun,
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
const luxon = require('luxon');
|
||||
const frappe = require('frappe');
|
||||
const { DEFAULT_DISPLAY_PRECISION, DEFAULT_LOCALE } = require('./consts');
|
||||
import frappe from 'frappe';
|
||||
import { DateTime } from 'luxon';
|
||||
import { DEFAULT_DISPLAY_PRECISION, DEFAULT_LOCALE } from './consts';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
format(value, df, doc) {
|
||||
if (!df) {
|
||||
return value;
|
||||
@ -25,10 +25,10 @@ module.exports = {
|
||||
|
||||
if (typeof value === 'string') {
|
||||
// ISO String
|
||||
value = luxon.DateTime.fromISO(value);
|
||||
value = DateTime.fromISO(value);
|
||||
} else if (Object.prototype.toString.call(value) === '[object Date]') {
|
||||
// JS Date
|
||||
value = luxon.DateTime.fromJSDate(value);
|
||||
value = DateTime.fromJSDate(value);
|
||||
}
|
||||
|
||||
value = value.toFormat(dateFormat);
|
||||
|
@ -1,128 +0,0 @@
|
||||
module.exports = class Observable {
|
||||
constructor() {
|
||||
this._observable = {
|
||||
isHot: {},
|
||||
eventQueue: {},
|
||||
listeners: {},
|
||||
onceListeners: {}
|
||||
}
|
||||
}
|
||||
|
||||
// getter, setter stubs, so Observable can be used as a simple Document
|
||||
get(key) {
|
||||
return this[key];
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this[key] = value;
|
||||
this.trigger('change', {
|
||||
doc: this,
|
||||
fieldname: key
|
||||
});
|
||||
}
|
||||
|
||||
on(event, listener) {
|
||||
this._addListener('listeners', event, listener);
|
||||
if (this._observable.socketClient) {
|
||||
this._observable.socketClient.on(event, listener);
|
||||
}
|
||||
}
|
||||
|
||||
// remove listener
|
||||
off(event, listener) {
|
||||
for (let type of ['listeners', 'onceListeners']) {
|
||||
let index = this._observable[type][event] && this._observable[type][event].indexOf(listener);
|
||||
if (index) {
|
||||
this._observable[type][event].splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
once(event, listener) {
|
||||
this._addListener('onceListeners', event, listener);
|
||||
}
|
||||
|
||||
async trigger(event, params, throttle = false) {
|
||||
if (throttle) {
|
||||
if (this._throttled(event, params, throttle)) return;
|
||||
params = [params]
|
||||
}
|
||||
|
||||
await this._executeTriggers(event, params);
|
||||
}
|
||||
|
||||
async _executeTriggers(event, params) {
|
||||
let response = await this._triggerEvent('listeners', event, params);
|
||||
if (response === false) return false;
|
||||
|
||||
response = await this._triggerEvent('onceListeners', event, params);
|
||||
if (response === false) return false;
|
||||
|
||||
// emit via socket
|
||||
if (this._observable.socketServer) {
|
||||
this._observable.socketServer.emit(event, params);
|
||||
}
|
||||
|
||||
// clear once-listeners
|
||||
if (this._observable.onceListeners && this._observable.onceListeners[event]) {
|
||||
delete this._observable.onceListeners[event];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clearListeners() {
|
||||
this._observable.listeners = {};
|
||||
this._observable.onceListeners = {};
|
||||
}
|
||||
|
||||
bindSocketClient(socket) {
|
||||
// also send events with sockets
|
||||
this._observable.socketClient = socket;
|
||||
}
|
||||
|
||||
bindSocketServer(socket) {
|
||||
// also send events with sockets
|
||||
this._observable.socketServer = socket;
|
||||
}
|
||||
|
||||
_throttled(event, params, throttle) {
|
||||
if (this._observable.isHot[event]) {
|
||||
// hot, add to queue
|
||||
if (!this._observable.eventQueue[event]) this._observable.eventQueue[event] = [];
|
||||
this._observable.eventQueue[event].push(params);
|
||||
|
||||
// aleady hot, quit
|
||||
return true;
|
||||
}
|
||||
this._observable.isHot[event] = true;
|
||||
|
||||
// cool-off
|
||||
setTimeout(() => {
|
||||
this._observable.isHot[event] = false;
|
||||
|
||||
// flush queue
|
||||
if (this._observable.eventQueue[event]) {
|
||||
let _queuedParams = this._observable.eventQueue[event];
|
||||
this._observable.eventQueue[event] = null;
|
||||
this._executeTriggers(event, _queuedParams);
|
||||
}
|
||||
}, throttle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_addListener(type, event, listener) {
|
||||
if (!this._observable[type][event]) {
|
||||
this._observable[type][event] = [];
|
||||
}
|
||||
this._observable[type][event].push(listener);
|
||||
}
|
||||
|
||||
async _triggerEvent(type, event, params) {
|
||||
if (this._observable[type][event]) {
|
||||
for (let listener of this._observable[type][event]) {
|
||||
await listener(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
170
frappe/utils/observable.ts
Normal file
170
frappe/utils/observable.ts
Normal file
@ -0,0 +1,170 @@
|
||||
enum EventType {
|
||||
Listeners = '_listeners',
|
||||
OnceListeners = '_onceListeners',
|
||||
}
|
||||
|
||||
export default class Observable {
|
||||
[key: string]: unknown;
|
||||
_isHot: Map<string, boolean>;
|
||||
_eventQueue: Map<string, unknown[]>;
|
||||
_map: Map<string, unknown>;
|
||||
_listeners: Map<string, Function[]>;
|
||||
_onceListeners: Map<string, Function[]>;
|
||||
|
||||
constructor() {
|
||||
this._map = new Map();
|
||||
this._isHot = new Map();
|
||||
this._eventQueue = new Map();
|
||||
this._listeners = new Map();
|
||||
this._onceListeners = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter to use Observable as a regular document.
|
||||
*
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
get(key: string): unknown {
|
||||
return this[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter to use Observable as a regular document.
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
set(key: string, value: unknown) {
|
||||
this[key] = value;
|
||||
this.trigger('change', {
|
||||
doc: this,
|
||||
fieldname: key,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a `listener` that executes every time `event` is triggered
|
||||
*
|
||||
* @param event : name of the event for which the listener is set
|
||||
* @param listener : listener that is executed when the event is triggered
|
||||
*/
|
||||
on(event: string, listener: Function) {
|
||||
this._addListener(EventType.Listeners, event, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a `listener` that execture `once`: executes once when `event` is
|
||||
* triggered then deletes itself
|
||||
*
|
||||
* @param event : name of the event for which the listener is set
|
||||
* @param listener : listener that is executed when the event is triggered
|
||||
*/
|
||||
once(event: string, listener: Function) {
|
||||
this._addListener(EventType.OnceListeners, event, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener from an event for both 'on' and 'once'
|
||||
*
|
||||
* @param event : name of the event from which to remove the listener
|
||||
* @param listener : listener that was set for the event
|
||||
*/
|
||||
off(event: string, listener: Function) {
|
||||
this._removeListener(EventType.Listeners, event, listener);
|
||||
this._removeListener(EventType.OnceListeners, event, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all the listeners.
|
||||
*/
|
||||
clear() {
|
||||
this._listeners.clear();
|
||||
this._onceListeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the event's listener function.
|
||||
*
|
||||
* @param event : name of the event to be triggered.
|
||||
* @param params : params to pass to the listeners.
|
||||
* @param throttle : wait time before triggering the event.
|
||||
*/
|
||||
|
||||
async trigger(event: string, params: unknown, throttle: number = 0) {
|
||||
let isHot = false;
|
||||
if (throttle > 0) {
|
||||
isHot = this._throttled(event, params, throttle);
|
||||
params = [params];
|
||||
}
|
||||
|
||||
if (isHot) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._executeTriggers(event, params);
|
||||
}
|
||||
|
||||
_removeListener(type: EventType, event: string, listener: Function) {
|
||||
const listeners = (this[type].get(event) ?? []).filter(
|
||||
(l) => l !== listener
|
||||
);
|
||||
this[type].set(event, listeners);
|
||||
}
|
||||
|
||||
async _executeTriggers(event: string, params?: unknown) {
|
||||
await this._triggerEvent(EventType.Listeners, event, params);
|
||||
await this._triggerEvent(EventType.OnceListeners, event, params);
|
||||
this._onceListeners.delete(event);
|
||||
}
|
||||
|
||||
_throttled(event: string, params: unknown, throttle: number) {
|
||||
/**
|
||||
* Throttled events execute after `throttle` ms, during this period
|
||||
* isHot is true, i.e it's going to execute.
|
||||
*/
|
||||
|
||||
if (!this._eventQueue.has(event)) {
|
||||
this._eventQueue.set(event, []);
|
||||
}
|
||||
|
||||
if (this._isHot.get(event)) {
|
||||
this._eventQueue.get(event)!.push(params);
|
||||
return true;
|
||||
}
|
||||
|
||||
this._isHot.set(event, true);
|
||||
|
||||
setTimeout(() => {
|
||||
this._isHot.set(event, false);
|
||||
|
||||
const params = this._eventQueue.get(event);
|
||||
if (params !== undefined) {
|
||||
this._executeTriggers(event, params);
|
||||
this._eventQueue.delete(event);
|
||||
}
|
||||
}, throttle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_addListener(type: EventType, event: string, listener: Function) {
|
||||
this._initLiseners(type, event);
|
||||
this[type].get(event)!.push(listener);
|
||||
}
|
||||
|
||||
_initLiseners(type: EventType, event: string) {
|
||||
if (this[type].has(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this[type].set(event, []);
|
||||
}
|
||||
|
||||
async _triggerEvent(type: EventType, event: string, params?: unknown) {
|
||||
const listeners = this[type].get(event) ?? [];
|
||||
for (const listener of listeners) {
|
||||
await listener(params);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import frappe from 'frappe';
|
||||
import naming from 'frappe/model/naming';
|
||||
import { createNumberSeries } from 'frappe/model/naming';
|
||||
import GSTR3BServer from '../models/doctype/GSTR3B/GSTR3BServer.js';
|
||||
import JournalEntryServer from '../models/doctype/JournalEntry/JournalEntryServer.js';
|
||||
import PartyServer from '../models/doctype/Party/PartyServer.js';
|
||||
@ -20,10 +20,10 @@ export default async function postStart() {
|
||||
frappe.metaCache = {};
|
||||
|
||||
// init naming series if missing
|
||||
await naming.createNumberSeries('SINV-', 'SalesInvoice');
|
||||
await naming.createNumberSeries('PINV-', 'PurchaseInvoice');
|
||||
await naming.createNumberSeries('PAY-', 'Payment');
|
||||
await naming.createNumberSeries('JV-', 'JournalEntry');
|
||||
await createNumberSeries('SINV-', 'SalesInvoice');
|
||||
await createNumberSeries('PINV-', 'PurchaseInvoice');
|
||||
await createNumberSeries('PAY-', 'Payment');
|
||||
await createNumberSeries('JV-', 'JournalEntry');
|
||||
// await naming.createNumberSeries('QTN-', 'QuotationSettings');
|
||||
// await naming.createNumberSeries('SO-', 'SalesOrderSettings');
|
||||
// await naming.createNumberSeries('OF-', 'FulfillmentSettings');
|
||||
|
@ -35,7 +35,7 @@ import config from '@/config';
|
||||
import {
|
||||
connectToLocalDatabase,
|
||||
postSetup,
|
||||
purgeCache
|
||||
purgeCache,
|
||||
} from '@/initialization';
|
||||
import { IPC_ACTIONS, IPC_MESSAGES } from '@/messages';
|
||||
import { ipcRenderer } from 'electron';
|
||||
@ -131,10 +131,10 @@ export default {
|
||||
routeTo('/get-started');
|
||||
}
|
||||
},
|
||||
changeDbFile() {
|
||||
async changeDbFile() {
|
||||
config.set('lastSelectedFilePath', null);
|
||||
telemetry.stop();
|
||||
purgeCache(true);
|
||||
await purgeCache(true);
|
||||
this.activeScreen = 'DatabaseSelector';
|
||||
},
|
||||
async setupCanceled() {
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
MandatoryError,
|
||||
ValidationError,
|
||||
} from 'frappe/common/errors';
|
||||
import BaseDocument from 'frappe/model/document';
|
||||
import Document from 'frappe/model/document';
|
||||
import config, { ConfigKeys, TelemetrySetting } from './config';
|
||||
import { IPC_ACTIONS, IPC_MESSAGES } from './messages';
|
||||
import telemetry from './telemetry/telemetry';
|
||||
@ -110,7 +110,7 @@ export function handleError(
|
||||
}
|
||||
}
|
||||
|
||||
export function getErrorMessage(e: Error, doc?: BaseDocument): string {
|
||||
export function getErrorMessage(e: Error, doc?: Document): string {
|
||||
let errorMessage = e.message || t`An error occurred.`;
|
||||
|
||||
const { doctype, name }: { doctype?: unknown; name?: unknown } = doc ?? {};
|
||||
@ -125,7 +125,7 @@ export function getErrorMessage(e: Error, doc?: BaseDocument): string {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
export function handleErrorWithDialog(error: Error, doc?: BaseDocument) {
|
||||
export function handleErrorWithDialog(error: Error, doc?: Document) {
|
||||
const errorMessage = getErrorMessage(error, doc);
|
||||
handleError(false, error, { errorMessage, doc });
|
||||
|
||||
|
@ -106,7 +106,7 @@ export async function connectToLocalDatabase(filePath) {
|
||||
return { connectionSuccess: true, reason: '' };
|
||||
}
|
||||
|
||||
export function purgeCache(purgeAll = false) {
|
||||
export async function purgeCache(purgeAll = false) {
|
||||
const filterFunction = purgeAll
|
||||
? () => true
|
||||
: (d) => frappe.docs[d][d] instanceof frappe.BaseMeta;
|
||||
@ -120,7 +120,7 @@ export function purgeCache(purgeAll = false) {
|
||||
|
||||
if (purgeAll) {
|
||||
delete frappe.db;
|
||||
frappe.initializeAndRegister(models, true);
|
||||
await frappe.initializeAndRegister(models, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ import { setLanguageMap, stringifyCircular } from './utils';
|
||||
frappe.isServer = true;
|
||||
frappe.isElectron = true;
|
||||
|
||||
frappe.initializeAndRegister(models);
|
||||
await frappe.initializeAndRegister(models);
|
||||
|
||||
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
||||
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
||||
|
@ -89,25 +89,23 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import frappe from 'frappe';
|
||||
import TwoColumnForm from '@/components/TwoColumnForm';
|
||||
import FormControl from '@/components/Controls/FormControl';
|
||||
import setupCompany from './setupCompany';
|
||||
import Popover from '@/components/Popover';
|
||||
import config from '@/config';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { purgeCache, connectToLocalDatabase } from '@/initialization';
|
||||
import { setLanguageMap, showMessageDialog } from '@/utils';
|
||||
import {
|
||||
handleErrorWithDialog,
|
||||
getErrorMessage,
|
||||
showErrorDialog,
|
||||
} from '../../errorHandling';
|
||||
import Slide from './Slide.vue';
|
||||
import LanguageSelector from '@/components/Controls/LanguageSelector.vue';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import Popover from '@/components/Popover';
|
||||
import TwoColumnForm from '@/components/TwoColumnForm';
|
||||
import config from '@/config';
|
||||
import { connectToLocalDatabase, purgeCache } from '@/initialization';
|
||||
import { IPC_MESSAGES } from '@/messages';
|
||||
import { setLanguageMap, showMessageDialog } from '@/utils';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import frappe from 'frappe';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import {
|
||||
getErrorMessage, handleErrorWithDialog, showErrorDialog
|
||||
} from '../../errorHandling';
|
||||
import setupCompany from './setupCompany';
|
||||
import Slide from './Slide.vue';
|
||||
|
||||
export default {
|
||||
name: 'SetupWizard',
|
||||
@ -209,7 +207,7 @@ export default {
|
||||
const filePath = config.get('lastSelectedFilePath');
|
||||
renameDbFile(filePath);
|
||||
|
||||
purgeCache();
|
||||
await purgeCache();
|
||||
|
||||
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
||||
filePath
|
||||
|
Loading…
Reference in New Issue
Block a user