Add new file database, count how many times its downloaded

tungd0 1 year ago
parent 171fc25ee5
commit a2c21de092
  1. 223
      package.json
  2. 1
      public/15/login-password.json
  3. 0
      public/15/name name/file.txt
  4. 0
      public/15/namename/file.txt
  5. BIN
      public/59/Papers-1(2).docx
  6. BIN
      public/60/LouiseHay-YouCanHealYourLife-HayHouse(1984).epub
  7. 45
      public/60/deeplearning_ex2.py
  8. 1
      public/60/login-password.json
  9. BIN
      public/9/c1a875_e21d978198ad4b9c85cf63a8d1b146cc_mv2 (1).jpeg
  10. BIN
      public/9/c1a875_e75b8c21992e4f749fed9f2bfec29872_mv2 (1).png
  11. BIN
      public/9/c1a875_e75b8c21992e4f749fed9f2bfec29872_mv2 (2).png
  12. BIN
      public/9/coinbanner.jpeg
  13. BIN
      public/9/test.docx
  14. BIN
      public/9/test1/test.docx
  15. BIN
      public/download/15/123353222-1684321000419.zip
  16. BIN
      public/download/15/123353222-1690800641686.zip
  17. BIN
      public/download/60/1233532-1691052065162.zip
  18. 230
      src/api/controllers/v1/image.controller.js
  19. 595
      src/api/controllers/v1/path.controller.js
  20. 377
      src/api/controllers/v1/user.controller.js
  21. 40
      src/api/middlewares/image.middleware.js
  22. 80
      src/api/routes/v1/image.route.js
  23. 105
      src/api/routes/v1/path.route.js
  24. 817
      src/common/models/config.model.js
  25. 554
      src/common/models/file.model.js
  26. 585
      src/common/models/image.model.js
  27. 2036
      src/common/models/user.model.js
  28. 238
      src/common/services/adapters/upload-adapter.js
  29. 30
      src/config/locales/en.json
  30. 80
      src/config/postgres.js
  31. 2489
      yarn.lock

@ -1,111 +1,112 @@
{ {
"name": "backend-image", "name": "backend-image",
"version": "1.0.0", "version": "1.0.0",
"description": "Service backend image", "description": "Service backend image",
"author": "Mạnh Tiến", "author": "Mạnh Tiến",
"main": "/src/index.js", "main": "/src/index.js",
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8", "node": ">=8",
"yarn": "*" "yarn": "*"
}, },
"nyc": { "nyc": {
"require": [ "require": [
"babel-register" "babel-register"
], ],
"sourceMap": false, "sourceMap": false,
"instrument": false "instrument": false
}, },
"scripts": { "scripts": {
"clean": "./node_modules/.bin/rimraf dist -p", "clean": "./node_modules/.bin/rimraf dist -p",
"build": "yarn run clean && mkdir -p dist && ./node_modules/.bin/babel src -s -D -d dist", "build": "yarn run clean && mkdir -p dist && ./node_modules/.bin/babel src -s -D -d dist",
"start": "cross-env NODE_ENV=production pm2 start ./dist/index.js", "start": "cross-env NODE_ENV=production pm2 start ./dist/index.js",
"start-worker": "cross-env NODE_ENV=production pm2 start docker-process.yml --only worker", "start-worker": "cross-env NODE_ENV=production pm2 start docker-process.yml --only worker",
"start-event-dispatcher": "cross-env NODE_ENV=production pm2 start docker-process.yml --only event-dispatcher", "start-event-dispatcher": "cross-env NODE_ENV=production pm2 start docker-process.yml --only event-dispatcher",
"dev": "nodemon src/index.js --exec ./node_modules/.bin/babel-node", "dev": "nodemon src/index.js --exec ./node_modules/.bin/babel-node",
"dev-worker": "nodemon src/index-worker.js --exec ./node_modules/.bin/babel-node", "dev-worker": "nodemon src/index-worker.js --exec ./node_modules/.bin/babel-node",
"dev-event-dispatcher": "nodemon src/index-event-dispatcher.js --exec ./node_modules/.bin/babel-node", "dev-event-dispatcher": "nodemon src/index-event-dispatcher.js --exec ./node_modules/.bin/babel-node",
"lint": "eslint **/*.js --ignore-path .gitignore --ignore-pattern internals/scripts", "lint": "eslint **/*.js --ignore-path .gitignore --ignore-pattern internals/scripts",
"lint:fix": "yarn lint -- --fix", "lint:fix": "yarn lint -- --fix",
"lint:watch": "yarn lint -- --watch", "lint:watch": "yarn lint -- --watch",
"test": "cross-env NODE_ENV=test nyc --reporter=html --reporter=text mocha --timeout 20000 --recursive src/api/tests", "test": "cross-env NODE_ENV=test nyc --reporter=html --reporter=text mocha --timeout 20000 --recursive src/api/tests",
"test:unit": "cross-env NODE_ENV=test mocha dist/api/tests/unit", "test:unit": "cross-env NODE_ENV=test mocha dist/api/tests/unit",
"test:integration": "cross-env NODE_ENV=test mocha --timeout 20000 dist/api/tests/integration", "test:integration": "cross-env NODE_ENV=test mocha --timeout 20000 dist/api/tests/integration",
"test:watch": "cross-env NODE_ENV=test mocha --watch dist/api/tests/unit", "test:watch": "cross-env NODE_ENV=test mocha --watch dist/api/tests/unit",
"coverage": "nyc report --reporter=text-lcov | coveralls", "coverage": "nyc report --reporter=text-lcov | coveralls",
"validate": "yarn lint && yarn test", "validate": "yarn lint && yarn test",
"postpublish": "git push --tags", "postpublish": "git push --tags",
"docker:start": "node ./dist/index.js --exec ./node_modules/.bin/babel-node", "docker:start": "node ./dist/index.js --exec ./node_modules/.bin/babel-node",
"docker:dev": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up", "docker:dev": "docker-compose -f docker-compose.yml -f docker-compose.dev.yml up",
"docker:test": "docker-compose -f docker-compose.yml -f docker-compose.test.yml up --abort-on-container-exit" "docker:test": "docker-compose -f docker-compose.yml -f docker-compose.test.yml up --abort-on-container-exit"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@gitlab.com:csell-team/b2c/sv-backend-file.git" "url": "git@gitlab.com:csell-team/b2c/sv-backend-file.git"
}, },
"dependencies": { "dependencies": {
"amqplib": "^0.5.2", "@shopify/cli": "^3.45.4",
"archiver": "^5.3.1", "amqplib": "^0.5.2",
"auth-adapter": "1.1.0", "archiver": "^5.3.1",
"axios": "^0.18.0", "auth-adapter": "1.1.0",
"bcryptjs": "^2.4.3", "axios": "^0.18.0",
"bluebird": "^3.5.2", "bcryptjs": "^2.4.3",
"body-parser": "^1.17.0", "bluebird": "^3.5.2",
"bull": "^3.4.1", "body-parser": "^1.17.0",
"busboy": "^1.6.0", "bull": "^3.4.1",
"compression": "^1.6.2", "busboy": "^1.6.0",
"cors": "^2.8.3", "compression": "^1.6.2",
"cross-env": "^5.0.1", "cors": "^2.8.3",
"dotenv-safe": "^5.0.1", "cross-env": "^5.0.1",
"exceljs": "^4.3.0", "dotenv-safe": "^5.0.1",
"express": "^4.15.2", "exceljs": "^4.3.0",
"express-validation": "^1.0.2", "express": "^4.15.2",
"fs-extra": "^10.1.0", "express-validation": "^1.0.2",
"helmet": "^3.5.0", "fs-extra": "^10.1.0",
"http-status": "^1.0.1", "helmet": "^3.5.0",
"i18n": "^0.8.3", "http-status": "^1.0.1",
"image-downloader": "^4.3.0", "i18n": "^0.8.3",
"ioredis": "^4.14.0", "image-downloader": "^4.3.0",
"joi": "^10.4.1", "ioredis": "^4.14.0",
"jsonwebtoken": "^8.5.1", "joi": "^10.4.1",
"jszip": "^3.10.1", "jsonwebtoken": "^8.5.1",
"lodash": "^4.17.4", "jszip": "^3.10.1",
"method-override": "^2.3.8", "lodash": "^4.17.4",
"moment-timezone": "^0.5.13", "method-override": "^2.3.8",
"mongoose": "^5.7.0", "moment-timezone": "^0.5.13",
"morgan": "^1.8.1", "mongoose": "^5.7.0",
"multer": "^1.4.2", "morgan": "^1.8.1",
"nanoid": "^2.0.3", "multer": "^1.4.2",
"pg": "^8.5.1", "nanoid": "^2.0.3",
"pg-hstore": "^2.3.3", "pg": "^8.5.1",
"pm2": "^2.4.6", "pg-hstore": "^2.3.3",
"query-string": "^7.0.0", "pm2": "^2.4.6",
"rabbit-event-source": "1.0.0", "query-string": "^7.0.0",
"request": "^2.88.2", "rabbit-event-source": "1.0.0",
"sequelize": "^6.3.5", "request": "^2.88.2",
"sharp": "^0.30.6", "sequelize": "^6.3.5",
"uuid": "^9.0.0", "sharp": "^0.30.6",
"xlsx": "^0.16.9" "uuid": "^9.0.0",
}, "xlsx": "^0.16.9"
"devDependencies": { },
"@types/archiver": "^5.3.2", "devDependencies": {
"babel-cli": "^6.26.0", "@types/archiver": "^5.3.2",
"babel-plugin-istanbul": "^4.1.6", "babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1", "babel-plugin-istanbul": "^4.1.6",
"chai": "^4.1.0", "babel-preset-env": "^1.6.1",
"chai-as-promised": "^7.1.1", "chai": "^4.1.0",
"coveralls": "^3.0.0", "chai-as-promised": "^7.1.1",
"eslint": "^4.2.0", "coveralls": "^3.0.0",
"eslint-config-airbnb-base": "^12.0.1", "eslint": "^4.2.0",
"eslint-plugin-import": "^2.2.0", "eslint-config-airbnb-base": "^12.0.1",
"husky": "^0.14.3", "eslint-plugin-import": "^2.2.0",
"mocha": "^3.3.0", "husky": "^0.14.3",
"nodemon": "^1.11.0", "mocha": "^3.3.0",
"nyc": "^11.0.3", "nodemon": "^1.11.0",
"rimraf": "^2.6.2", "nyc": "^11.0.3",
"sinon": "^6.1.0", "rimraf": "^2.6.2",
"sinon-chai": "^3.0.0", "sinon": "^6.1.0",
"supertest": "^3.0.0" "sinon-chai": "^3.0.0",
} "supertest": "^3.0.0"
} }
}

