forest-express-sequelize
Version:
Official Express/Sequelize Liana for Forest
102 lines (96 loc) • 4.59 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
require("core-js/modules/es.promise.js");
var _bluebird = _interopRequireDefault(require("bluebird"));
var _forestExpress = require("forest-express");
var _lodash = _interopRequireDefault(require("lodash"));
var _operators = _interopRequireDefault(require("../utils/operators"));
var _orm = _interopRequireDefault(require("../utils/orm"));
var _filtersParser = _interopRequireDefault(require("./filters-parser"));
var _queryOptions = _interopRequireDefault(require("./query-options"));
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
class ValueStatGetter {
constructor(model, params, options, user) {
this._model = model;
this._params = params;
this._options = options;
this._user = user;
this._OPERATORS = _operators.default.getInstance(options);
this._schema = _forestExpress.Schemas.schemas[model.name];
this._operatorDateParser = new _forestExpress.BaseOperatorDateParser({
operators: this._OPERATORS,
timezone: params.timezone
});
}
/** Function used to aggregate results (count, sum, ...) */
get _aggregateFunction() {
return this._params.aggregator.toLowerCase();
}
/** Column name we're aggregating on */
get _aggregateField() {
// NOTICE: As MySQL cannot support COUNT(table_name.*) syntax, fieldName cannot be '*'.
const fieldName = this._params.aggregateFieldName || this._schema.primaryKeys[0] || this._schema.fields[0].field;
return `${this._schema.name}.${_orm.default.getColumnName(this._schema, fieldName)}`;
}
async perform() {
const {
filter,
timezone
} = this._params;
const scopeFilters = await _forestExpress.scopeManager.getScopeForUser(this._user, this._model.name, true);
const queryOptions = new _queryOptions.default(this._model, {
includeRelations: true
});
await queryOptions.filterByConditionTree(filter, timezone);
await queryOptions.filterByConditionTree(scopeFilters, timezone);
// No attributes should be retrieved from relations for the group by to work.
const options = queryOptions.sequelizeOptions;
options.include = options.include ? options.include.map(function (includeProperties) {
return _objectSpread(_objectSpread({}, includeProperties), {}, {
attributes: []
});
}) : undefined;
return {
value: await _bluebird.default.props({
countCurrent: this._getCount(options),
countPrevious: this._getCountPrevious(options)
})
};
}
async _getCount(options) {
const count = await this._model.unscoped().aggregate(this._aggregateField, this._aggregateFunction, options);
// sequelize@4 returns NaN, while sequelize@5+ returns null
return count || 0;
}
/**
* Fetch the value for the previous period.
*
* FIXME Will not work on edges cases
* - when the 'rawPreviousInterval.field' appears twice
* - when scopes use the same field as the filter
*/
async _getCountPrevious(options) {
const {
filter,
timezone
} = this._params;
if (!filter) {
return undefined;
}
const conditionsParser = new _filtersParser.default(this._schema, timezone, this._options);
const rawInterval = conditionsParser.getPreviousIntervalCondition(filter);
if (!rawInterval) {
return undefined;
}
const interval = this._operatorDateParser.getPreviousDateFilter(rawInterval.operator, rawInterval.value);
const newOptions = _lodash.default.cloneDeepWith(options, function (object) {
return object && object[rawInterval.field] ? _objectSpread(_objectSpread({}, object), {}, {
[rawInterval.field]: interval
}) : undefined;
});
return this._getCount(newOptions);
}
}
module.exports = ValueStatGetter;