/* eslint-disable camelcase */ import httpStatus from 'http-status'; import { Model, DataTypes, Op } from 'sequelize'; import { isEqual, isNil, isUndefined, omitBy, pick } from 'lodash'; import moment from 'moment-timezone'; import { serviceName } from '../../config/vars'; import postgres from '../../config/postgres'; import APIError from '../utils/APIException'; /** * Create connection */ const { sequelize } = postgres; class Image extends Model { } const PUBLIC_FIELDS = [ 'name', 'title', 'payload' ]; Image.Groups = { USER: 'users', STORE: 'stores', VOUCHER: 'vouchers', STORIES: 'stories', CHAPTERS: 'chapters', GAMES: 'games', CUSTOMER: 'customers', PROMOTION: 'promotions', PRODUCT: 'products', // configration BANNER: 'banners', CATEGORY: 'categories', DEFAULT: 'defaults' }; /** * Image Schema * @public */ Image.init( { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }, url: { type: DataTypes.STRING(255), allowNull: false }, name: { type: DataTypes.STRING(255), defaultValue: null }, title: { type: DataTypes.STRING(255), defaultValue: null }, payload: { type: DataTypes.JSONB, defaultValue: null // id | code | name }, // manager is_active: { type: DataTypes.BOOLEAN, defaultValue: true }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW }, updated_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW }, created_by: { type: DataTypes.JSONB, defaultValue: null // id | name } }, { timestamps: false, sequelize: sequelize, schema: serviceName, modelName: 'image', tableName: 'tbl_images' } ); /** * Register event emiter */ Image.Events = { IMAGE_CREATED: `${serviceName}.image.created`, IMAGE_UPDATED: `${serviceName}.image.updated`, IMAGE_DELETED: `${serviceName}.image.deleted`, }; Image.EVENT_SOURCE = `${serviceName}.image`; /** * Add your * - pre-save hooks * - validations * - virtuals */ Image.addHook('afterCreate', () => { }); Image.addHook('afterUpdate', () => { }); Image.addHook('afterDestroy', () => { }); /** * Load query * @param {*} params */ function filterConditions(params) { const options = omitBy(params, isNil); options.is_active = true; // TODO: load condition if (options.name) { options.name = { [Op.iLike]: `%${options.name}%` }; } return options; } /** * Load sort query * @param {*} sort_by * @param {*} order_by */ function sortConditions({ sort_by, order_by }) { let sort = null; switch (sort_by) { case 'created_at': sort = ['created_at', order_by]; break; case 'updated_at': sort = ['updated_at', order_by]; break; default: sort = ['created_at', 'DESC']; break; } return sort; } /** * Transform postgres model to expose object */ Image.transform = (params) => { const transformed = {}; const fields = [ 'id', 'name', 'payload', 'created_by' ]; fields.forEach((field) => { transformed[field] = params[field]; }); // pipe date const dateFields = [ 'created_at', 'updated_at' ]; dateFields.forEach((field) => { if (params[field]) { transformed[field] = moment(params[field]).unix(); } else { transformed[field] = null; } }); return transformed; }; /** * Get all changed properties */ Image.getChangedProperties = ({ newModel, oldModel }) => { const changedProperties = []; const allChangableProperties = [ 'id', 'name', 'payload', ]; if (!oldModel) { return allChangableProperties; } allChangableProperties.forEach((field) => { if ( !isUndefined(newModel[field]) && !isEqual(newModel[field], oldModel[field]) ) { changedProperties.push(field); } }); return changedProperties; }; /** * Detail * * @public * @param {string} id */ Image.get = async (id) => { try { const data = await Image.findOne({ where: { id, is_active: true } }); if (!data) { throw new APIError({ status: httpStatus.NOT_FOUND, message: 'Không tìm thấy địa chỉ tỉnh/thành!' }); } return data; } catch (ex) { throw ex; } }; /** * List users in descending order of 'createdAt' timestamp. * * @param {number} skip - Number of users to be skipped. * @param {number} limit - Limit number of users to be returned. * @returns {Promise} */ Image.list = async ({ name, // sort sort_by, order_by, skip = 0, limit = 20, }) => { const options = filterConditions({ name }); const sort = sortConditions({ sort_by, order_by }); return Image.findAll({ where: options, order: [sort], offset: skip, limit: limit }); }; /** * Total records. * * @param {number} skip - Number of users to be skipped. * @param {number} limit - Limit number of users to be returned. * @returns {Promise} */ Image.totalRecords = ({ name }) => { const options = filterConditions({ name }); return Image.count({ where: options }); }; /** * Filter only allowed fields from Province * * @param {Object} params */ Image.filterParams = (params) => pick(params, PUBLIC_FIELDS); /** * @typedef Province */ export default Image;