@ -0,0 +1 @@
{"status":"error","message":"bad request"}

Binary file not shown.

@ -0,0 +1,45 @@
import torch
torch.manual_seed(2023)
def activation_func(x):
#TODO Implement one of these following activation function: sigmoid, tanh, ReLU, leaky ReLU
epsilon = 0.01 # Only use this variable if you choose Leaky ReLU
result = None
return result
def softmax(x):
# TODO Implement softmax function here
result = None
return result
# Define the size of each layer in the network
num_input = 784 # Number of node in input layer (28x28)
num_hidden_1 = 128 # Number of nodes in hidden layer 1
num_hidden_2 = 256 # Number of nodes in hidden layer 2
num_hidden_3 = 128 # Number of nodes in hidden layer 3
num_classes = 10 # Number of nodes in output layer
# Random input
input_data = torch.randn((1, num_input))
# Weights for inputs to hidden layer 1
W1 = torch.randn(num_input, num_hidden_1)
# Weights for hidden layer 1 to hidden layer 2
W2 = torch.randn(num_hidden_1, num_hidden_2)
# Weights for hidden layer 2 to hidden layer 3
W3 = torch.randn(num_hidden_2, num_hidden_3)
# Weights for hidden layer 3 to output layer
W4 = torch.randn(num_hidden_3, num_classes)
# and bias terms for hidden and output layers
B1 = torch.randn((1, num_hidden_1))
B2 = torch.randn((1, num_hidden_2))
B3 = torch.randn((1, num_hidden_3))
B4 = torch.randn((1, num_classes))
#TODO Calculate forward pass of the network here. Result should have the shape of [1,10]
# Dont forget to check if sum of result = 1.0
result = None
print(result)

@ -0,0 +1 @@
{"status":"error","message":"bad request"}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Binary file not shown.

