UNPKG

forest-express-sequelize

Version:

Official Express/Sequelize Liana for Forest

102 lines (96 loc) 4.59 kB
"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;