mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
feat: sales and purchases status. feat: sales and purchases auto-increment number. fix: settings find query with extra columns.
226 lines
5.3 KiB
TypeScript
226 lines
5.3 KiB
TypeScript
import { Model } from 'objection';
|
|
import {
|
|
IMetadata,
|
|
IMetableStoreStorage,
|
|
} from 'interfaces';
|
|
import MetableStore from './MetableStore';
|
|
import { isBlank } from 'utils';
|
|
|
|
export default class MetableDBStore extends MetableStore implements IMetableStoreStorage{
|
|
repository: any;
|
|
KEY_COLUMN: string;
|
|
VALUE_COLUMN: string;
|
|
TYPE_COLUMN: string;
|
|
extraQuery: Function;
|
|
loaded: Boolean;
|
|
|
|
/**
|
|
* Constructor method.
|
|
*/
|
|
constructor() {
|
|
super();
|
|
|
|
this.loaded = false;
|
|
this.KEY_COLUMN = 'key';
|
|
this.VALUE_COLUMN = 'value';
|
|
this.TYPE_COLUMN = 'type';
|
|
this.repository = null;
|
|
|
|
this.extraQuery = (meta) => {
|
|
return {
|
|
key: meta[this.KEY_COLUMN],
|
|
...this.transfromMetaExtraColumns(meta),
|
|
};
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Transformes meta query.
|
|
* @param {IMetadata} meta
|
|
*/
|
|
private transfromMetaExtraColumns(meta: IMetadata) {
|
|
return this.extraColumns.reduce((obj, column) => {
|
|
const metaValue = meta[column];
|
|
|
|
if (!isBlank(metaValue)) {
|
|
obj[column] = metaValue;
|
|
}
|
|
return obj;
|
|
}, {});
|
|
}
|
|
|
|
/**
|
|
* Set repository entity of this metadata collection.
|
|
* @param {Object} repository -
|
|
*/
|
|
setRepository(repository) {
|
|
this.repository = repository;
|
|
}
|
|
|
|
/**
|
|
* Sets a extra query callback.
|
|
* @param callback
|
|
*/
|
|
setExtraQuery(callback) {
|
|
this.extraQuery = callback;
|
|
}
|
|
|
|
/**
|
|
* Saves the modified, deleted and insert metadata.
|
|
*/
|
|
save() {
|
|
this.validateStoreIsLoaded();
|
|
|
|
return Promise.all([
|
|
this.saveUpdated(this.metadata),
|
|
this.saveDeleted(this.metadata),
|
|
this.saveInserted(this.metadata),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Saves the updated metadata.
|
|
* @param {IMetadata[]} metadata -
|
|
* @returns {Promise}
|
|
*/
|
|
saveUpdated(metadata: IMetadata[]) {
|
|
const updated = metadata.filter((m) => (m._markAsUpdated === true));
|
|
const opers = [];
|
|
|
|
updated.forEach((meta) => {
|
|
const updateOper = this.repository.update({
|
|
[this.VALUE_COLUMN]: meta.value,
|
|
}, {
|
|
...this.extraQuery(meta),
|
|
}).then(() => {
|
|
meta._markAsUpdated = false;
|
|
});
|
|
opers.push(updateOper);
|
|
});
|
|
return Promise.all(opers);
|
|
}
|
|
|
|
/**
|
|
* Saves the deleted metadata.
|
|
* @param {IMetadata[]} metadata -
|
|
* @returns {Promise}
|
|
*/
|
|
saveDeleted(metadata: IMetadata[]) {
|
|
const deleted = metadata.filter((m: IMetadata) => (m._markAsDeleted === true));
|
|
const opers: Promise<void> = [];
|
|
|
|
if (deleted.length > 0) {
|
|
deleted.forEach((meta) => {
|
|
const deleteOper = this.repository.deleteBy({
|
|
...this.extraQuery(meta),
|
|
}).then(() => {
|
|
meta._markAsDeleted = false;
|
|
});
|
|
opers.push(deleteOper);
|
|
});
|
|
}
|
|
return Promise.all(opers);
|
|
}
|
|
|
|
/**
|
|
* Saves the inserted metadata.
|
|
* @param {IMetadata[]} metadata -
|
|
* @returns {Promise}
|
|
*/
|
|
saveInserted(metadata: IMetadata[]) {
|
|
const inserted = metadata.filter((m: IMetadata) => (m._markAsInserted === true));
|
|
const opers: Promise<void> = [];
|
|
|
|
inserted.forEach((meta) => {
|
|
const insertData = {
|
|
[this.KEY_COLUMN]: meta.key,
|
|
[this.VALUE_COLUMN]: meta.value,
|
|
...this.transfromMetaExtraColumns(meta),
|
|
};
|
|
const insertOper = this.repository.create(insertData)
|
|
.then(() => {
|
|
meta._markAsInserted = false;
|
|
});
|
|
opers.push(insertOper);
|
|
});
|
|
return Promise.all(opers);
|
|
}
|
|
|
|
/**
|
|
* Loads the metadata from the storage.
|
|
* @param {String|Array} key -
|
|
* @param {Boolean} force -
|
|
*/
|
|
async load() {
|
|
const metadata = await this.repository.all();
|
|
const mappedMetadata = this.mapMetadataCollection(metadata);
|
|
|
|
mappedMetadata.forEach((meta: IMetadata) => {
|
|
this.metadata.push(meta);
|
|
});
|
|
this.loaded = true;
|
|
}
|
|
|
|
/**
|
|
* Format the metadata before saving to the database.
|
|
* @param {String|Number|Boolean} value -
|
|
* @param {String} valueType -
|
|
* @return {String|Number|Boolean} -
|
|
*/
|
|
static formatMetaValue(value: string|number|boolean, valueType: string|false) {
|
|
let parsedValue: string|number|boolean;
|
|
|
|
switch (valueType) {
|
|
case 'number':
|
|
parsedValue = `${value}`;
|
|
break;
|
|
case 'boolean':
|
|
parsedValue = value ? '1' : '0';
|
|
break;
|
|
case 'json':
|
|
parsedValue = JSON.stringify(parsedValue);
|
|
break;
|
|
default:
|
|
parsedValue = value;
|
|
break;
|
|
}
|
|
return parsedValue;
|
|
}
|
|
|
|
/**
|
|
* Mapping and parse metadata to collection entries.
|
|
* @param {Meta} attr -
|
|
* @param {String} parseType -
|
|
*/
|
|
mapMetadata(metadata: IMetadata) {
|
|
return {
|
|
key: metadata[this.KEY_COLUMN],
|
|
value: MetableDBStore.formatMetaValue(
|
|
metadata[this.VALUE_COLUMN],
|
|
this.TYPE_COLUMN ? metadata[this.TYPE_COLUMN] : false,
|
|
),
|
|
...this.extraColumns.reduce((obj, extraCol: string) => {
|
|
obj[extraCol] = metadata[extraCol] || null;
|
|
return obj;
|
|
}, {}),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Parse the metadata to the collection.
|
|
* @param {Array} collection -
|
|
*/
|
|
mapMetadataCollection(metadata: IMetadata[]) {
|
|
return metadata.map((model) => this.mapMetadata(model));
|
|
}
|
|
|
|
/**
|
|
* Throw error in case the store is not loaded yet.
|
|
*/
|
|
private validateStoreIsLoaded() {
|
|
if (!this.loaded) {
|
|
throw new Error('You could not save the store before loaded from the storage.');
|
|
}
|
|
}
|
|
}
|