@ -1,100 +1,130 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import { pick } from 'lodash';
import path from 'path'; import path from 'path';
import Busboy from 'busboy'; import Busboy from 'busboy';
import fs from 'fs-extra'; import fs from 'fs-extra';
import multer from 'multer'; import multer from 'multer';
import httpStatus from 'http-status'; import messages from '../../../config/messages';
// import moment from 'moment-timezone'; import httpStatus from 'http-status';
import { handler as ErrorHandel } from '../../middlewares/errors'; // import moment from 'moment-timezone';
import ApiException from '../../../common/utils/APIException'; import { handler as ErrorHandel } from '../../middlewares/errors';
// import eventBus from '../../../common/services/event-bus'; import ApiException from '../../../common/utils/APIException';
// import Image from '../../../common/models/image.model'; // import eventBus from '../../../common/services/event-bus';
import { import File from "../../../common/models/file.model";
cdn as cdnConfig, import { handler as ErrorHandler } from '../../middlewares/error';
storage as storageConfig // import Image from '../../../common/models/image.model';
} from '../../../config/vars'; import {
/** storage will create folder when new date */ cdn as cdnConfig,
storage as storageConfig
} from '../../../config/vars';
const filePath = `${storageConfig.uri}`; /** storage will create folder when new date */
const replaceBaseUrl = (location) => const filePath = `${storageConfig.uri}`;
location.replace(storageConfig.uri, cdnConfig.uri);
const replaceBaseUrl = (location) =>
exports.uploadSingle = (req, res, next) => { location.replace(storageConfig.uri, cdnConfig.uri);
try {
if (!req.file) {
throw new ApiException({ exports.uploadSingle = (req, res, next) => {
status: httpStatus.BAD_REQUEST, try {
message: 'Invalid file!' if (!req.file) {
}); throw new ApiException({
} status: httpStatus.BAD_REQUEST,
/** resize image uploaded */ message: 'Invalid file!'
// eventBus.emit(Image.Events.IMAGE_CREATED, req.file); });
return res.json({ url: replaceBaseUrl(req.file.path) }); }
} catch (ex) { /** resize image uploaded */
return ErrorHandel(ex, req, res, next); // eventBus.emit(Image.Events.IMAGE_CREATED, req.file);
} // await File.
}; return res.json({ url: replaceBaseUrl(req.file.path) });
} catch (ex) {
/** return ErrorHandel(ex, req, res, next);
* Upload multiple }
* };
* @param {Formdata} file
*/ /**
exports.uploadMultiple = (req, res, next) => { * Upload multiple
try { *
if (!req.files) { * @param {Formdata} file
throw new ApiException({ */
status: httpStatus.BAD_REQUEST, exports.uploadMultiple = (req, res, next) => {
message: 'Invalid file!' try {
}); // if (!req.files) {
} // throw new ApiException({
const urls = []; // status: httpStatus.BAD_REQUEST,
for (let index = 0; index < req.files.length; index += 1) { // message: 'Invalid file!'
urls.push(replaceBaseUrl(req.files[index].path)); // });
/** resize image uploaded */ // }
// eventBus.emit(Image.Events.IMAGE_CREATED, req.files[index]); const urls = [];
} const user = req.locals.user;
return res.json({ urls: urls }); let data = {}
} catch (ex) {
return ErrorHandel(ex, req, res, next); // const file = req.files;
}
};
for (let index = 0; index < req.files.length; index += 1) {
exports.uploadFile = (req, res, next) => { urls.push(replaceBaseUrl(req.files[index].path));
try { data.url = replaceBaseUrl(req.files[index].path);
console.log(req.query); data.name = req.files[index].originalname;
let filename = null; data.created_by = pick(user, ['id', 'name']);
const cfg = { highWaterMark: 1048576 * 2 }; // 20 mb // File.create()
cfg.headers = req.headers;
req.busboy = Busboy(cfg); /** resize image uploaded */
const pathName = `${filePath}/${req.query.path}`; // eventBus.emit(Image.Events.IMAGE_CREATED, req.files[index]);
multer({ File.create(data)
dest: `${filePath}`, .then(result => {
limits: { res.json({
fileSize: 1024 * 1024 * 2048 // 2048MB code: 0,
}, }); message: messages.UPLOAD_SUCCESS,
req.pipe(req.busboy); // Pipe it trough busboy })
return req.busboy.on('file', (name, file, info) => {
filename = info.filename; }).catch(err => {
ErrorHandler(err, req, res, next);
// Create a write stream of the new file
const fstream = fs.createWriteStream(path.join(pathName, filename)); })
// Pipe it trough }
file.pipe(fstream); // console.log(urls);
// return res.json({ urls: urls,data : data});
// On finish of the upload } catch (ex) {
fstream.on('close', () => { console.log("error");
console.log(`Upload of '${filename}' finished`); return ErrorHandel(ex, req, res, next);
return res.json({ url: replaceBaseUrl(`${pathName}/${filename}`) }); }
}); };
});
} catch (ex) { exports.uploadFile = (req, res, next) => {
return ErrorHandel(ex, req, res, next); try {
} console.log(req.query);
}; let filename = null;
const cfg = { highWaterMark: 1048576 * 2 }; // 20 mb
cfg.headers = req.headers;
req.busboy = Busboy(cfg);
const pathName = `${filePath}/${req.query.path}`;
multer({
dest: `${filePath}`,
limits: {
fileSize: 1024 * 1024 * 2048 // 2048MB
}, });
req.pipe(req.busboy); // Pipe it trough busboy
return req.busboy.on('file', (name, file, info) => {
filename = info.filename;
// Create a write stream of the new file
const fstream = fs.createWriteStream(path.join(pathName, filename));
// Pipe it trough
file.pipe(fstream);
// On finish of the upload
fstream.on('close', () => {
console.log(`Upload of '${filename}' finished`);
return res.json({ url: replaceBaseUrl(`${pathName}/${filename}`) });
});
});
} catch (ex) {
return ErrorHandel(ex, req, res, next);
}
};

@ -1,236 +1,359 @@
/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable import/no-extraneous-dependencies */
// import httpStatus from 'http-status'; // import httpStatus from 'http-status';
import fs from 'fs'; import fs from 'fs';
import archiver from 'archiver'; import archiver from 'archiver';
import multer from 'multer'; import multer from 'multer';
import path from 'path'; import path from 'path';
import { handler as ErrorHandel } from '../../middlewares/errors'; import { handler as ErrorHandel } from '../../middlewares/errors';
// import ApiException from '../../../common/utils/APIException'; import File from "../../../common/models/file.model";
import { import { handler as ErrorHandler } from '../../middlewares/error';
import ApiException from '../../../common/utils/APIException';
cdn as cdnConfig, import {
storage as storageConfig
} from '../../../config/vars'; cdn as cdnConfig,
import uploadAdapter from '../../../common/services/adapters/upload-adapter'; storage as storageConfig
import { cloneDeep, forEach } from 'lodash'; } from '../../../config/vars';
import uploadAdapter from '../../../common/services/adapters/upload-adapter';
function deleteFolderRecursive(folderPath) { import { cloneDeep, forEach } from 'lodash';
if (fs.existsSync(folderPath)) { import APIError from '../../middlewares/ApiError';
fs.readdirSync(folderPath).forEach((file) => { import { example } from 'joi';
const curPath = path.join(folderPath, file); import { where } from 'sequelize';
if (fs.lstatSync(curPath).isDirectory()) { // delete folder import messages from '../../../config/messages';
deleteFolderRecursive(curPath); // recursively call deleteFolderRecursive function
fs.rmdirSync(curPath); function deleteFolderRecursive(folderPath) {
} else { // delete file if (fs.existsSync(folderPath)) {
fs.unlinkSync(curPath); fs.readdirSync(folderPath).forEach((file) => {
} const curPath = path.join(folderPath, file);
}); if (fs.lstatSync(curPath).isDirectory()) { // delete folder
} deleteFolderRecursive(curPath); // recursively call deleteFolderRecursive function
} fs.rmdirSync(curPath);
/** } else { // delete file
* get file and folder fs.unlinkSync(curPath);
* }
* @param {Formdata} file });
*/ }
exports.get = (req, res, next) => { }
try { /**
const user = req.user; * get file and folder
*
let path = `${storageConfig.uri}/${user.id}`; * @param {Formdata} file
if (req.body.path) { */
path += req.body.path;
}
// console.log(path);
const listFile = []; exports.get = async (req, res, next) => {
fs.readdir(path, (err, files) => { try {
if (files && files.length > 0) { const user = req.user;
files.forEach((item) => { const user_infor = {
listFile.push({ id: user.id,
name: item, name: user.name
path: `${cdnConfig.uri}/${user.id}${req.body.path}/${item}`, };
isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory() console.log(user_infor);
}); let path = `${storageConfig.uri}/${user.id}`;
}); console.log(path);
} if (req.body.path) {
return res.json({ path += req.body.path;
code: 0, }
data: listFile const listFile = [];
}); // fs.readdir(path, (err, files) => {
}); // if (files && files.length > 0) {
// test local // files.forEach((item) => {
// fs.readdir(path, (err, files) => { // listFile.push({
// if (files && files.length > 0) { // name: item,
// files.forEach((item) => { // path: `${cdnConfig.uri}/${user.id}/${req.body.path}/${item}`,
// listFile.push({ // isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory(),
// name: item, // });
// path: `${storageConfig.uri}/${user.id}${req.body.path}/${item}`, // });
// isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory() // }
// }); // return res.json({
// }); // code: 0,
// } // data: listFile
// return res.json({ // });
// code: 0, // });
// data: listFile
// }); await File.findAll({
// }); where: {
is_active: true,
created_by : user_infor
return null; }
/** resize image uploaded */ }).then(result => {
} catch (ex) { let path = []
return ErrorHandel(ex, req, res, next); result.forEach(data => {
} console.log(data.created_by.id);
}; // console.log(`${storageConfig.uri}/${data.created_by.id}/${req.body.path}/${data.name}`);
const file = {
/** name: data.name,
* get file and folder path: data.url,
* // isFolder: fs.lstatSync(`${storageConfig.uri}/${data.created_by.id}/${req.body.path}/${data.name}`).isDirectory(),
* @param {Formdata} file isFolder: fs.lstatSync(`${storageConfig.uri}/${data.created_by.id}/${req.body.path}/${data.name}`).isDirectory(),
*/ download_count : data.download_count
exports.create = (req, res, next) => {
const user = req.user; }
let dir = `${user.id}`;
const name_folder = cloneDeep(req.body.name).trim(); path.push(file);
if (req.body.path) { });
dir += req.body.path; return res.json({
} code: 0,
if (req.body.name) { data : path
dir += `/${name_folder}`; })
} }).catch(ex => {
if (!fs.existsSync(dir)) { ErrorHandler(ex, req, res, next);
uploadAdapter.createFolder({ path: dir });
} })
return res.json({ code: 0, message: 'success' });
};
// test local
/** // fs.readdir(path, (err, files) => {
* get file and folder // if (files && files.length > 0) {
* // files.forEach((item) => {
* @param {Formdata} file // listFile.push({
*/ // name: item,
exports.update = (req, res, next) => { // path: `${cdnConfig.uri}/${user.id}${req.body.path}/${item}`,
try {
const oldPath = req.body.oldPath.replace(cdnConfig.uri, storageConfig.uri); // path: `${storageConfig.uri}/${user.id}${req.body.path}/${item}`,
const newPath = req.body.newPath.replace(cdnConfig.uri, storageConfig.uri); // isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory()
// });
fs.rename(oldPath, newPath, (err) => { // });
if (err) { // }
console.log(err); // return res.json({
return res.status(400).json({ code: 400, message: 'lỗi' }); // code: 0,
} // data: listFile
return res.json({ code: 0, message: 'success' }); // });
}); // });
return null;
} catch (ex) {
return ErrorHandel(ex, req, res, next); return null;
} /** resize image uploaded */
}; } catch (ex) {
return ErrorHandel(ex, req, res, next);
}
exports.delete = (req, res, next) => { };
try {
const user = req.user; /**
const dir = `${storageConfig.uri_backup}/${user.id}`; * get file and folder
multer({ dest: `${dir}` }); *
const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); * @param {Formdata} file
const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup); */
// fs.rm(path, { recursive: true }, err => { exports.create = (req, res, next) => {
// if (err) { const user = req.user;
// return res.status(400).json({ code: 400, message: 'lỗi', detail: err }); let dir = `${user.id}`;
// } const name_folder = cloneDeep(req.body.name).trim();
// return res.json({ code: 0, message: 'success' }); if (req.body.path) {
// }); dir += req.body.path;
fs.rename(path, newpath, (err) => { }
if (err) throw err; if (req.body.name) {
return res.json({ code: 0, message: 'success' }); dir += `/${name_folder}`;
}); }
return null; if (!fs.existsSync(dir)) {
} catch (ex) { uploadAdapter.createFolder({ path: dir });
return ErrorHandel(ex, req, res, next); }
} return res.json({ code: 0, message: 'success' });
}; };
exports.download = async (req, res, next) => {
try { /**
const user = req.user; * get file and folder
const namefile = `${user.name}-${Date.now()}.zip`; *
const dir = `${storageConfig.uri}/download/${user.id}/${namefile}`; * @param {Formdata} file
const folder = `${storageConfig.uri}/download/${user.id}`; */
multer({ dest: `${folder}` }); exports.update = (req, res, next) => {
await deleteFolderRecursive(folder); try {
const output = fs.createWriteStream(dir); const oldPath = req.body.oldPath.replace(cdnConfig.uri, storageConfig.uri);
const archive = archiver('zip', { const newPath = req.body.newPath.replace(cdnConfig.uri, storageConfig.uri);
zlib: { level: 9 } // Sets the compression level.
}); fs.rename(oldPath, newPath, (err) => {
if (err) {
console.log(err);
archive.pipe(output); return res.status(400).json({ code: 400, message: 'lỗi' });
if (req.body.data) { }
req.body.data.forEach((e) => { return res.json({ code: 0, message: 'success' });
const path = e.path.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ '); });
// const path = e.path.replace(cdnConfig.uri, storageConfig.uri); return null;
console.log('path', path); } catch (ex) {
// const download = path.split("/"); return ErrorHandel(ex, req, res, next);
// download.splice( download.indexOf(`${user.id}`), 0, "download"); }
// const final_path = download.join("/"); };
if (e.isFolder) {
archive.directory(path, e.name);
} else { exports.delete = (req, res, next) => {
archive.file(path, { name: e.name }); try {
} const user = req.user;
}); const dir = `${storageConfig.uri_backup}/${user.id}`;
} multer({ dest: `${dir}` });
const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri);
archive.finalize(); const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup);
return res.json({ // fs.rm(path, { recursive: true }, err => {
code: 0, // if (err) {
data: { // return res.status(400).json({ code: 400, message: 'lỗi', detail: err });
name: namefile, // }
path: `${cdnConfig.uri}/download/${user.id}/${namefile}`, // return res.json({ code: 0, message: 'success' });
} // });
}); fs.rename(path, newpath, (err) => {
} catch (ex) { if (err) throw err;
return ErrorHandel(ex, req, res, next); return res.json({ code: 0, message: 'success' });
} });
}; return null;
} catch (ex) {
return ErrorHandel(ex, req, res, next);
exports.forceDelete = (req, res, next) => { }
try { };
const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); exports.download = async (req, res, next) => {
// const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup); try {
fs.rm(path, { recursive: true }, err => {
if (err) { const user = req.user;
return res.status(400).json({ code: 400, message: 'lỗi', detail: err }); const namefile = `${user.name}-${Date.now()}.zip`;
} const dir = `${storageConfig.uri}/download/${user.id}/${namefile}`;
return res.json({ code: 0, message: 'success' }); const folder = `${storageConfig.uri}/download/${user.id}`;
}); multer({ dest: `${folder}` });
await deleteFolderRecursive(folder);
return null; const output = fs.createWriteStream(dir);
} catch (ex) { const archive = archiver('zip', {
return ErrorHandel(ex, req, res, next); zlib: { level: 9 } // Sets the compression level.
} });
};
const user_infor = {
exports.deleteMultiple = (req, res, next) => { id: user.id,
try { name: user.name
const user = req.user; }
const dir = `${storageConfig.uri_backup}/${user.id}/${Date.now()}`; archive.pipe(output);
multer({ dest: `${dir}` }); if (req.body.data) {
if (req.body.data) { req.body.data.forEach( async (e) => {
req.body.data.forEach((e) => { // const path = e.path.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ ');
const path = e.path.replace(cdnConfig.uri, storageConfig.uri); // // // const path = e.path.replace(cdnConfig.uri, storageConfig.uri);
let newpath = e.path.replace(cdnConfig.uri, storageConfig.uri_backup); // console.log('path: ', path);
const split = newpath.split('/'); let downnload_count_list = new Map();
newpath = `${dir}/${split[split.length - 1]}`;
fs.rename(path, newpath, (err) => { await File.findOne({
if (err) throw err; where: {
return { code: 0, message: 'success' }; name: e.name,
}); url : e.path,
}); created_by: user_infor,
} is_active : true
return res.json({ code: 0, message: 'success' }); }
} catch (ex) { }).then(result => {
return ErrorHandel(ex, req, res, next); // plus one to the download count when download each selected file
} downnload_count_list.set( result.id,result.download_count + 1);
};
const storage = result.url.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ ');
if (e.isFolder) {
archive.directory(storage, e.name);
} else {
archive.file(storage, { name: e.name });
}
archive.finalize();
next()
}).catch(ex => {
console.log(ex);
next()
// ErrorHandel(ex, req, res, next);
});
downnload_count_list.forEach(async (value,key) => {
const new_download_count_value = {download_count : value};
await File.update(
new_download_count_value, {
where : {
id : key,
is_active: true
}
}
).then(result => {
console.log("download count add success");
next()
}).catch(ex => {
console.log("error2");
next()
// ErrorHandel(ex, req, res, next);
})
})
});
}
return res.json({
code: 0,
data: {
name: namefile,
path: `${cdnConfig.uri}/download/${user.id}/${namefile}`
}
});
} catch (ex) {
return ErrorHandel(ex, req, res, next);
}
};
exports.forceDelete = (req, res, next) => {
try {
const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri);
// const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup);
fs.rm(path, { recursive: true }, err => {
if (err) {
return res.status(400).json({ code: 400, message: 'lỗi', detail: err });
}
return res.json({ code: 0, message: 'success' });
});
return null;
} catch (ex) {
return ErrorHandel(ex, req, res, next);
}
};
exports.deleteMultiple = (req, res, next) => {
try {
// const dir = `${storageConfig.uri_backup}/${user.id}/${Date.now()}`;
// multer({ dest: `${dir}` });
if (req.body.data) {
req.body.data.forEach(async (e) => {
// const path = e.path.replace(cdnConfig.uri, storageConfig.uri);
// let newpath = e.path.replace(cdnConfig.uri, storageConfig.uri_backup);
// const split = newpath.split('/');
// newpath = `${dir}/${split[split.length - 1]}`;
// fs.rename(path, newpath, (err) => {
// if (err) throw err;
// return { code: 0, message: 'success' };
// });
console.log(e.path);
const user = req.user;
const user_infor = {
id: user.id,
name: user.name
}
const data = {is_active : false}
await File.update(
data,
{
where: {
name: e.name,
created_by: user_infor,
url : e.path
}
}
).then(result => {
console.log("success");
}).catch(ex => {
console.log(ex);
})
// console.log(e);
});
}
return res.json({ code: 0, message: messages.REMOVE_SUCCESS });
} catch (ex) {
return ErrorHandel(ex, req, res, next);
}
};

