You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
upload-file-backend/src/common/models/config.model.js

409 lines
12 KiB

/* 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 FileConfig extends Model { }
const PUBLIC_FIELDS = [
'name',
'type',
'group',
'config'
];
FileConfig.Groups = {
PRODUCT: 'product',
PRODUCT_OPTION: 'product-option',
PRODUCT_PRICE: 'product-price',
ORDER: 'order',
ORDER_NESTED: 'order-nested',
INVOICE: 'invoice',
INVOICE_NESTED: 'invoice-nested',
RETURN: 'return',
RETURN_NESTED: 'return-nested',
DELIVERY: 'delivery',
IMPORT: 'import',
IMPORT_NESTED: 'import-nested',
STOCK_TAKE: 'stock-take',
STOCK_TAKE_NESTED: 'stock-take-nested',
TRANSFER: 'transfer',
TRANSFER_NESTED: 'transfer-nested',
EXPORT: 'export',
EXPORT_NESTED: 'export-nested',
PAYMENT: 'payment',
CUSTOMER: 'customer',
SUPPLIER: 'supplier',
DELIVERY_PAYMENT: 'delivery-payment',
DELIVERY_PAYMENT_NESTED: 'delivery-payment-nested',
/** Sale Report */
SALE_REPORT_TIME: 'sale-report-time',
SALE_REPORT_TIME_NESTED: 'sale-report-time-nested',
SALE_REPORT_TIME_INVOICE: 'sale-report-time-invoice',
SALE_REPORT_PROFIT: 'sale-report-profit',
SALE_REPORT_PROFIT_NESTED: 'sale-report-profit-nested',
SALE_REPORT_PROFIT_INVOICE: 'sale-report-profit-invoice',
SALE_REPORT_PROFIT_PRODUCT: 'sale-report-profit-product',
SALE_REPORT_DISCOUNT: 'sale-report-discount',
SALE_REPORT_DISCOUNT_NESTED: 'sale-report-discount-nested',
SALE_REPORT_DISCOUNT_INVOICE: 'sale-report-discount-invoice',
SALE_REPORT_RETURN: 'sale-report-return',
SALE_REPORT_RETURN_NESTED: 'sale-report-return-nested',
SALE_REPORT_RETURN_INVOICE: 'sale-report-return-invoice',
SALE_REPORT_STAFF: 'sale-report-staff',
SALE_REPORT_STAFF_NESTED: 'sale-report-staff-nested',
SALE_REPORT_STAFF_TIME: 'sale-report-staff-time',
SALE_REPORT_STAFF_TIME_NESTED: 'sale-report-staff-time-nested',
SALE_REPORT_STAFF_INVOICE: 'sale-report-staff-invoice',
SALE_REPORT_STORE: 'sale-report-store',
SALE_REPORT_STORE_NESTED: 'sale-report-store-nested',
SALE_REPORT_STORE_TIME: 'sale-report-store-time',
SALE_REPORT_STORE_TIME_NESTED: 'sale-report-store-time-nested',
SALE_REPORT_STORE_INVOICE: 'sale-report-store-invoice',
/** product report */
PRODUCT_REPORT_SALE: 'product-report-sale',
PRODUCT_REPORT_SALE_SPECIFIC: 'product-report-sale-specific',
PRODUCT_REPORT_SALE_GROUP_CATEGORIES: 'product-report-sale-group-categories',
PRODUCT_REPORT_SALE_DETAIL: 'product-report-sale-detail',
PRODUCT_REPORT_PROFIT: 'product-report-profit',
PRODUCT_REPORT_PROFIT_GROUP_CATEGORIES: 'product-report-profit-group-categories',
PRODUCT_REPORT_STOCK_VALUE: 'product-report-stock-value',
PRODUCT_REPORT_STOCK_VALUE_GROUP_CATEGORIES: 'product-report-stock-value-group-categories',
PRODUCT_REPORT_STOCK_VALUE_DETAIL: 'product-report-stock-value-detail',
PRODUCT_REPORT_STOCK_VALUE_STORE: 'product-report-stock-value-store',
PRODUCT_REPORT_STOCK_VALUE_GENERAL: 'product-report-stock-value-general',
PRODUCT_REPORT_STOCK: 'product-report-stock',
PRODUCT_REPORT_STOCK_STORE: 'product-report-stock-store',
PRODUCT_REPORT_STOCK_ONE_STORE: 'product-report-stock-one-store',
PRODUCT_REPORT_STOCK_GROUP_CATEGORIES: 'product-report-stock-group-categories',
PRODUCT_REPORT_STOCK_MORE_STORE: 'product-report-stock-more-store',
PRODUCT_REPORT_STOCK_DETAIL: 'product-report-stock-detail',
PRODUCT_REPORT_STOCK_DETAIL_STORE: 'product-report-stock-detail-store',
PRODUCT_REPORT_STOCK_DETAIL_DETAIL: 'product-report-stock-detail-detail',
PRODUCT_REPORT_STOCK_DETAIL_GROUP_CATEGORIES: 'product-report-stock-detail-group-categories',
PRODUCT_REPORT_STOCK_DETAIL_GENERAL: 'product-report-stock-detail-general',
PRODUCT_REPORT_STAFF: 'product-report-staff',
PRODUCT_REPORT_STAFF_SPECIFIC: 'product-report-staff-specific',
PRODUCT_REPORT_STAFF_DETAIL: 'product-report-staff-detail',
PRODUCT_REPORT_STAFF_GROUP_CATEGORIES: 'product-report-staff-group-categories',
PRODUCT_REPORT_EXPORT: 'product-report-export',
PRODUCT_REPORT_EXPORT_SPECIFIC: 'product-report-export-specific',
PRODUCT_REPORT_EXPORT_DETAIL: 'product-report-export-detail',
PRODUCT_REPORT_EXPORT_GROUP_CATEGORIES: 'product-report-export-group-categories',
PRODUCT_REPORT_CUSTOMER: 'product-report-customer',
PRODUCT_REPORT_CUSTOMER_SPECIFIC: 'product-report-customer-specific',
PRODUCT_REPORT_CUSTOMER_DETAIL: 'product-report-customer-detail',
PRODUCT_REPORT_CUSTOMER_GROUP_CATEGORIES: 'product-report-customer-group-categories',
PRODUCT_REPORT_SUPPLIER: 'product-report-supplier',
PRODUCT_REPORT_SUPPLIER_DETAIL: 'product-report-supplier-detail',
PRODUCT_REPORT_SUPPLIER_SPECIFIC: 'product-report-supplier-specific',
PRODUCT_REPORT_SUPPLIER_GROUP_CATEGORIES: 'product-report-supplier-group-categories',
PRODUCT_REPORT_STOCK_SPECIFIC: 'product-report-stock-specific',
PRODUCT_REPORT_STOCK_DETAIL_SPECIFIC: 'product-report-stock-detail-specific',
PRODUCT_REPORT_CUSTOMER_INVOICE: 'product-report-customer-invoice',
PRODUCT_REPORT_STAFF_INVOICE: 'product-report-staff-invoice',
/** start end of day report */
END_OF_DAY_REPORT_SALE: 'end-of-day-report-sale',
END_OF_DAY_REPORT_SALE_DETAIL: 'end-of-day-report-sale-detail',
END_OF_DAY_REPORT_SALE_DETAIL_TIME: 'end-of-day-report-sale-detail-time',
END_OF_DAY_REPORT_PAYMENT: 'end-of-day-report-payment',
END_OF_DAY_REPORT_PRODUCT: 'end-of-day-report-product',
END_OF_DAY_REPORT_PRODUCT_DETAIL: 'end-of-day-report-product-detail',
};
FileConfig.Types = {
IMPORT: 'import',
EXPORT: 'export'
};
FileConfig.Configs = [
'name', // file name,
'path', // file path,
'content', // file data
];
/**
* FileConfig Schema
* @public
*/
FileConfig.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING(255),
defaultValue: null
},
type: {
type: DataTypes.STRING(50),
allowNull: false
},
group: {
type: DataTypes.STRING(100),
defaultValue: null
},
path: {
type: DataTypes.STRING(155),
defaultValue: null
},
config: {
type: DataTypes.JSONB,
defaultValue: null
},
// 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,
schema: serviceName,
sequelize: sequelize,
modelName: 'file_config',
tableName: 'tbl_file_configs'
}
);
/**
* Register event emiter
*/
FileConfig.Events = {
FILE_CONFIG_CREATED: `${serviceName}.file-config.created`,
FILE_CONFIG_UPDATED: `${serviceName}.file-config.updated`,
FILE_CONFIG_DELETED: `${serviceName}.file-config.deleted`,
};
FileConfig.EVENT_SOURCE = `${serviceName}.file-config`;
/**
* Add your
* - pre-save hooks
* - validations
* - virtuals
*/
FileConfig.addHook('afterCreate', () => { });
FileConfig.addHook('afterUpdate', () => { });
FileConfig.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
*/
FileConfig.transform = (params) => {
const transformed = {};
const fields = [
'id',
'name',
'type',
'group',
'config',
'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
*/
FileConfig.getChangedProperties = ({ newModel, oldModel }) => {
const changedProperties = [];
const allChangableProperties = [
'name',
'type',
'group',
'config',
'status',
'status_name'
];
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} group
*/
FileConfig.get = async (operation) => {
try {
const data = await FileConfig.findOne({
where: {
type: operation.type,
group: operation.group,
is_active: true
}
});
if (!data) {
throw new APIError({
status: httpStatus.NOT_FOUND,
message: 'Không tìm thấy file!'
});
}
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<Supplider[]>}
*/
FileConfig.list = async ({
name,
// sort
sort_by,
order_by,
skip = 0,
limit = 20,
}) => {
const options = filterConditions({
name
});
const sort = sortConditions({ sort_by, order_by });
return FileConfig.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<Number>}
*/
FileConfig.totalRecords = ({
name
}) => {
const options = filterConditions({
name
});
return FileConfig.count({ where: options });
};
/**
* Filter only allowed fields from Province
*
* @param {Object} params
*/
FileConfig.filterParams = (params) => pick(params, PUBLIC_FIELDS);
/**
* @typedef Province
*/
export default FileConfig;