2
0
mirror of https://github.com/frappe/books.git synced 2024-11-10 07:40:55 +00:00

feat: init pesa and set on the frappe object

This commit is contained in:
18alantom 2021-11-30 14:50:54 +05:30
parent b746200050
commit 7698af67e6
4 changed files with 123 additions and 28 deletions

View File

@ -13,9 +13,10 @@ module.exports = class Database extends Observable {
connect() { connect() {
this.knex = Knex(this.connectionParams); this.knex = Knex(this.connectionParams);
this.knex.on('query-error', error => { this.knex.on('query-error', (error) => {
error.type = this.getError(error); error.type = this.getError(error);
}); });
this.executePostDbConnect();
} }
close() { close() {
@ -41,15 +42,25 @@ module.exports = class Database extends Observable {
async initializeSingles() { async initializeSingles() {
let singleDoctypes = frappe let singleDoctypes = frappe
.getModels(model => model.isSingle) .getModels((model) => model.isSingle)
.map(model => model.name); .map((model) => model.name);
for (let doctype of singleDoctypes) { for (let doctype of singleDoctypes) {
if (await this.singleExists(doctype)) { if (await this.singleExists(doctype)) {
const singleValues = await this.getSingleFieldsToInsert(doctype);
singleValues.forEach(({ fieldname, value }) => {
let singleValue = frappe.newDoc({
doctype: 'SingleValue',
parent: doctype,
fieldname,
value,
});
singleValue.insert();
});
continue; continue;
} }
let meta = frappe.getMeta(doctype); let meta = frappe.getMeta(doctype);
if (meta.fields.every(df => df.default == null)) { if (meta.fields.every((df) => df.default == null)) {
continue; continue;
} }
let defaultValues = meta.fields.reduce((doc, df) => { let defaultValues = meta.fields.reduce((doc, df) => {
@ -70,6 +81,26 @@ module.exports = class Database extends Observable {
return res.count > 0; return res.count > 0;
} }
async getSingleFieldsToInsert(doctype) {
const existingFields = (
await frappe.db
.knex('SingleValue')
.where({ parent: doctype })
.select('fieldname')
).map(({ fieldname }) => fieldname);
return frappe
.getMeta(doctype)
.fields.map(({ fieldname, default: value }) => ({
fieldname,
value,
}))
.filter(
({ fieldname, value }) =>
!existingFields.includes(fieldname) && value !== undefined
);
}
tableExists(table) { tableExists(table) {
return this.knex.schema.hasTable(table); return this.knex.schema.hasTable(table);
} }
@ -80,7 +111,7 @@ module.exports = class Database extends Observable {
} }
runCreateTableQuery(doctype, fields) { runCreateTableQuery(doctype, fields) {
return this.knex.schema.createTable(doctype, table => { return this.knex.schema.createTable(doctype, (table) => {
for (let field of fields) { for (let field of fields) {
this.buildColumnForTable(table, field); this.buildColumnForTable(table, field);
} }
@ -93,7 +124,7 @@ module.exports = class Database extends Observable {
let newForeignKeys = await this.getNewForeignKeys(doctype); let newForeignKeys = await this.getNewForeignKeys(doctype);
return this.knex.schema return this.knex.schema
.table(doctype, table => { .table(doctype, (table) => {
if (diff.added.length) { if (diff.added.length) {
for (let field of diff.added) { for (let field of diff.added) {
this.buildColumnForTable(table, field); this.buildColumnForTable(table, field);
@ -162,7 +193,7 @@ module.exports = class Database extends Observable {
} }
} }
const validFieldNames = validFields.map(field => field.fieldname); const validFieldNames = validFields.map((field) => field.fieldname);
for (let column of tableColumns) { for (let column of tableColumns) {
if (!validFieldNames.includes(column)) { if (!validFieldNames.includes(column)) {
diff.removed.push(column); diff.removed.push(column);
@ -235,7 +266,7 @@ module.exports = class Database extends Observable {
fields: ['*'], fields: ['*'],
filters: { parent: doc.name }, filters: { parent: doc.name },
orderBy: 'idx', orderBy: 'idx',
order: 'asc' order: 'asc',
}); });
} }
} }
@ -246,7 +277,7 @@ module.exports = class Database extends Observable {
fields: ['fieldname', 'value'], fields: ['fieldname', 'value'],
filters: { parent: doctype }, filters: { parent: doctype },
orderBy: 'fieldname', orderBy: 'fieldname',
order: 'asc' order: 'asc',
}); });
let doc = {}; let doc = {};
for (let row of values) { for (let row of values) {
@ -255,6 +286,38 @@ module.exports = class Database extends Observable {
return doc; return doc;
} }
/**
* Get list of values from the singles table.
* @param {...string | Object} fieldnames list of fieldnames to get the values of
* @returns {Array<Object>} array of {parent, value, fieldname}.
* @example
* Database.getSingleValues('internalPrecision');
* // returns [{ fieldname: 'internalPrecision', parent: 'SystemSettings', value: '12' }]
* @example
* Database.getSingleValues({fieldname:'internalPrecision', parent: 'SystemSettings'});
* // returns [{ fieldname: 'internalPrecision', parent: 'SystemSettings', value: '12' }]
*/
async getSingleValues(...fieldnames) {
fieldnames = fieldnames.map((fieldname) => {
if (typeof fieldname === 'string') {
return { fieldname };
}
return fieldname;
});
let builder = frappe.db.knex('SingleValue');
builder = builder.where(fieldnames[0]);
fieldnames.slice(1).forEach(({ fieldname, parent }) => {
if (typeof parent === 'undefined') {
builder = builder.orWhere({ fieldname });
} else {
builder = builder.orWhere({ fieldname, parent });
}
});
return await builder.select('fieldname', 'value', 'parent');
}
getOne(doctype, name, fields = '*') { getOne(doctype, name, fields = '*') {
let meta = frappe.getMeta(doctype); let meta = frappe.getMeta(doctype);
let baseDoctype = meta.getBaseDocType(); let baseDoctype = meta.getBaseDocType();
@ -358,8 +421,8 @@ module.exports = class Database extends Observable {
updateOne(doctype, doc) { updateOne(doctype, doc) {
let validFields = this.getValidFields(doctype); let validFields = this.getValidFields(doctype);
let fieldsToUpdate = Object.keys(doc).filter(f => f !== 'name'); let fieldsToUpdate = Object.keys(doc).filter((f) => f !== 'name');
let fields = validFields.filter(df => let fields = validFields.filter((df) =>
fieldsToUpdate.includes(df.fieldname) fieldsToUpdate.includes(df.fieldname)
); );
let formattedDoc = this.getFormattedDoc(fields, doc); let formattedDoc = this.getFormattedDoc(fields, doc);
@ -396,7 +459,7 @@ module.exports = class Database extends Observable {
doctype: 'SingleValue', doctype: 'SingleValue',
parent: doctype, parent: doctype,
fieldname: field.fieldname, fieldname: field.fieldname,
value: value value: value,
}); });
await singleValue.insert(); await singleValue.insert();
} }
@ -404,9 +467,7 @@ module.exports = class Database extends Observable {
} }
deleteSingleValues(name) { deleteSingleValues(name) {
return this.knex('SingleValue') return this.knex('SingleValue').where('parent', name).delete();
.where('parent', name)
.delete();
} }
async rename(doctype, oldName, newName) { async rename(doctype, oldName, newName) {
@ -439,7 +500,7 @@ module.exports = class Database extends Observable {
getFormattedDoc(fields, doc) { getFormattedDoc(fields, doc) {
let formattedDoc = {}; let formattedDoc = {};
fields.map(field => { fields.map((field) => {
let value = doc[field.fieldname]; let value = doc[field.fieldname];
formattedDoc[field.fieldname] = this.getFormattedValue(field, value); formattedDoc[field.fieldname] = this.getFormattedValue(field, value);
}); });
@ -507,9 +568,7 @@ module.exports = class Database extends Observable {
} }
deleteChildren(parenttype, parent) { deleteChildren(parenttype, parent) {
return this.knex(parenttype) return this.knex(parenttype).where('parent', parent).delete();
.where('parent', parent)
.delete();
} }
async exists(doctype, name) { async exists(doctype, name) {
@ -533,14 +592,14 @@ module.exports = class Database extends Observable {
start: 0, start: 0,
limit: 1, limit: 1,
orderBy: 'name', orderBy: 'name',
order: 'asc' order: 'asc',
}); });
return row.length ? row[0][fieldname] : null; return row.length ? row[0][fieldname] : null;
} }
async setValue(doctype, name, fieldname, value) { async setValue(doctype, name, fieldname, value) {
return await this.setValues(doctype, name, { return await this.setValues(doctype, name, {
[fieldname]: value [fieldname]: value,
}); });
} }
@ -565,7 +624,7 @@ module.exports = class Database extends Observable {
limit, limit,
groupBy, groupBy,
orderBy = 'creation', orderBy = 'creation',
order = 'desc' order = 'desc',
} = {}) { } = {}) {
let meta = frappe.getMeta(doctype); let meta = frappe.getMeta(doctype);
let baseDoctype = meta.getBaseDocType(); let baseDoctype = meta.getBaseDocType();
@ -643,7 +702,7 @@ module.exports = class Database extends Observable {
} }
} }
filtersArray.map(filter => { filtersArray.map((filter) => {
const [field, operator, comparisonValue] = filter; const [field, operator, comparisonValue] = filter;
if (operator === '=') { if (operator === '=') {
builder.where(field, comparisonValue); builder.where(field, comparisonValue);
@ -689,4 +748,8 @@ module.exports = class Database extends Observable {
initTypeMap() { initTypeMap() {
this.typeMap = {}; this.typeMap = {};
} }
executePostDbConnect() {
frappe.initializeMoneyMaker();
}
}; };

View File

@ -1,5 +1,6 @@
const Observable = require('./utils/observable'); const Observable = require('./utils/observable');
const utils = require('./utils'); const utils = require('./utils');
const { getMoneyMaker } = require('pesa');
module.exports = { module.exports = {
initializeAndRegister(customModels = {}, force = false) { initializeAndRegister(customModels = {}, force = false) {
@ -11,6 +12,37 @@ module.exports = {
this.registerModels(customModels); this.registerModels(customModels);
}, },
async initializeMoneyMaker() {
// to be called after db initialization
const { currency, internalPrecision: precision } = (
await frappe.db.getSingleValues(
{ fieldname: 'currency', parent: 'AccountingSettings' },
{ fieldname: 'internalPrecision', parent: 'SystemSettings' }
)
).reduce((acc, { fieldname, value }) => {
acc[fieldname] = value;
return acc;
}, {});
if (typeof precision === 'undefined') {
precision = this.getMeta('SystemSettings').fields.find(
(f) => f.fieldname === 'internalPrecision'
)?.default;
}
if (typeof precision === 'undefined') {
throw new frappe.errors.NotFoundError(
'SystemSettings internalPrecision value is undefined'
);
}
if (typeof precision.value === 'string') {
precision = parseInt(precision);
}
this.pesa = getMoneyMaker({ currency, precision });
},
init(force) { init(force) {
if (this._initialized && !force) return; if (this._initialized && !force) return;
this.initConfig(); this.initConfig();

View File

@ -32,7 +32,7 @@
"multer": "^1.4.3", "multer": "^1.4.3",
"node-fetch": "^3.0.0", "node-fetch": "^3.0.0",
"nunjucks": "^3.2.3", "nunjucks": "^3.2.3",
"pesa": "latest", "pesa": "^1.0.3",
"postcss": "^8.3.11", "postcss": "^8.3.11",
"postcss-loader": "^6.2.0", "postcss-loader": "^6.2.0",
"sass-loader": "^12.3.0", "sass-loader": "^12.3.0",

View File

@ -3417,10 +3417,10 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
pesa@latest: pesa@^1.0.3:
version "1.0.2" version "1.0.3"
resolved "https://registry.yarnpkg.com/pesa/-/pesa-1.0.2.tgz#78410dbbebb92382cb5c4285aa0a781de2dfc769" resolved "https://registry.yarnpkg.com/pesa/-/pesa-1.0.3.tgz#e0eab7a13a6a8d0cfd1cbc0214aece6befd63a74"
integrity sha512-ITR9V8bRe1GDbBQq8/SyMBtzXJlDs8ludO2ZBMtCZen6D7oqlJXVBeZQSJQs4FfoHBLKJtdsk/JvsleE5Qqu4g== integrity sha512-UGw3TPnQKAcM0EhPzQO17cXtibBcJCCqlB/hjfYtVPFAgDOIJ2kv6az9Fwq5Gflp2R7hODZlJy1cG+eL70od/g==
pg-connection-string@2.5.0: pg-connection-string@2.5.0:
version "2.5.0" version "2.5.0"