@ -1,189 +1,190 @@
import { hash } from 'bcryptjs'; import { hash } from 'bcryptjs';
import { pick } from 'lodash'; import { pick } from 'lodash';
// import httpStatus from 'http-status'; // import httpStatus from 'http-status';
import messages from '../../../config/messages'; import messages from '../../../config/messages';
// import { hash, compare } from 'bcryptjs'; // import { hash, compare } from 'bcryptjs';
import { handler as ErrorHandler } from '../../middlewares/error'; import { handler as ErrorHandler } from '../../middlewares/error';
import User from '../../../common/models/user.model'; import User from '../../../common/models/user.model';
import uploadAdapter from '../../../common/services/adapters/upload-adapter'; import uploadAdapter from '../../../common/services/adapters/upload-adapter';
/** /**
* Create * Create
* *
* @public * @public
* @param {StorySchema} body * @param {StorySchema} body
* @returns {Promise<StorySchema>, APIException>} * @returns {Promise<StorySchema>, APIException>}
*/ */
exports.create = async (req, res, next) => { exports.create = async (req, res, next) => {
// transform data // transform data
req.body.created_by = pick(req.user, ['id', 'name']); req.body.created_by = pick(req.user, ['id', 'name']);
const params = req.body; const params = req.body;
params.type = User.Types.INDIVIDUAL; params.type = User.Types.INDIVIDUAL;
params.service = User.Services.INDIVIDUAL; params.service = User.Services.INDIVIDUAL;
// save data // save data
await User.create(req.body) console.log(req.body);
.then(data => { await User.create(req.body)
uploadAdapter.createDefaultFolder({ id: data.id }); .then(data => {
res.json({ uploadAdapter.createDefaultFolder({ id: data.id });
code: 0, res.json({
message: messages.CREATE_SUCCESS, code: 0,
data: User.transform(data) message: messages.CREATE_SUCCESS,
}); data: User.transform(data)
}).catch(ex => { });
ErrorHandler(ex, req, res, next); }).catch(ex => {
}); ErrorHandler(ex, req, res, next);
}; });
};
/**
* List /**
* * List
* @public *
* @param {StorySchema} query * @public
* @returns {Promise<StorySchema[]>, APIException>} * @param {StorySchema} query
*/ * @returns {Promise<StorySchema[]>, APIException>}
exports.list = async (req, res, next) => { */
req.query.services = User.Services.USER; exports.list = async (req, res, next) => {
// console.log(req.query.services); req.query.services = User.Services.USER;
// User.list( { // console.log(req.query.services);
// service : "user", // User.list( {
// is_active: true // service : "user",
// } // is_active: true
// ).then(result => { // }
// res.json({ // ).then(result => {
// code: 0, // res.json({
// count: req.totalRecords, // code: 0,
// data: result.map( // count: req.totalRecords,
// x => User.transform(x) // data: result.map(
// ) // x => User.transform(x)
// }); // )
// }).catch(ex => { // });
// ErrorHandler(ex, req, res, next); // }).catch(ex => {
// }); // ErrorHandler(ex, req, res, next);
// });
return User.findAll({
where : { return User.findAll({
service : "user", where : {
is_active: true service : "user",
} is_active: true
}).then(result => { }
res.json({ }).then(result => {
code: 0, res.json({
count: req.totalRecords, code: 0,
data: result.map( count: req.totalRecords,
x => User.transform(x) data: result.map(
) x => User.transform(x)
}); )
}).catch(ex => { });
ErrorHandler(ex, req, res, next); }).catch(ex => {
}); ErrorHandler(ex, req, res, next);
}; });
};
/**
* Detail /**
* * Detail
* @public *
* @param {params} userId, * @public
* @returns {Promise<StorySchema>, APIException>} * @param {params} userId,
*/ * @returns {Promise<StorySchema>, APIException>}
exports.get = async (req, res, next) => res.json({ data: User.transform(req.locals.user) }); */
exports.get = async (req, res, next) => res.json({ data: User.transform(req.locals.user) });
/**
* Update /**
* * Update
* @public *
* @param {params} userId * @public
* @returns {Promise<any>, APIException>} * @param {params} userId
*/ * @returns {Promise<any>, APIException>}
exports.update = async (req, res, next) => { */
const { user } = req.locals; exports.update = async (req, res, next) => {
const dataChanged = User.getChangedProperties(req.body); const { user } = req.locals;
const new_properties = pick(req.body, dataChanged); const dataChanged = User.getChangedProperties(req.body);
// const updateUser = Object.assign( const new_properties = pick(req.body, dataChanged);
// user, // const updateUser = Object.assign(
// pick(req.body, dataChanged) // user,
// ); // pick(req.body, dataChanged)
// );
// const currentUser = await User.get(user.id)
// console.log(dataChanged); // const currentUser = await User.get(user.id)
// console.log(dataChanged);
return User.update(
new_properties, return User.update(
{ new_properties,
where: { {
id: user.id where: {
} id: user.id
} }
).then(() => { }
res.json({ ).then(() => {
code: 0, res.json({
message: messages.UPDATE_SUCCESS, code: 0,
// dataChanged: dataChanged message: messages.UPDATE_SUCCESS,
}); // dataChanged: dataChanged
}).catch(ex => { });
ErrorHandler(ex, req, res, next); }).catch(ex => {
}); ErrorHandler(ex, req, res, next);
}; });
};
/**
* delete /**
* * delete
* @public *
* @param {params} userId * @public
* @returns {Promise<any>, APIException>} * @param {params} userId
*/ * @returns {Promise<any>, APIException>}
exports.delete = async (req, res, next) => { */
const { user } = req.locals; exports.delete = async (req, res, next) => {
// const new_user = Object.assign( const { user } = req.locals;
// user, // const new_user = Object.assign(
// isactive : false // user,
// ) // isactive : false
// )
return User.update(
{ is_active: false}, return User.update(
{ { is_active: false},
where: { {
id: user.id where: {
} id: user.id
} }
).then( () => { }
res.json({ ).then( () => {
code: 0, res.json({
message: messages.REMOVE_SUCCESS code: 0,
}); message: messages.REMOVE_SUCCESS
}).catch(ex => { });
ErrorHandler(ex, req, res, next); }).catch(ex => {
}); ErrorHandler(ex, req, res, next);
}; });
};
exports.getStaffPermission = async (req, res, next) => {
const { story } = req.locals; exports.getStaffPermission = async (req, res, next) => {
return res.json({ const { story } = req.locals;
code: 0, return res.json({
data: story code: 0,
}); data: story
}; });
exports.updatePassword = async(req,res,next) => { };
const {new_password} = req.body; exports.updatePassword = async(req,res,next) => {
const {user} = req.locals; const {new_password} = req.body;
// console.log(user); const {user} = req.locals;
if (user) { // console.log(user);
const rounds = 10; if (user) {
const new_pass = await hash(new_password, rounds); const rounds = 10;
return User.update( const new_pass = await hash(new_password, rounds);
{password: new_pass}, return User.update(
{ {password: new_pass},
where: { {
id: user.id where: {
} id: user.id
}, }
).then( async () => { },
res.json({ ).then( async () => {
code: 0, res.json({
message: messages.UPDATE_SUCCESS code: 0,
}); message: messages.UPDATE_SUCCESS
}).catch(ex => { });
ErrorHandler(ex, req, res, next); }).catch(ex => {
}); ErrorHandler(ex, req, res, next);
}; });
};
}; };

@ -1,17 +1,23 @@
import { handler as ErrorHandler } from './errors'; import { handler as ErrorHandler } from './errors';
import Image from '../../common/models/image.model'; import Image from '../../common/models/image.model';
/** /**
* Load image and append to req. * Load image and append to req.
* @public * @public
*/ */
exports.load = async (req, res, next) => { exports.load = async (req, res, next) => {
try { try {
const image = await Image.getImageById(req.params.id); const image = await Image.getImageById(req.params.id);
req.locals = req.locals ? req.locals : {}; req.locals = req.locals ? req.locals : {};
req.locals.image = image; req.locals.image = image;
return next(); return next();
} catch (error) { } catch (error) {
return ErrorHandler(error, req, res); return ErrorHandler(error, req, res);
} }
}; };
// check wheather user has upload any file
exports.checkExist = async(req,res,next) => {
}

@ -1,38 +1,42 @@
import express from 'express'; import express from 'express';
// import validate from 'express-validation'; // import validate from 'express-validation';
import { authorize } from '../../middlewares/auth.middleware'; import { authorize } from '../../middlewares/auth.middleware';
import Permissions from '../../../common/utils/Permissions'; import Permissions from '../../../common/utils/Permissions';
import userMiddleware from '../../middlewares/user.middleware';
import { uploader } from '../../../common/services/adapters/upload-adapter';
import controller from '../../controllers/v1/image.controller'; import { uploader } from '../../../common/services/adapters/upload-adapter';
// import { import controller from '../../controllers/v1/image.controller';
// uploadValidation // import {
// } from '../../validations/v1/image.validation'; // uploadValidation
// } from '../../validations/v1/image.validation';
const router = express.Router();
const router = express.Router();
router
.route('/upload-single') router
.post( .route('/upload-single')
// authorize([Permissions.IMAGE_UPLOAD]), .post(
// validate(uploadValidation), // authorize([Permissions.IMAGE_UPLOAD]),
uploader.single('file'), // validate(uploadValidation),
controller.uploadSingle uploader.single('file'),
); controller.uploadSingle
);
router
.route('/upload-multiple') router
.post( .route('/upload-multiple/:id')
// authorize([Permissions.IMAGE_UPLOAD]), .post(
// validate(uploadValidation), // authorize([Permissions.IMAGE_UPLOAD]),
uploader.array('file', 100), // validate(uploadValidation),
controller.uploadMultiple userMiddleware.load,
); uploader.array('file', 100),
router controller.uploadMultiple
.route('/upload-file') );
.post( router
// authorize([Permissions.IMAGE_UPLOAD]), .route('/upload-file')
controller.uploadFile .post(
); // authorize([Permissions.IMAGE_UPLOAD]),
controller.uploadFile
export default router; );
export default router;

@ -1,51 +1,54 @@
import express from 'express'; import express from 'express';
import { authorize } from '../../middlewares/auth.middleware'; import { authorize } from '../../middlewares/auth.middleware';
import controller from '../../controllers/v1/path.controller'; import controller from '../../controllers/v1/path.controller';
import Permissions from '../../../common/utils/Permissions'; import Permissions from '../../../common/utils/Permissions';
const router = express.Router(); const router = express.Router();
router router
.route('/') .route('/')
.post( .post(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.get controller.get
); );
router router
.route('/create') .route('/create')
.post( .post(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.create controller.create
); );
router router
.route('/update') .route('/update')
.put( .put(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.update controller.update
); );
router router
.route('/delete') .route('/delete')
.patch( .patch(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.delete controller.delete
); );
router router
.route('/download') .route('/download')
.put( .put(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.download controller.download
); );
router router
.route('/force-delete') .route('/force-delete')
.patch( .patch(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.forceDelete controller.forceDelete
); );
router router
.route('/delete-multiple') .route('/delete-multiple')
.patch( .patch(
authorize([Permissions.USER]), authorize([Permissions.USER]),
controller.deleteMultiple controller.deleteMultiple
); );
export default router;
export default router;

@ -1,408 +1,409 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import httpStatus from 'http-status'; import httpStatus from 'http-status';
import { Model, DataTypes, Op } from 'sequelize'; import { Model, DataTypes, Op } from 'sequelize';
import { isEqual, isNil, isUndefined, omitBy, pick } from 'lodash'; import { isEqual, isNil, isUndefined, omitBy, pick } from 'lodash';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { serviceName } from '../../config/vars'; import { serviceName } from '../../config/vars';
import postgres from '../../config/postgres'; import postgres from '../../config/postgres';
import APIError from '../utils/APIException'; import APIError from '../utils/APIException';
/** /**
* Create connection * Create connection
*/ */
const { sequelize } = postgres; const { sequelize } = postgres;
class FileConfig extends Model { } class FileConfig extends Model { }
const PUBLIC_FIELDS = [ const PUBLIC_FIELDS = [
'name', 'name',
'type', 'type',
'group', 'group',
'config' 'config'
]; ];
FileConfig.Groups = { FileConfig.Groups = {
PRODUCT: 'product', PRODUCT: 'product',
PRODUCT_OPTION: 'product-option', PRODUCT_OPTION: 'product-option',
PRODUCT_PRICE: 'product-price', PRODUCT_PRICE: 'product-price',
ORDER: 'order', ORDER: 'order',
ORDER_NESTED: 'order-nested', ORDER_NESTED: 'order-nested',
INVOICE: 'invoice', INVOICE: 'invoice',
INVOICE_NESTED: 'invoice-nested', INVOICE_NESTED: 'invoice-nested',
RETURN: 'return', RETURN: 'return',
RETURN_NESTED: 'return-nested', RETURN_NESTED: 'return-nested',
DELIVERY: 'delivery', DELIVERY: 'delivery',
IMPORT: 'import', IMPORT: 'import',
IMPORT_NESTED: 'import-nested', IMPORT_NESTED: 'import-nested',
STOCK_TAKE: 'stock-take', STOCK_TAKE: 'stock-take',
STOCK_TAKE_NESTED: 'stock-take-nested', STOCK_TAKE_NESTED: 'stock-take-nested',
TRANSFER: 'transfer', TRANSFER: 'transfer',
TRANSFER_NESTED: 'transfer-nested', TRANSFER_NESTED: 'transfer-nested',
EXPORT: 'export', EXPORT: 'export',
EXPORT_NESTED: 'export-nested', EXPORT_NESTED: 'export-nested',
PAYMENT: 'payment', PAYMENT: 'payment',
CUSTOMER: 'customer', CUSTOMER: 'customer',
SUPPLIER: 'supplier', SUPPLIER: 'supplier',
DELIVERY_PAYMENT: 'delivery-payment', DELIVERY_PAYMENT: 'delivery-payment',
DELIVERY_PAYMENT_NESTED: 'delivery-payment-nested', DELIVERY_PAYMENT_NESTED: 'delivery-payment-nested',
/** Sale Report */ /** Sale Report */
SALE_REPORT_TIME: 'sale-report-time', SALE_REPORT_TIME: 'sale-report-time',
SALE_REPORT_TIME_NESTED: 'sale-report-time-nested', SALE_REPORT_TIME_NESTED: 'sale-report-time-nested',
SALE_REPORT_TIME_INVOICE: 'sale-report-time-invoice', SALE_REPORT_TIME_INVOICE: 'sale-report-time-invoice',
SALE_REPORT_PROFIT: 'sale-report-profit', SALE_REPORT_PROFIT: 'sale-report-profit',
SALE_REPORT_PROFIT_NESTED: 'sale-report-profit-nested', SALE_REPORT_PROFIT_NESTED: 'sale-report-profit-nested',
SALE_REPORT_PROFIT_INVOICE: 'sale-report-profit-invoice', SALE_REPORT_PROFIT_INVOICE: 'sale-report-profit-invoice',
SALE_REPORT_PROFIT_PRODUCT: 'sale-report-profit-product', SALE_REPORT_PROFIT_PRODUCT: 'sale-report-profit-product',
SALE_REPORT_DISCOUNT: 'sale-report-discount', SALE_REPORT_DISCOUNT: 'sale-report-discount',
SALE_REPORT_DISCOUNT_NESTED: 'sale-report-discount-nested', SALE_REPORT_DISCOUNT_NESTED: 'sale-report-discount-nested',
SALE_REPORT_DISCOUNT_INVOICE: 'sale-report-discount-invoice', SALE_REPORT_DISCOUNT_INVOICE: 'sale-report-discount-invoice',
SALE_REPORT_RETURN: 'sale-report-return', SALE_REPORT_RETURN: 'sale-report-return',
SALE_REPORT_RETURN_NESTED: 'sale-report-return-nested', SALE_REPORT_RETURN_NESTED: 'sale-report-return-nested',
SALE_REPORT_RETURN_INVOICE: 'sale-report-return-invoice', SALE_REPORT_RETURN_INVOICE: 'sale-report-return-invoice',
SALE_REPORT_STAFF: 'sale-report-staff', SALE_REPORT_STAFF: 'sale-report-staff',
SALE_REPORT_STAFF_NESTED: 'sale-report-staff-nested', SALE_REPORT_STAFF_NESTED: 'sale-report-staff-nested',
SALE_REPORT_STAFF_TIME: 'sale-report-staff-time', SALE_REPORT_STAFF_TIME: 'sale-report-staff-time',
SALE_REPORT_STAFF_TIME_NESTED: 'sale-report-staff-time-nested', SALE_REPORT_STAFF_TIME_NESTED: 'sale-report-staff-time-nested',
SALE_REPORT_STAFF_INVOICE: 'sale-report-staff-invoice', SALE_REPORT_STAFF_INVOICE: 'sale-report-staff-invoice',
SALE_REPORT_STORE: 'sale-report-store', SALE_REPORT_STORE: 'sale-report-store',
SALE_REPORT_STORE_NESTED: 'sale-report-store-nested', SALE_REPORT_STORE_NESTED: 'sale-report-store-nested',
SALE_REPORT_STORE_TIME: 'sale-report-store-time', SALE_REPORT_STORE_TIME: 'sale-report-store-time',
SALE_REPORT_STORE_TIME_NESTED: 'sale-report-store-time-nested', SALE_REPORT_STORE_TIME_NESTED: 'sale-report-store-time-nested',
SALE_REPORT_STORE_INVOICE: 'sale-report-store-invoice', SALE_REPORT_STORE_INVOICE: 'sale-report-store-invoice',
/** product report */ /** product report */
PRODUCT_REPORT_SALE: 'product-report-sale', PRODUCT_REPORT_SALE: 'product-report-sale',
PRODUCT_REPORT_SALE_SPECIFIC: 'product-report-sale-specific', PRODUCT_REPORT_SALE_SPECIFIC: 'product-report-sale-specific',
PRODUCT_REPORT_SALE_GROUP_CATEGORIES: 'product-report-sale-group-categories', PRODUCT_REPORT_SALE_GROUP_CATEGORIES: 'product-report-sale-group-categories',
PRODUCT_REPORT_SALE_DETAIL: 'product-report-sale-detail', PRODUCT_REPORT_SALE_DETAIL: 'product-report-sale-detail',
PRODUCT_REPORT_PROFIT: 'product-report-profit', PRODUCT_REPORT_PROFIT: 'product-report-profit',
PRODUCT_REPORT_PROFIT_GROUP_CATEGORIES: 'product-report-profit-group-categories', PRODUCT_REPORT_PROFIT_GROUP_CATEGORIES: 'product-report-profit-group-categories',
PRODUCT_REPORT_STOCK_VALUE: 'product-report-stock-value', PRODUCT_REPORT_STOCK_VALUE: 'product-report-stock-value',
PRODUCT_REPORT_STOCK_VALUE_GROUP_CATEGORIES: 'product-report-stock-value-group-categories', 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_DETAIL: 'product-report-stock-value-detail',
PRODUCT_REPORT_STOCK_VALUE_STORE: 'product-report-stock-value-store', PRODUCT_REPORT_STOCK_VALUE_STORE: 'product-report-stock-value-store',
PRODUCT_REPORT_STOCK_VALUE_GENERAL: 'product-report-stock-value-general', PRODUCT_REPORT_STOCK_VALUE_GENERAL: 'product-report-stock-value-general',
PRODUCT_REPORT_STOCK: 'product-report-stock', PRODUCT_REPORT_STOCK: 'product-report-stock',
PRODUCT_REPORT_STOCK_STORE: 'product-report-stock-store', PRODUCT_REPORT_STOCK_STORE: 'product-report-stock-store',
PRODUCT_REPORT_STOCK_ONE_STORE: 'product-report-stock-one-store', PRODUCT_REPORT_STOCK_ONE_STORE: 'product-report-stock-one-store',
PRODUCT_REPORT_STOCK_GROUP_CATEGORIES: 'product-report-stock-group-categories', PRODUCT_REPORT_STOCK_GROUP_CATEGORIES: 'product-report-stock-group-categories',
PRODUCT_REPORT_STOCK_MORE_STORE: 'product-report-stock-more-store', PRODUCT_REPORT_STOCK_MORE_STORE: 'product-report-stock-more-store',
PRODUCT_REPORT_STOCK_DETAIL: 'product-report-stock-detail', PRODUCT_REPORT_STOCK_DETAIL: 'product-report-stock-detail',
PRODUCT_REPORT_STOCK_DETAIL_STORE: 'product-report-stock-detail-store', PRODUCT_REPORT_STOCK_DETAIL_STORE: 'product-report-stock-detail-store',
PRODUCT_REPORT_STOCK_DETAIL_DETAIL: 'product-report-stock-detail-detail', 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_GROUP_CATEGORIES: 'product-report-stock-detail-group-categories',
PRODUCT_REPORT_STOCK_DETAIL_GENERAL: 'product-report-stock-detail-general', PRODUCT_REPORT_STOCK_DETAIL_GENERAL: 'product-report-stock-detail-general',
PRODUCT_REPORT_STAFF: 'product-report-staff', PRODUCT_REPORT_STAFF: 'product-report-staff',
PRODUCT_REPORT_STAFF_SPECIFIC: 'product-report-staff-specific', PRODUCT_REPORT_STAFF_SPECIFIC: 'product-report-staff-specific',
PRODUCT_REPORT_STAFF_DETAIL: 'product-report-staff-detail', PRODUCT_REPORT_STAFF_DETAIL: 'product-report-staff-detail',
PRODUCT_REPORT_STAFF_GROUP_CATEGORIES: 'product-report-staff-group-categories', PRODUCT_REPORT_STAFF_GROUP_CATEGORIES: 'product-report-staff-group-categories',
PRODUCT_REPORT_EXPORT: 'product-report-export', PRODUCT_REPORT_EXPORT: 'product-report-export',
PRODUCT_REPORT_EXPORT_SPECIFIC: 'product-report-export-specific', PRODUCT_REPORT_EXPORT_SPECIFIC: 'product-report-export-specific',
PRODUCT_REPORT_EXPORT_DETAIL: 'product-report-export-detail', PRODUCT_REPORT_EXPORT_DETAIL: 'product-report-export-detail',
PRODUCT_REPORT_EXPORT_GROUP_CATEGORIES: 'product-report-export-group-categories', PRODUCT_REPORT_EXPORT_GROUP_CATEGORIES: 'product-report-export-group-categories',
PRODUCT_REPORT_CUSTOMER: 'product-report-customer', PRODUCT_REPORT_CUSTOMER: 'product-report-customer',
PRODUCT_REPORT_CUSTOMER_SPECIFIC: 'product-report-customer-specific', PRODUCT_REPORT_CUSTOMER_SPECIFIC: 'product-report-customer-specific',
PRODUCT_REPORT_CUSTOMER_DETAIL: 'product-report-customer-detail', PRODUCT_REPORT_CUSTOMER_DETAIL: 'product-report-customer-detail',
PRODUCT_REPORT_CUSTOMER_GROUP_CATEGORIES: 'product-report-customer-group-categories', PRODUCT_REPORT_CUSTOMER_GROUP_CATEGORIES: 'product-report-customer-group-categories',
PRODUCT_REPORT_SUPPLIER: 'product-report-supplier', PRODUCT_REPORT_SUPPLIER: 'product-report-supplier',
PRODUCT_REPORT_SUPPLIER_DETAIL: 'product-report-supplier-detail', PRODUCT_REPORT_SUPPLIER_DETAIL: 'product-report-supplier-detail',
PRODUCT_REPORT_SUPPLIER_SPECIFIC: 'product-report-supplier-specific', PRODUCT_REPORT_SUPPLIER_SPECIFIC: 'product-report-supplier-specific',
PRODUCT_REPORT_SUPPLIER_GROUP_CATEGORIES: 'product-report-supplier-group-categories', PRODUCT_REPORT_SUPPLIER_GROUP_CATEGORIES: 'product-report-supplier-group-categories',
PRODUCT_REPORT_STOCK_SPECIFIC: 'product-report-stock-specific', PRODUCT_REPORT_STOCK_SPECIFIC: 'product-report-stock-specific',
PRODUCT_REPORT_STOCK_DETAIL_SPECIFIC: 'product-report-stock-detail-specific', PRODUCT_REPORT_STOCK_DETAIL_SPECIFIC: 'product-report-stock-detail-specific',
PRODUCT_REPORT_CUSTOMER_INVOICE: 'product-report-customer-invoice', PRODUCT_REPORT_CUSTOMER_INVOICE: 'product-report-customer-invoice',
PRODUCT_REPORT_STAFF_INVOICE: 'product-report-staff-invoice', PRODUCT_REPORT_STAFF_INVOICE: 'product-report-staff-invoice',
/** start end of day report */ /** start end of day report */
END_OF_DAY_REPORT_SALE: 'end-of-day-report-sale', 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: 'end-of-day-report-sale-detail',
END_OF_DAY_REPORT_SALE_DETAIL_TIME: 'end-of-day-report-sale-detail-time', 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_PAYMENT: 'end-of-day-report-payment',
END_OF_DAY_REPORT_PRODUCT: 'end-of-day-report-product', END_OF_DAY_REPORT_PRODUCT: 'end-of-day-report-product',
END_OF_DAY_REPORT_PRODUCT_DETAIL: 'end-of-day-report-product-detail', END_OF_DAY_REPORT_PRODUCT_DETAIL: 'end-of-day-report-product-detail',
}; };
FileConfig.Types = { FileConfig.Types = {
IMPORT: 'import', IMPORT: 'import',
EXPORT: 'export' EXPORT: 'export'
}; };
FileConfig.Configs = [ FileConfig.Configs = [
'name', // file name, 'name', // file name,
'path', // file path, 'path', // file path,
'content', // file data 'content', // file data
]; ];
/** /**
* FileConfig Schema * FileConfig Schema
* @public * @public
*/ */
FileConfig.init( FileConfig.init(
{ {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
autoIncrement: true, autoIncrement: true,
primaryKey: true primaryKey: true
}, },
name: { name: {
type: DataTypes.STRING(255), type: DataTypes.STRING(255),
defaultValue: null defaultValue: null
}, },
type: { type: {
type: DataTypes.STRING(50), type: DataTypes.STRING(50),
allowNull: false allowNull: false
}, },
group: { group: {
type: DataTypes.STRING(100), type: DataTypes.STRING(100),
defaultValue: null defaultValue: null
}, },
path: { path: {
type: DataTypes.STRING(155), type: DataTypes.STRING(155),
defaultValue: null defaultValue: null
}, },
config: { config: {
type: DataTypes.JSONB, type: DataTypes.JSONB,
defaultValue: null defaultValue: null
}, },
// manager // manager
is_active: { is_active: {
type: DataTypes.BOOLEAN, type: DataTypes.BOOLEAN,
defaultValue: true defaultValue: true
}, },
created_at: { created_at: {
type: DataTypes.DATE, type: DataTypes.DATE,
defaultValue: DataTypes.NOW defaultValue: DataTypes.NOW
}, },
updated_at: { updated_at: {
type: DataTypes.DATE, type: DataTypes.DATE,
defaultValue: DataTypes.NOW defaultValue: DataTypes.NOW
}, },
created_by: { created_by: {
type: DataTypes.JSONB, type: DataTypes.JSONB,
defaultValue: null // id | name defaultValue: null // id | name
} },
},
{ },
timestamps: false, {
schema: serviceName, timestamps: false,
sequelize: sequelize, schema: serviceName,
modelName: 'file_config', sequelize: sequelize,
tableName: 'tbl_file_configs' modelName: 'file_config',
} tableName: 'tbl_file_configs'
); }
);
/**
* Register event emiter /**
*/ * Register event emiter
FileConfig.Events = { */
FILE_CONFIG_CREATED: `${serviceName}.file-config.created`, FileConfig.Events = {
FILE_CONFIG_UPDATED: `${serviceName}.file-config.updated`, FILE_CONFIG_CREATED: `${serviceName}.file-config.created`,
FILE_CONFIG_DELETED: `${serviceName}.file-config.deleted`, FILE_CONFIG_UPDATED: `${serviceName}.file-config.updated`,
}; FILE_CONFIG_DELETED: `${serviceName}.file-config.deleted`,
FileConfig.EVENT_SOURCE = `${serviceName}.file-config`; };
FileConfig.EVENT_SOURCE = `${serviceName}.file-config`;
/**
* Add your /**
* - pre-save hooks * Add your
* - validations * - pre-save hooks
* - virtuals * - validations
*/ * - virtuals
FileConfig.addHook('afterCreate', () => { }); */
FileConfig.addHook('afterCreate', () => { });
FileConfig.addHook('afterUpdate', () => { });
FileConfig.addHook('afterUpdate', () => { });
FileConfig.addHook('afterDestroy', () => { });
FileConfig.addHook('afterDestroy', () => { });
/**
* Load query /**
* @param {*} params * Load query
*/ * @param {*} params
function filterConditions(params) { */
const options = omitBy(params, isNil); function filterConditions(params) {
options.is_active = true; const options = omitBy(params, isNil);
options.is_active = true;
// TODO: load condition
if (options.name) { // TODO: load condition
options.name = { if (options.name) {
[Op.iLike]: `%${options.name}%` options.name = {
}; [Op.iLike]: `%${options.name}%`
} };
}
return options;
} return options;
}
/**
* Load sort query /**
* @param {*} sort_by * Load sort query
* @param {*} order_by * @param {*} sort_by
*/ * @param {*} order_by
function sortConditions({ sort_by, order_by }) { */
let sort = null; function sortConditions({ sort_by, order_by }) {
switch (sort_by) { let sort = null;
case 'created_at': switch (sort_by) {
sort = ['created_at', order_by]; case 'created_at':
break; sort = ['created_at', order_by];
case 'updated_at': break;
sort = ['updated_at', order_by]; case 'updated_at':
break; sort = ['updated_at', order_by];
default: sort = ['created_at', 'DESC']; break;
break; default: sort = ['created_at', 'DESC'];
} break;
return sort; }
} return sort;
}
/**
* Transform postgres model to expose object /**
*/ * Transform postgres model to expose object
FileConfig.transform = (params) => { */
const transformed = {}; FileConfig.transform = (params) => {
const fields = [ const transformed = {};
'id', const fields = [
'name', 'id',
'type', 'name',
'group', 'type',
'config', 'group',
'created_by' 'config',
]; 'created_by'
fields.forEach((field) => { ];
transformed[field] = params[field]; fields.forEach((field) => {
}); transformed[field] = params[field];
});
// pipe date
const dateFields = [ // pipe date
'created_at', const dateFields = [
'updated_at' 'created_at',
]; 'updated_at'
dateFields.forEach((field) => { ];
if (params[field]) { dateFields.forEach((field) => {
transformed[field] = moment(params[field]).unix(); if (params[field]) {
} else { transformed[field] = moment(params[field]).unix();
transformed[field] = null; } else {
} transformed[field] = null;
}); }
});
return transformed;
}; return transformed;
};
/**
* Get all changed properties /**
*/ * Get all changed properties
FileConfig.getChangedProperties = ({ newModel, oldModel }) => { */
const changedProperties = []; FileConfig.getChangedProperties = ({ newModel, oldModel }) => {
const allChangableProperties = [ const changedProperties = [];
'name', const allChangableProperties = [
'type', 'name',
'group', 'type',
'config', 'group',
'status', 'config',
'status_name' 'status',
]; 'status_name'
if (!oldModel) { ];
return allChangableProperties; if (!oldModel) {
} return allChangableProperties;
}
allChangableProperties.forEach((field) => {
if ( allChangableProperties.forEach((field) => {
!isUndefined(newModel[field]) && if (
!isEqual(newModel[field], oldModel[field]) !isUndefined(newModel[field]) &&
) { !isEqual(newModel[field], oldModel[field])
changedProperties.push(field); ) {
} changedProperties.push(field);
}); }
});
return changedProperties;
}; return changedProperties;
};
/**
* Detail /**
* * Detail
* @public *
* @param {string} group * @public
*/ * @param {string} group
FileConfig.get = async (operation) => { */
try { FileConfig.get = async (operation) => {
const data = await FileConfig.findOne({ try {
where: { const data = await FileConfig.findOne({
type: operation.type, where: {
group: operation.group, type: operation.type,
is_active: true group: operation.group,
} is_active: true
}); }
if (!data) { });
throw new APIError({ if (!data) {
status: httpStatus.NOT_FOUND, throw new APIError({
message: 'Không tìm thấy file!' status: httpStatus.NOT_FOUND,
}); message: 'Không tìm thấy file!'
} });
return data; }
} catch (ex) { return data;
throw ex; } catch (ex) {
} throw ex;
}; }
};
/**
* List users in descending order of 'createdAt' timestamp. /**
* * 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. * @param {number} skip - Number of users to be skipped.
* @returns {Promise<Supplider[]>} * @param {number} limit - Limit number of users to be returned.
*/ * @returns {Promise<Supplider[]>}
FileConfig.list = async ({ */
name, FileConfig.list = async ({
name,
// sort
sort_by, // sort
order_by, sort_by,
skip = 0, order_by,
limit = 20, skip = 0,
}) => { limit = 20,
const options = filterConditions({ }) => {
name const options = filterConditions({
}); name
const sort = sortConditions({ sort_by, order_by }); });
return FileConfig.findAll({ const sort = sortConditions({ sort_by, order_by });
where: options, return FileConfig.findAll({
order: [sort], where: options,
offset: skip, order: [sort],
limit: limit offset: skip,
}); limit: limit
}; });
};
/**
* Total records. /**
* * Total records.
* @param {number} skip - Number of users to be skipped. *
* @param {number} limit - Limit number of users to be returned. * @param {number} skip - Number of users to be skipped.
* @returns {Promise<Number>} * @param {number} limit - Limit number of users to be returned.
*/ * @returns {Promise<Number>}
FileConfig.totalRecords = ({ */
name FileConfig.totalRecords = ({
}) => { name
const options = filterConditions({ }) => {
name const options = filterConditions({
}); name
});
return FileConfig.count({ where: options });
}; return FileConfig.count({ where: options });
};
/**
* Filter only allowed fields from Province /**
* * Filter only allowed fields from Province
* @param {Object} params *
*/ * @param {Object} params
FileConfig.filterParams = (params) => pick(params, PUBLIC_FIELDS); */
FileConfig.filterParams = (params) => pick(params, PUBLIC_FIELDS);
/**
* @typedef Province /**
*/ * @typedef Province
export default FileConfig; */
export default FileConfig;

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

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

File diff suppressed because it is too large Load Diff

@ -1,114 +1,124 @@
import multer from 'multer'; import multer from 'multer';
// import moment from 'moment-timezone'; // import moment from 'moment-timezone';
import { storage as storageConfig } from '../../../config/vars'; import { storage as storageConfig } from '../../../config/vars';
import { forIn } from 'lodash'; import { forIn } from 'lodash';
import { equal } from 'joi'; import { equal } from 'joi';
/** storage will create folder when new date */ /** storage will create folder when new date */
// const date = new Date(); // const date = new Date();
// const year = moment(date).format('YYYY'); // const year = moment(date).format('YYYY');
// const month = moment(date).format('MM'); // const month = moment(date).format('MM');
const filePath = `${storageConfig.uri}`; const filePath = `${storageConfig.uri}`;
const createDefaultFolder = ({ id }) => { const createDefaultFolder = ( id ) => {
try { try {
if (id) { if (id) {
multer({ dest: `${filePath}/${id}` }); multer({ dest: `${filePath}/${id}` });
} else { console.log(`creat default ${filePath}/${id}` );
multer({ dest: `${filePath}` });
} } else {
// multer({ dest: `${filePath}/images/games` }); multer({ dest: `${filePath}` });
// multer({ dest: `${filePath}/images/stories` }); console.log(`creat default ${filePath}` );
// multer({ dest: `${filePath}/images/chapters` });
// multer({ dest: `${filePath}/images/vouchers` }); }
// multer({ dest: `${filePath}/images/products` }); // multer({ dest: `${filePath}/images/games` });
// multer({ dest: `${filePath}/images/customers` }); // multer({ dest: `${filePath}/images/stories` });
// multer({ dest: `${filePath}/images/promotions` }); // multer({ dest: `${filePath}/images/chapters` });
// multer({ dest: `${filePath}/images/vouchers` });
// // configuration // multer({ dest: `${filePath}/images/products` });
// multer({ dest: `${filePath}/images/banners` }); // multer({ dest: `${filePath}/images/customers` });
// multer({ dest: `${filePath}/images/categories` }); // multer({ dest: `${filePath}/images/promotions` });
// multer({ dest: `${filePath}/images/upload/default` });
return true; // // configuration
} catch (ex) { // multer({ dest: `${filePath}/images/banners` });
return false; // multer({ dest: `${filePath}/images/categories` });
} // multer({ dest: `${filePath}/images/upload/default` });
}; return true;
const createFolder = ({ path }) => { } catch (ex) {
try { return false;
console.log(`${filePath}/${path}`); }
multer({ dest: `${filePath}/${path}` }); };
const createFolder = ({ path }) => {
try {
// multer({ dest: `${filePath}/images/games` }); console.log(`${filePath}/${path}`);
// multer({ dest: `${filePath}/images/stories` }); multer({ dest: `${filePath}/${path}` });
// multer({ dest: `${filePath}/images/chapters` });
// multer({ dest: `${filePath}/images/vouchers` });
// multer({ dest: `${filePath}/images/products` }); // multer({ dest: `${filePath}/images/games` });
// multer({ dest: `${filePath}/images/customers` }); // multer({ dest: `${filePath}/images/stories` });
// multer({ dest: `${filePath}/images/promotions` }); // multer({ dest: `${filePath}/images/chapters` });
// multer({ dest: `${filePath}/images/vouchers` });
// // configuration // multer({ dest: `${filePath}/images/products` });
// multer({ dest: `${filePath}/images/banners` }); // multer({ dest: `${filePath}/images/customers` });
// multer({ dest: `${filePath}/images/categories` }); // multer({ dest: `${filePath}/images/promotions` });
// multer({ dest: `${filePath}/images/upload/default` });
// console.log(multer); // // configuration
return true; // multer({ dest: `${filePath}/images/banners` });
} catch (ex) { // multer({ dest: `${filePath}/images/categories` });
return false; // multer({ dest: `${filePath}/images/upload/default` });
} // console.log(multer);
}; return true;
/** add image to storage follow group */ } catch (ex) {
const storage = multer.diskStorage({ return false;
destination: (req, file, cb) => { }
cb(null, filePath); };
}, /** add image to storage follow group */
filename: (req, file, cb) => { const storage = multer.diskStorage({
/** destination: (req, file, cb) => {
* setup folder follow date cb(null, filePath);
*/ },
createDefaultFolder({}); filename: (req, file, cb) => {
console.log('run in herer', req.query.path, file); /**
/** * setup folder follow date
* save image follow type */
*/ createDefaultFolder(req.params.id);
const path = req.query.path; console.log('run in herer', req.query.path, file);
// const fileName = file.originalname.includes('.') /**
// ? file.originalname.slice(0, file.originalname.lastIndexOf('.')) * save image follow type
// : file.originalname; */
cb(
null, // let path = req.locals.user.id;
`/${path}/${file.originalname.replace(/\s/g, '')}` // console.log(path);
); let path = req.params.id;
} console.log(path);
}); console.log(file);
const fileFilter = (req, file, cb) => { // const fileName = file.originalname.includes('.')
// if ( // ? file.originalname.slice(0, file.originalname.lastIndexOf('.'))
// file.mimetype === 'image/jpeg' || // : file.originalname;
// file.mimetype === 'image/webp' || cb(
// file.mimetype === 'image/png' || null,
// file.mimetype === 'image/gif' || `/${path}/${file.originalname.replace(/\s/g, '')}`
// ) { );
// cb(null, true); }
// } else { });
// cb(null, false);
// } const fileFilter = (req, file, cb) => {
cb(null, true); // if (
}; // file.mimetype === 'image/jpeg' ||
// file.mimetype === 'image/webp' ||
const uploader = multer({ // file.mimetype === 'image/png' ||
storage, // file.mimetype === 'image/gif' ||
limits: { // ) {
fileSize: 1024 * 1024 * 2048 // 5MB // cb(null, true);
}, // } else {
fileFilter // cb(null, false);
}); // }
cb(null, true);
module.exports = { };
createDefaultFolder,
createFolder, const uploader = multer({
uploader, storage,
fileFilter limits: {
}; fileSize: 1024 * 1024 * 2048 // 5MB
},
fileFilter
});
module.exports = {
createDefaultFolder,
createFolder,
uploader,
fileFilter
};

@ -35,5 +35,33 @@
"_ is not defined": "_ is not defined", "_ is not defined": "_ is not defined",
"Cannot access 'splited_dir' before initialization": "Cannot access 'splited_dir' before initialization", "Cannot access 'splited_dir' before initialization": "Cannot access 'splited_dir' before initialization",
"main_dir is not defined": "main_dir is not defined", "main_dir is not defined": "main_dir is not defined",
"Cannot read properties of undefined (reading 'trim')": "Cannot read properties of undefined (reading 'trim')" "Cannot read properties of undefined (reading 'trim')": "Cannot read properties of undefined (reading 'trim')",
"relation \"file_service.tbl_files\" does not exist": "relation \"file_service.tbl_files\" does not exist",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\12\\755296-200.png'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\12\\755296-200.png'",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\755296-200.png'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\755296-200.png'",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\Papers-1(2).docx'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\Papers-1(2).docx'",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\style.txt'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\style.txt'",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\12\\style.txt'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\12\\style.txt'",
"Cannot read properties of undefined (reading 'locals')": "Cannot read properties of undefined (reading 'locals')",
"body is not defined": "body is not defined",
"Tài khoản này đã được đăng kí": "Tài khoản này đã được đăng kí",
"file is not defined": "file is not defined",
"pick is not defined": "pick is not defined",
"path is not defined": "path is not defined",
"Cannot read properties of undefined (reading 'isFolder')": "Cannot read properties of undefined (reading 'isFolder')",
"Cannot read properties of undefined (reading 'isDirectory')": "Cannot read properties of undefined (reading 'isDirectory')",
"data.url.isDirectory is not a function": "data.url.isDirectory is not a function",
"ENOENT: no such file or directory, lstat 'http://103.162.31.170\\15\\login-password.json'": "ENOENT: no such file or directory, lstat 'http://103.162.31.170\\15\\login-password.json'",
"ENOENT: no such file or directory, lstat 'public/15/undefined/login-password.json'": "ENOENT: no such file or directory, lstat 'public/15/undefined/login-password.json'",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\59\\Papers-1(2).docx'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\59\\Papers-1(2).docx'",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\60\\Papers-1(2).docx'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\60\\Papers-1(2).docx'",
"ENOENT: no such file or directory, lstat 'public/60//Papers-1 (2).docx'": "ENOENT: no such file or directory, lstat 'public/60//Papers-1 (2).docx'",
"Converting circular structure to JSON\n --> starting at object with constructor 'Object'\n --- property 'win32' closes the circle": "Converting circular structure to JSON\n --> starting at object with constructor 'Object'\n --- property 'win32' closes the circle",
"EPERM: operation not permitted, lstat 'public\\download\\60\\1233532-1691036912591.zip'": "EPERM: operation not permitted, lstat 'public\\download\\60\\1233532-1691036912591.zip'",
"_file2.default.find is not a function": "_file2.default.find is not a function",
"storage is not defined": "storage is not defined",
"queue closed": "queue closed",
"downnload_count_list is not defined": "downnload_count_list is not defined",
"ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\deeplearning_ex2.py'": "ENOENT: no such file or directory, open 'C:\\Users\\TUNG DO\\upload-file-backend\\public\\undefined\\deeplearning_ex2.py'",
"invalid input syntax for type integer: \"deeplearning_ex2.py\"": "invalid input syntax for type integer: \"deeplearning_ex2.py\""
} }

@ -1,40 +1,40 @@
import Sequelize from 'sequelize'; import Sequelize from 'sequelize';
import bluebird from 'bluebird'; import bluebird from 'bluebird';
import { postgres, env } from './vars'; import { postgres, env } from './vars';
Sequelize.Promise = bluebird; Sequelize.Promise = bluebird;
const defaultErrorHandler = (err) => { const defaultErrorHandler = (err) => {
console.log(`Connection to Postgres error: ${err}`); console.log(`Connection to Postgres error: ${err}`);
}; };
const app = { const app = {
sequelize: new Sequelize( sequelize: new Sequelize(
postgres.uri, postgres.uri,
{ {
dialect: 'postgres' dialect: 'postgres'
} }
), ),
connect(errorHandler = defaultErrorHandler) { connect(errorHandler = defaultErrorHandler) {
this.sequelize.authenticate() this.sequelize.authenticate()
.then(() => { .then(() => {
console.log('Postgres connection established!'); console.log('Postgres connection established!');
if (env === '1') { if (env === '1') {
this.sequelize.sync({ this.sequelize.sync({
alter: true, alter: true,
logging: true logging: true
}); });
} }
}).catch((error) => { }).catch((error) => {
errorHandler(error); errorHandler(error);
}); });
return this.sequelize; return this.sequelize;
}, },
disconnect() { disconnect() {
// close connection // close connection
console.log('Closing postgres connection!'); console.log('Closing postgres connection!');
this.sequelize.close(); this.sequelize.close();
} }
}; };
export default app; export default app;

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save