Compare commits
	
		
			3 Commits 
		
	
	
		
			65b85f1640
			...
			8888a9b1d3
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						8888a9b1d3 | 2 years ago | 
| 
							
							
								 | 
						c4edd5eca2 | 2 years ago | 
| 
							
							
								 | 
						785a3afd83 | 2 years ago | 
@ -1,112 +1,111 @@ | 
				
			|||||||
{ | 
					{ | 
				
			||||||
    "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": { | 
				
			||||||
        "@shopify/cli": "^3.45.4", | 
					        "amqplib": "^0.5.2", | 
				
			||||||
        "amqplib": "^0.5.2", | 
					        "archiver": "^5.3.1", | 
				
			||||||
        "archiver": "^5.3.1", | 
					        "auth-adapter": "1.1.0", | 
				
			||||||
        "auth-adapter": "1.1.0", | 
					        "axios": "^0.18.0", | 
				
			||||||
        "axios": "^0.18.0", | 
					        "bcryptjs": "^2.4.3", | 
				
			||||||
        "bcryptjs": "^2.4.3", | 
					        "bluebird": "^3.5.2", | 
				
			||||||
        "bluebird": "^3.5.2", | 
					        "body-parser": "^1.17.0", | 
				
			||||||
        "body-parser": "^1.17.0", | 
					        "bull": "^3.4.1", | 
				
			||||||
        "bull": "^3.4.1", | 
					        "busboy": "^1.6.0", | 
				
			||||||
        "busboy": "^1.6.0", | 
					        "compression": "^1.6.2", | 
				
			||||||
        "compression": "^1.6.2", | 
					        "cors": "^2.8.3", | 
				
			||||||
        "cors": "^2.8.3", | 
					        "cross-env": "^5.0.1", | 
				
			||||||
        "cross-env": "^5.0.1", | 
					        "dotenv-safe": "^5.0.1", | 
				
			||||||
        "dotenv-safe": "^5.0.1", | 
					        "exceljs": "^4.3.0", | 
				
			||||||
        "exceljs": "^4.3.0", | 
					        "express": "^4.15.2", | 
				
			||||||
        "express": "^4.15.2", | 
					        "express-validation": "^1.0.2", | 
				
			||||||
        "express-validation": "^1.0.2", | 
					        "fs-extra": "^10.1.0", | 
				
			||||||
        "fs-extra": "^10.1.0", | 
					        "helmet": "^3.5.0", | 
				
			||||||
        "helmet": "^3.5.0", | 
					        "http-status": "^1.0.1", | 
				
			||||||
        "http-status": "^1.0.1", | 
					        "i18n": "^0.8.3", | 
				
			||||||
        "i18n": "^0.8.3", | 
					        "image-downloader": "^4.3.0", | 
				
			||||||
        "image-downloader": "^4.3.0", | 
					        "ioredis": "^4.14.0", | 
				
			||||||
        "ioredis": "^4.14.0", | 
					        "joi": "^10.4.1", | 
				
			||||||
        "joi": "^10.4.1", | 
					        "jsonwebtoken": "^8.5.1", | 
				
			||||||
        "jsonwebtoken": "^8.5.1", | 
					        "jszip": "^3.10.1", | 
				
			||||||
        "jszip": "^3.10.1", | 
					        "lodash": "^4.17.4", | 
				
			||||||
        "lodash": "^4.17.4", | 
					        "method-override": "^2.3.8", | 
				
			||||||
        "method-override": "^2.3.8", | 
					        "moment-timezone": "^0.5.13", | 
				
			||||||
        "moment-timezone": "^0.5.13", | 
					        "mongoose": "^5.7.0", | 
				
			||||||
        "mongoose": "^5.7.0", | 
					        "morgan": "^1.8.1", | 
				
			||||||
        "morgan": "^1.8.1", | 
					        "multer": "^1.4.2", | 
				
			||||||
        "multer": "^1.4.2", | 
					        "nanoid": "^2.0.3", | 
				
			||||||
        "nanoid": "^2.0.3", | 
					        "pg": "^8.5.1", | 
				
			||||||
        "pg": "^8.5.1", | 
					        "pg-hstore": "^2.3.3", | 
				
			||||||
        "pg-hstore": "^2.3.3", | 
					        "pm2": "^2.4.6", | 
				
			||||||
        "pm2": "^2.4.6", | 
					        "query-string": "^7.0.0", | 
				
			||||||
        "query-string": "^7.0.0", | 
					        "rabbit-event-source": "1.0.0", | 
				
			||||||
        "rabbit-event-source": "1.0.0", | 
					        "request": "^2.88.2", | 
				
			||||||
        "request": "^2.88.2", | 
					        "sequelize": "^6.3.5", | 
				
			||||||
        "sequelize": "^6.3.5", | 
					        "sharp": "^0.30.6", | 
				
			||||||
        "sharp": "^0.30.6", | 
					        "uuid": "^9.0.0", | 
				
			||||||
        "uuid": "^9.0.0", | 
					        "xlsx": "^0.16.9" | 
				
			||||||
        "xlsx": "^0.16.9" | 
					    }, | 
				
			||||||
    }, | 
					    "devDependencies": { | 
				
			||||||
    "devDependencies": { | 
					        "@types/archiver": "^5.3.2", | 
				
			||||||
        "@types/archiver": "^5.3.2", | 
					        "babel-cli": "^6.26.0", | 
				
			||||||
        "babel-cli": "^6.26.0", | 
					        "babel-plugin-istanbul": "^4.1.6", | 
				
			||||||
        "babel-plugin-istanbul": "^4.1.6", | 
					        "babel-preset-env": "^1.6.1", | 
				
			||||||
        "babel-preset-env": "^1.6.1", | 
					        "chai": "^4.1.0", | 
				
			||||||
        "chai": "^4.1.0", | 
					        "chai-as-promised": "^7.1.1", | 
				
			||||||
        "chai-as-promised": "^7.1.1", | 
					        "coveralls": "^3.0.0", | 
				
			||||||
        "coveralls": "^3.0.0", | 
					        "eslint": "^4.2.0", | 
				
			||||||
        "eslint": "^4.2.0", | 
					        "eslint-config-airbnb-base": "^12.0.1", | 
				
			||||||
        "eslint-config-airbnb-base": "^12.0.1", | 
					        "eslint-plugin-import": "^2.2.0", | 
				
			||||||
        "eslint-plugin-import": "^2.2.0", | 
					        "husky": "^0.14.3", | 
				
			||||||
        "husky": "^0.14.3", | 
					        "mocha": "^3.3.0", | 
				
			||||||
        "mocha": "^3.3.0", | 
					        "nodemon": "^1.11.0", | 
				
			||||||
        "nodemon": "^1.11.0", | 
					        "nyc": "^11.0.3", | 
				
			||||||
        "nyc": "^11.0.3", | 
					        "rimraf": "^2.6.2", | 
				
			||||||
        "rimraf": "^2.6.2", | 
					        "sinon": "^6.1.0", | 
				
			||||||
        "sinon": "^6.1.0", | 
					        "sinon-chai": "^3.0.0", | 
				
			||||||
        "sinon-chai": "^3.0.0", | 
					        "supertest": "^3.0.0" | 
				
			||||||
        "supertest": "^3.0.0" | 
					    } | 
				
			||||||
    } | 
					} | 
				
			||||||
} | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1 +0,0 @@ | 
				
			|||||||
{"status":"error","message":"bad request"} | 
					 | 
				
			||||||
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						@ -1,45 +0,0 @@ | 
				
			|||||||
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) | 
					 | 
				
			||||||
@ -1 +0,0 @@ | 
				
			|||||||
{"status":"error","message":"bad request"} | 
					 | 
				
			||||||
| 
		 After Width: | Height: | Size: 100 KiB  | 
| 
		 After Width: | Height: | Size: 284 KiB  | 
| 
		 After Width: | Height: | Size: 284 KiB  | 
| 
		 After Width: | Height: | Size: 93 KiB  | 
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						
									
										Binary file not shown.
									
								
							
						@ -1,130 +1,100 @@ | 
				
			|||||||
/* 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 messages from '../../../config/messages'; | 
					import httpStatus from 'http-status'; | 
				
			||||||
import httpStatus from 'http-status'; | 
					// import moment from 'moment-timezone';
 | 
				
			||||||
// import moment from 'moment-timezone';
 | 
					import { handler as ErrorHandel } from '../../middlewares/errors'; | 
				
			||||||
import { handler as ErrorHandel } from '../../middlewares/errors'; | 
					import ApiException from '../../../common/utils/APIException'; | 
				
			||||||
import ApiException from '../../../common/utils/APIException'; | 
					// import eventBus from '../../../common/services/event-bus';
 | 
				
			||||||
// import eventBus from '../../../common/services/event-bus';
 | 
					// import Image from '../../../common/models/image.model';
 | 
				
			||||||
import File from "../../../common/models/file.model"; | 
					import { | 
				
			||||||
import { handler as ErrorHandler } from '../../middlewares/error'; | 
					    cdn as cdnConfig, | 
				
			||||||
// import Image from '../../../common/models/image.model';
 | 
					    storage as storageConfig | 
				
			||||||
import { | 
					} from '../../../config/vars'; | 
				
			||||||
    cdn as cdnConfig, | 
					/** storage will create folder when new date */ | 
				
			||||||
    storage as storageConfig | 
					
 | 
				
			||||||
} from '../../../config/vars'; | 
					
 | 
				
			||||||
/** storage will create folder when new date */ | 
					const filePath = `${storageConfig.uri}`; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const filePath = `${storageConfig.uri}`; | 
					const replaceBaseUrl = (location) => | 
				
			||||||
 | 
					    location.replace(storageConfig.uri, cdnConfig.uri); | 
				
			||||||
 | 
					
 | 
				
			||||||
const replaceBaseUrl = (location) => | 
					
 | 
				
			||||||
    location.replace(storageConfig.uri, cdnConfig.uri); | 
					exports.uploadSingle = (req, res, next) => { | 
				
			||||||
 | 
					    try { | 
				
			||||||
 | 
					        if (!req.file) { | 
				
			||||||
exports.uploadSingle = (req, res, next) => { | 
					            throw new ApiException({ | 
				
			||||||
    try { | 
					                status: httpStatus.BAD_REQUEST, | 
				
			||||||
        if (!req.file) { | 
					                message: 'Invalid file!' | 
				
			||||||
            throw new ApiException({ | 
					            }); | 
				
			||||||
                status: httpStatus.BAD_REQUEST, | 
					        } | 
				
			||||||
                message: 'Invalid file!' | 
					        /** resize image uploaded */ | 
				
			||||||
            }); | 
					        // eventBus.emit(Image.Events.IMAGE_CREATED, req.file);
 | 
				
			||||||
        } | 
					        return res.json({ url: replaceBaseUrl(req.file.path) }); | 
				
			||||||
        /** resize image uploaded */ | 
					    } catch (ex) { | 
				
			||||||
        // eventBus.emit(Image.Events.IMAGE_CREATED, req.file);
 | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
        // await File.
 | 
					    } | 
				
			||||||
        return res.json({ url: replaceBaseUrl(req.file.path) }); | 
					}; | 
				
			||||||
    } catch (ex) { | 
					
 | 
				
			||||||
        return ErrorHandel(ex, req, res, next); | 
					/** | 
				
			||||||
    } | 
					 * Upload multiple | 
				
			||||||
}; | 
					 * | 
				
			||||||
 | 
					 * @param {Formdata} file | 
				
			||||||
/** | 
					 */ | 
				
			||||||
 * Upload multiple | 
					exports.uploadMultiple = (req, res, next) => { | 
				
			||||||
 * | 
					    try { | 
				
			||||||
 * @param {Formdata} file | 
					        if (!req.files) { | 
				
			||||||
 */ | 
					            throw new ApiException({ | 
				
			||||||
exports.uploadMultiple = (req, res, next) => { | 
					                status: httpStatus.BAD_REQUEST, | 
				
			||||||
    try { | 
					                message: 'Invalid file!' | 
				
			||||||
        // if (!req.files) {
 | 
					            }); | 
				
			||||||
        //     throw new ApiException({
 | 
					        } | 
				
			||||||
        //         status: httpStatus.BAD_REQUEST,
 | 
					        const urls = []; | 
				
			||||||
        //         message: 'Invalid file!'
 | 
					        for (let index = 0; index < req.files.length; index += 1) { | 
				
			||||||
        //     });
 | 
					            urls.push(replaceBaseUrl(req.files[index].path)); | 
				
			||||||
        // }
 | 
					            /** resize image uploaded */ | 
				
			||||||
        const urls = []; | 
					            // eventBus.emit(Image.Events.IMAGE_CREATED, req.files[index]);
 | 
				
			||||||
        const user = req.locals.user; | 
					        } | 
				
			||||||
        let data = {} | 
					        return res.json({ urls: urls }); | 
				
			||||||
        
 | 
					    } catch (ex) { | 
				
			||||||
    //    const  file = req.files;
 | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
      
 | 
					    } | 
				
			||||||
 | 
					}; | 
				
			||||||
        for (let index = 0; index < req.files.length; index += 1) { | 
					
 | 
				
			||||||
            urls.push(replaceBaseUrl(req.files[index].path)); | 
					exports.uploadFile = (req, res, next) => { | 
				
			||||||
            data.url = replaceBaseUrl(req.files[index].path); | 
					    try { | 
				
			||||||
            data.name = req.files[index].originalname; | 
					        console.log(req.query); | 
				
			||||||
            data.created_by = pick(user, ['id', 'name']); | 
					        let filename = null; | 
				
			||||||
            // File.create()
 | 
					        const cfg = { highWaterMark: 1048576 * 2 }; // 20 mb
 | 
				
			||||||
           
 | 
					        cfg.headers = req.headers; | 
				
			||||||
            /** resize image uploaded */ | 
					        req.busboy = Busboy(cfg); | 
				
			||||||
            // eventBus.emit(Image.Events.IMAGE_CREATED, req.files[index]);
 | 
					        const pathName = `${filePath}/${req.query.path}`; | 
				
			||||||
            File.create(data) | 
					        multer({ | 
				
			||||||
                .then(result => { | 
					            dest: `${filePath}`, | 
				
			||||||
                    res.json({ | 
					            limits: { | 
				
			||||||
                        code: 0, | 
					                fileSize: 1024 * 1024 * 2048 // 2048MB
 | 
				
			||||||
                        message: messages.UPLOAD_SUCCESS, | 
					            }, }); | 
				
			||||||
                    }) | 
					        req.pipe(req.busboy); // Pipe it trough busboy
 | 
				
			||||||
                    
 | 
					        return req.busboy.on('file', (name, file, info) => { | 
				
			||||||
                }).catch(err => { | 
					            filename = info.filename; | 
				
			||||||
                    ErrorHandler(err, req, res, next); | 
					
 | 
				
			||||||
 | 
					            // Create a write stream of the new file
 | 
				
			||||||
                }) | 
					            const fstream = fs.createWriteStream(path.join(pathName, filename)); | 
				
			||||||
        } | 
					            // Pipe it trough
 | 
				
			||||||
        // console.log(urls);
 | 
					            file.pipe(fstream); | 
				
			||||||
        // return res.json({ urls: urls,data : data});
 | 
					
 | 
				
			||||||
    } catch (ex) { | 
					            // On finish of the upload
 | 
				
			||||||
        console.log("error"); | 
					            fstream.on('close', () => { | 
				
			||||||
        return ErrorHandel(ex, req, res, next); | 
					                console.log(`Upload of '${filename}' finished`); | 
				
			||||||
    } | 
					                return res.json({ url: replaceBaseUrl(`${pathName}/${filename}`) }); | 
				
			||||||
}; | 
					            }); | 
				
			||||||
 | 
					        }); | 
				
			||||||
exports.uploadFile = (req, res, next) => { | 
					    } catch (ex) { | 
				
			||||||
    try { | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
        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,360 +1,236 @@ | 
				
			|||||||
/* 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 File from "../../../common/models/file.model"; | 
					// import ApiException from '../../../common/utils/APIException';
 | 
				
			||||||
import { handler as ErrorHandler } from '../../middlewares/error'; | 
					import { | 
				
			||||||
import ApiException from '../../../common/utils/APIException'; | 
					
 | 
				
			||||||
import { | 
					    cdn as cdnConfig, | 
				
			||||||
 | 
					    storage as storageConfig | 
				
			||||||
    cdn as cdnConfig, | 
					} from '../../../config/vars'; | 
				
			||||||
    storage as storageConfig | 
					import uploadAdapter from '../../../common/services/adapters/upload-adapter'; | 
				
			||||||
} from '../../../config/vars'; | 
					import { cloneDeep, forEach } from 'lodash'; | 
				
			||||||
import uploadAdapter from '../../../common/services/adapters/upload-adapter'; | 
					
 | 
				
			||||||
import { cloneDeep, forEach } from 'lodash'; | 
					function deleteFolderRecursive(folderPath) { | 
				
			||||||
import APIError from '../../middlewares/ApiError'; | 
					    if (fs.existsSync(folderPath)) { | 
				
			||||||
import { example } from 'joi'; | 
					        fs.readdirSync(folderPath).forEach((file) => { | 
				
			||||||
import { where } from 'sequelize'; | 
					            const curPath = path.join(folderPath, file); | 
				
			||||||
import messages from '../../../config/messages'; | 
					            if (fs.lstatSync(curPath).isDirectory()) { // delete folder
 | 
				
			||||||
 | 
					                deleteFolderRecursive(curPath); // recursively call deleteFolderRecursive function
 | 
				
			||||||
function deleteFolderRecursive(folderPath) { | 
					                fs.rmdirSync(curPath); | 
				
			||||||
    if (fs.existsSync(folderPath)) { | 
					            } else { // delete file
 | 
				
			||||||
        fs.readdirSync(folderPath).forEach((file) => { | 
					                fs.unlinkSync(curPath); | 
				
			||||||
            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
 | 
					/** | 
				
			||||||
                fs.unlinkSync(curPath); | 
					 * get file and folder | 
				
			||||||
            } | 
					 * | 
				
			||||||
        }); | 
					 * @param {Formdata} file | 
				
			||||||
    } | 
					 */ | 
				
			||||||
} | 
					exports.get = (req, res, next) => { | 
				
			||||||
/** | 
					    try { | 
				
			||||||
 * get file and folder | 
					        const user = req.user; | 
				
			||||||
 * | 
					
 | 
				
			||||||
 * @param {Formdata} file | 
					        let path = `${storageConfig.uri}/${user.id}`; | 
				
			||||||
 */ | 
					        if (req.body.path) { | 
				
			||||||
 | 
					            path += req.body.path; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        // console.log(path);
 | 
				
			||||||
exports.get = async (req, res, next) => { | 
					        const listFile = []; | 
				
			||||||
    try { | 
					        fs.readdir(path, (err, files) => { | 
				
			||||||
        const user = req.user; | 
					            if (files && files.length > 0) { | 
				
			||||||
        const user_infor = { | 
					                files.forEach((item) => { | 
				
			||||||
            id: user.id, | 
					                    listFile.push({ | 
				
			||||||
            name: user.name | 
					                        name: item, | 
				
			||||||
        }; | 
					                        path: `${cdnConfig.uri}/${user.id}${req.body.path}/${item}`, | 
				
			||||||
        console.log(user_infor); | 
					                        isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory() | 
				
			||||||
        let path = `${storageConfig.uri}/${user.id}`; | 
					                    }); | 
				
			||||||
        console.log(path); | 
					                }); | 
				
			||||||
        if (req.body.path) { | 
					            } | 
				
			||||||
            path += req.body.path; | 
					            return res.json({ | 
				
			||||||
        } | 
					                code: 0, | 
				
			||||||
        const listFile = []; | 
					                data: listFile | 
				
			||||||
        // fs.readdir(path, (err, files) => {
 | 
					            }); | 
				
			||||||
        //     if (files && files.length > 0) {
 | 
					        }); | 
				
			||||||
        //         files.forEach((item) => {
 | 
					        // test local
 | 
				
			||||||
        //             listFile.push({
 | 
					        // fs.readdir(path, (err, files) => {
 | 
				
			||||||
        //                 name: item,
 | 
					        //     if (files && files.length > 0) {
 | 
				
			||||||
        //                 path: `${cdnConfig.uri}/${user.id}/${req.body.path}/${item}`,
 | 
					        //         files.forEach((item) => {
 | 
				
			||||||
        //                 isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory(),                
 | 
					        //             listFile.push({
 | 
				
			||||||
        //             });
 | 
					        //                 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; | 
				
			||||||
        }).then(result => { | 
					        /** resize image uploaded */ | 
				
			||||||
            let path = [] | 
					    } catch (ex) { | 
				
			||||||
            result.forEach(data => { | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
                console.log(data.created_by.id); | 
					    } | 
				
			||||||
                // console.log(`${storageConfig.uri}/${data.created_by.id}/${req.body.path}/${data.name}`);
 | 
					}; | 
				
			||||||
                const file = { | 
					
 | 
				
			||||||
                    name: data.name, | 
					/** | 
				
			||||||
                    path: data.url, | 
					 * get file and folder | 
				
			||||||
                    // isFolder: fs.lstatSync(`${storageConfig.uri}/${data.created_by.id}/${req.body.path}/${data.name}`).isDirectory(),
 | 
					 * | 
				
			||||||
                    isFolder: fs.lstatSync(`${storageConfig.uri}/${data.created_by.id}/${req.body.path}/${data.name}`).isDirectory(), | 
					 * @param {Formdata} file | 
				
			||||||
                    download_count : data.download_count | 
					 */ | 
				
			||||||
    
 | 
					exports.create = (req, res, next) => { | 
				
			||||||
                } | 
					    const user = req.user; | 
				
			||||||
                
 | 
					    let dir = `${user.id}`; | 
				
			||||||
                path.push(file);    
 | 
					    const name_folder = cloneDeep(req.body.name).trim(); | 
				
			||||||
            }); | 
					    if (req.body.path) { | 
				
			||||||
            return res.json({ | 
					        dir += req.body.path; | 
				
			||||||
                code: 0, 
 | 
					    } | 
				
			||||||
                data : path | 
					    if (req.body.name) { | 
				
			||||||
            }) | 
					        dir += `/${name_folder}`; | 
				
			||||||
        }).catch(ex => { | 
					    } | 
				
			||||||
            ErrorHandler(ex, req, res, next); | 
					    if (!fs.existsSync(dir)) { | 
				
			||||||
    
 | 
					        uploadAdapter.createFolder({ path: dir }); | 
				
			||||||
        }) | 
					    } | 
				
			||||||
 | 
					    return res.json({ code: 0, message: 'success' }); | 
				
			||||||
       
 | 
					}; | 
				
			||||||
        // test local
 | 
					
 | 
				
			||||||
        // fs.readdir(path, (err, files) => {
 | 
					/** | 
				
			||||||
        //     if (files && files.length > 0) {
 | 
					 * get file and folder | 
				
			||||||
        //         files.forEach((item) => {
 | 
					 * | 
				
			||||||
        //             listFile.push({
 | 
					 * @param {Formdata} file | 
				
			||||||
        //                 name: item,
 | 
					 */ | 
				
			||||||
                    //  path: `${cdnConfig.uri}/${user.id}${req.body.path}/${item}`,
 | 
					exports.update = (req, res, next) => { | 
				
			||||||
 | 
					    try { | 
				
			||||||
        //                 path: `${storageConfig.uri}/${user.id}${req.body.path}/${item}`,
 | 
					        const oldPath = req.body.oldPath.replace(cdnConfig.uri, storageConfig.uri); | 
				
			||||||
        //                 isFolder: fs.lstatSync(`${storageConfig.uri}/${user.id}/${req.body.path}/${item}`).isDirectory()
 | 
					        const newPath = req.body.newPath.replace(cdnConfig.uri, storageConfig.uri); | 
				
			||||||
        //             });
 | 
					
 | 
				
			||||||
        //         });
 | 
					        fs.rename(oldPath, newPath, (err) => { | 
				
			||||||
        //     }
 | 
					            if (err) { | 
				
			||||||
        //     return res.json({
 | 
					                console.log(err); | 
				
			||||||
        //         code: 0,
 | 
					                return res.status(400).json({ code: 400, message: 'lỗi' }); | 
				
			||||||
        //         data: listFile
 | 
					            } | 
				
			||||||
        //     });
 | 
					            return res.json({ code: 0, message: 'success' }); | 
				
			||||||
        // });
 | 
					        }); | 
				
			||||||
 | 
					        return null; | 
				
			||||||
 | 
					    } catch (ex) { | 
				
			||||||
        return null; | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
        /** resize image uploaded */ | 
					    } | 
				
			||||||
    } catch (ex) { | 
					}; | 
				
			||||||
        return ErrorHandel(ex, req, res, next); | 
					
 | 
				
			||||||
    } | 
					
 | 
				
			||||||
}; | 
					exports.delete = (req, res, next) => { | 
				
			||||||
 | 
					    try { | 
				
			||||||
/** | 
					        const user = req.user; | 
				
			||||||
 * get file and folder | 
					        const dir = `${storageConfig.uri_backup}/${user.id}`; | 
				
			||||||
 * | 
					        multer({ dest: `${dir}` }); | 
				
			||||||
 * @param {Formdata} file | 
					        const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); | 
				
			||||||
 */ | 
					        const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup); | 
				
			||||||
exports.create = (req, res, next) => { | 
					        // fs.rm(path, { recursive: true }, err => {
 | 
				
			||||||
    const user = req.user; | 
					        //     if (err) {
 | 
				
			||||||
    let dir = `${user.id}`; | 
					        //         return res.status(400).json({ code: 400, message: 'lỗi', detail: err });
 | 
				
			||||||
    const name_folder = cloneDeep(req.body.name).trim(); | 
					        //     }
 | 
				
			||||||
    if (req.body.path) { | 
					        //     return res.json({ code: 0, message: 'success' });
 | 
				
			||||||
        dir += req.body.path; | 
					        // });
 | 
				
			||||||
    } | 
					        fs.rename(path, newpath, (err) => { | 
				
			||||||
    if (req.body.name) { | 
					            if (err) throw err; | 
				
			||||||
        dir += `/${name_folder}`; | 
					            return res.json({ code: 0, message: 'success' }); | 
				
			||||||
    } | 
					        }); | 
				
			||||||
    if (!fs.existsSync(dir)) { | 
					        return null; | 
				
			||||||
        uploadAdapter.createFolder({ path: dir }); | 
					    } catch (ex) { | 
				
			||||||
    } | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
    return res.json({ code: 0, message: 'success' }); | 
					    } | 
				
			||||||
}; | 
					}; | 
				
			||||||
 | 
					exports.download = async (req, res, next) => { | 
				
			||||||
/** | 
					    try { | 
				
			||||||
 * get file and folder | 
					        const user = req.user; | 
				
			||||||
 * | 
					        const namefile = `${user.name}-${Date.now()}.zip`; | 
				
			||||||
 * @param {Formdata} file | 
					        const dir = `${storageConfig.uri}/download/${user.id}/${namefile}`; | 
				
			||||||
 */ | 
					        const folder = `${storageConfig.uri}/download/${user.id}`; | 
				
			||||||
exports.update = (req, res, next) => { | 
					        multer({ dest: `${folder}` }); | 
				
			||||||
    try { | 
					        await deleteFolderRecursive(folder); | 
				
			||||||
        const oldPath = req.body.oldPath.replace(cdnConfig.uri, storageConfig.uri); | 
					        const output = fs.createWriteStream(dir); | 
				
			||||||
        const newPath = req.body.newPath.replace(cdnConfig.uri, storageConfig.uri); | 
					        const archive = archiver('zip', { | 
				
			||||||
 | 
					            zlib: { level: 9 } // Sets the compression level.
 | 
				
			||||||
        fs.rename(oldPath, newPath, (err) => { | 
					        }); | 
				
			||||||
            if (err) { | 
					
 | 
				
			||||||
                console.log(err); | 
					
 | 
				
			||||||
                return res.status(400).json({ code: 400, message: 'lỗi' }); | 
					        archive.pipe(output); | 
				
			||||||
            } | 
					        if (req.body.data) { | 
				
			||||||
            return res.json({ code: 0, message: 'success' }); | 
					            req.body.data.forEach((e) => { | 
				
			||||||
        }); | 
					                const path = e.path.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ '); | 
				
			||||||
        return null; | 
					                // const path = e.path.replace(cdnConfig.uri, storageConfig.uri);
 | 
				
			||||||
    } catch (ex) { | 
					                console.log('path', path); | 
				
			||||||
        return ErrorHandel(ex, req, res, next); | 
					                // const download = path.split("/");
 | 
				
			||||||
    } | 
					                // download.splice( download.indexOf(`${user.id}`), 0, "download");
 | 
				
			||||||
}; | 
					                // const final_path = download.join("/");
 | 
				
			||||||
 | 
					                if (e.isFolder) { | 
				
			||||||
 | 
					                    archive.directory(path, e.name); | 
				
			||||||
exports.delete = (req, res, next) => { | 
					                } else { | 
				
			||||||
    try { | 
					                    archive.file(path, { name: e.name }); | 
				
			||||||
        const user = req.user; | 
					                } | 
				
			||||||
        const dir = `${storageConfig.uri_backup}/${user.id}`; | 
					            }); | 
				
			||||||
        multer({ dest: `${dir}` }); | 
					        } | 
				
			||||||
        const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); | 
					
 | 
				
			||||||
        const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup); | 
					        archive.finalize(); | 
				
			||||||
        // fs.rm(path, { recursive: true }, err => {
 | 
					        return res.json({ | 
				
			||||||
        //     if (err) {
 | 
					            code: 0, | 
				
			||||||
        //         return res.status(400).json({ code: 400, message: 'lỗi', detail: err });
 | 
					            data: { | 
				
			||||||
        //     }
 | 
					                name: namefile, | 
				
			||||||
        //     return res.json({ code: 0, message: 'success' });
 | 
					                path: `${cdnConfig.uri}/download/${user.id}/${namefile}`, | 
				
			||||||
        // });
 | 
					            } | 
				
			||||||
        fs.rename(path, newpath, (err) => { | 
					        }); | 
				
			||||||
            if (err) throw err; | 
					    } catch (ex) { | 
				
			||||||
            return res.json({ code: 0, message: 'success' }); | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
        }); | 
					    } | 
				
			||||||
        return null; | 
					}; | 
				
			||||||
    } catch (ex) { | 
					
 | 
				
			||||||
        return ErrorHandel(ex, req, res, next); | 
					
 | 
				
			||||||
    } | 
					exports.forceDelete = (req, res, next) => { | 
				
			||||||
}; | 
					    try { | 
				
			||||||
exports.download = async (req, res, next) => { | 
					        const path = req.body.path.replace(cdnConfig.uri, storageConfig.uri); | 
				
			||||||
    try { | 
					        // const newpath = req.body.path.replace(cdnConfig.uri, storageConfig.uri_backup);
 | 
				
			||||||
        
 | 
					        fs.rm(path, { recursive: true }, err => { | 
				
			||||||
        const user = req.user; | 
					            if (err) { | 
				
			||||||
        const namefile = `${user.name}-${Date.now()}.zip`; | 
					                return res.status(400).json({ code: 400, message: 'lỗi', detail: err }); | 
				
			||||||
        const dir = `${storageConfig.uri}/download/${user.id}/${namefile}`; | 
					            } | 
				
			||||||
        const folder = `${storageConfig.uri}/download/${user.id}`; | 
					            return res.json({ code: 0, message: 'success' }); | 
				
			||||||
        multer({ dest: `${folder}` }); | 
					        }); | 
				
			||||||
        await deleteFolderRecursive(folder); | 
					
 | 
				
			||||||
        const output = fs.createWriteStream(dir); | 
					        return null; | 
				
			||||||
        const archive = archiver('zip', { | 
					    } catch (ex) { | 
				
			||||||
            zlib: { level: 9 } // Sets the compression level.
 | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
        }); | 
					    } | 
				
			||||||
 | 
					}; | 
				
			||||||
        const user_infor = { | 
					
 | 
				
			||||||
            id: user.id, | 
					exports.deleteMultiple = (req, res, next) => { | 
				
			||||||
            name: user.name | 
					    try { | 
				
			||||||
        } | 
					        const user = req.user; | 
				
			||||||
        archive.pipe(output); | 
					        const dir = `${storageConfig.uri_backup}/${user.id}/${Date.now()}`; | 
				
			||||||
        if (req.body.data) { | 
					        multer({ dest: `${dir}` }); | 
				
			||||||
            req.body.data.forEach( async (e) => { | 
					        if (req.body.data) { | 
				
			||||||
                // const path = e.path.replace(cdnConfig.uri, storageConfig.uri).replace(/ /g, '\\ ');
 | 
					            req.body.data.forEach((e) => { | 
				
			||||||
                // // // const path = e.path.replace(cdnConfig.uri, storageConfig.uri);
 | 
					                const path = e.path.replace(cdnConfig.uri, storageConfig.uri); | 
				
			||||||
                // console.log('path: ', path);
 | 
					                let newpath = e.path.replace(cdnConfig.uri, storageConfig.uri_backup); | 
				
			||||||
                let downnload_count_list = new Map(); | 
					                const split = newpath.split('/'); | 
				
			||||||
 | 
					                newpath = `${dir}/${split[split.length - 1]}`; | 
				
			||||||
                await File.findOne({ | 
					                fs.rename(path, newpath, (err) => { | 
				
			||||||
                    where: { 
 | 
					                    if (err) throw err; | 
				
			||||||
                        name: e.name, | 
					                    return { code: 0, message: 'success' }; | 
				
			||||||
                        url : e.path, | 
					                }); | 
				
			||||||
                        created_by: user_infor, | 
					            }); | 
				
			||||||
                        is_active : true | 
					        } | 
				
			||||||
                    } | 
					        return res.json({ code: 0, message: 'success' }); | 
				
			||||||
                }).then(result => { | 
					    } catch (ex) { | 
				
			||||||
                    // plus one to the download count when download each selected file
 | 
					        return ErrorHandel(ex, req, res, next); | 
				
			||||||
                    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,190 +1,189 @@ | 
				
			|||||||
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
 | 
				
			||||||
    console.log(req.body); | 
					    await User.create(req.body) | 
				
			||||||
    await User.create(req.body) | 
					        .then(data => { | 
				
			||||||
        .then(data => { | 
					            uploadAdapter.createDefaultFolder({ id: data.id }); | 
				
			||||||
            uploadAdapter.createDefaultFolder({ id: data.id }); | 
					            res.json({ | 
				
			||||||
            res.json({ | 
					                code: 0, | 
				
			||||||
                code: 0, | 
					                message: messages.CREATE_SUCCESS, | 
				
			||||||
                message: messages.CREATE_SUCCESS, | 
					                data: User.transform(data) | 
				
			||||||
                data: User.transform(data) | 
					            }); | 
				
			||||||
            }); | 
					        }).catch(ex => { | 
				
			||||||
        }).catch(ex => { | 
					            ErrorHandler(ex, req, res, next); | 
				
			||||||
            ErrorHandler(ex, req, res, next); | 
					        }); | 
				
			||||||
        }); | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * List | 
				
			||||||
 * List | 
					 * | 
				
			||||||
 * | 
					 * @public | 
				
			||||||
 * @public | 
					 * @param {StorySchema} query | 
				
			||||||
 * @param {StorySchema} query | 
					 * @returns {Promise<StorySchema[]>, APIException>} | 
				
			||||||
 * @returns {Promise<StorySchema[]>, APIException>} | 
					 */ | 
				
			||||||
 */ | 
					exports.list = async (req, res, next) => { | 
				
			||||||
exports.list = async (req, res, next) => { | 
					    req.query.services = User.Services.USER; | 
				
			||||||
    req.query.services = User.Services.USER; | 
					    // console.log(req.query.services);
 | 
				
			||||||
    // console.log(req.query.services);
 | 
					    // User.list( {
 | 
				
			||||||
    // User.list( {
 | 
					    //     service : "user",
 | 
				
			||||||
    //     service : "user",
 | 
					    //     is_active: true
 | 
				
			||||||
    //     is_active: true
 | 
					    // }
 | 
				
			||||||
    // }
 | 
					    // ).then(result => {
 | 
				
			||||||
    // ).then(result => {
 | 
					    //     res.json({
 | 
				
			||||||
    //     res.json({
 | 
					    //         code: 0,
 | 
				
			||||||
    //         code: 0,
 | 
					    //         count: req.totalRecords,
 | 
				
			||||||
    //         count: req.totalRecords,
 | 
					    //         data: result.map(
 | 
				
			||||||
    //         data: result.map(
 | 
					    //             x => User.transform(x)
 | 
				
			||||||
    //             x => User.transform(x)
 | 
					    //         )
 | 
				
			||||||
    //         )
 | 
					    //     });
 | 
				
			||||||
    //     });
 | 
					    // }).catch(ex => {
 | 
				
			||||||
    // }).catch(ex => {
 | 
					    //     ErrorHandler(ex, req, res, next);
 | 
				
			||||||
    //     ErrorHandler(ex, req, res, next);
 | 
					    // });
 | 
				
			||||||
    // });
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return User.findAll({ | 
				
			||||||
    return User.findAll({ | 
					        where : { | 
				
			||||||
        where : { | 
					            service : "user", | 
				
			||||||
            service : "user", | 
					            is_active: true | 
				
			||||||
            is_active: true | 
					        } | 
				
			||||||
        } | 
					    }).then(result => { | 
				
			||||||
    }).then(result => { | 
					            res.json({ | 
				
			||||||
            res.json({ | 
					                code: 0, | 
				
			||||||
                code: 0, | 
					                count: req.totalRecords, | 
				
			||||||
                count: req.totalRecords, | 
					                data: result.map( | 
				
			||||||
                data: result.map( | 
					                 x => User.transform(x) | 
				
			||||||
                 x => User.transform(x) | 
					             ) | 
				
			||||||
             ) | 
					            }); | 
				
			||||||
            }); | 
					        }).catch(ex => { | 
				
			||||||
        }).catch(ex => { | 
					            ErrorHandler(ex, req, res, next); | 
				
			||||||
            ErrorHandler(ex, req, res, next); | 
					        }); | 
				
			||||||
        }); | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Detail | 
				
			||||||
 * Detail | 
					 * | 
				
			||||||
 * | 
					 * @public | 
				
			||||||
 * @public | 
					 * @param {params} userId, | 
				
			||||||
 * @param {params} userId, | 
					 * @returns {Promise<StorySchema>, APIException>} | 
				
			||||||
 * @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 | 
				
			||||||
 * @public | 
					 * @param {params} userId | 
				
			||||||
 * @param {params} userId | 
					 * @returns {Promise<any>, APIException>} | 
				
			||||||
 * @returns {Promise<any>, APIException>} | 
					 */ | 
				
			||||||
 */ | 
					exports.update = async (req, res, next) => { | 
				
			||||||
exports.update = async (req, res, next) => { | 
					    const { user } = req.locals; | 
				
			||||||
    const { user } = req.locals; | 
					    const dataChanged =  User.getChangedProperties(req.body); | 
				
			||||||
    const dataChanged =  User.getChangedProperties(req.body); | 
					    const new_properties = pick(req.body, dataChanged); | 
				
			||||||
    const new_properties = pick(req.body, dataChanged); | 
					    // const updateUser = Object.assign(
 | 
				
			||||||
    // const updateUser = Object.assign(
 | 
					    //     user,
 | 
				
			||||||
    //     user,
 | 
					    //     pick(req.body, dataChanged)
 | 
				
			||||||
    //     pick(req.body, dataChanged)
 | 
					    // );
 | 
				
			||||||
    // );
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // const currentUser = await User.get(user.id)
 | 
				
			||||||
    // const currentUser = await User.get(user.id)
 | 
					    // console.log(dataChanged);
 | 
				
			||||||
    // console.log(dataChanged);
 | 
					
 | 
				
			||||||
 | 
					    return User.update( | 
				
			||||||
    return User.update( | 
					        new_properties, | 
				
			||||||
        new_properties, | 
					        { | 
				
			||||||
        { | 
					            where: { | 
				
			||||||
            where: { | 
					                id: user.id | 
				
			||||||
                id: user.id | 
					            } | 
				
			||||||
            } | 
					        } | 
				
			||||||
        } | 
					    ).then(() => { | 
				
			||||||
    ).then(() => { | 
					        res.json({ | 
				
			||||||
        res.json({ | 
					            code: 0, | 
				
			||||||
            code: 0, | 
					            message: messages.UPDATE_SUCCESS, | 
				
			||||||
            message: messages.UPDATE_SUCCESS, | 
					            // dataChanged: dataChanged
 | 
				
			||||||
            // dataChanged: dataChanged
 | 
					        }); | 
				
			||||||
        }); | 
					    }).catch(ex => { | 
				
			||||||
    }).catch(ex => { | 
					        ErrorHandler(ex, req, res, next); | 
				
			||||||
        ErrorHandler(ex, req, res, next); | 
					    }); | 
				
			||||||
    }); | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * delete | 
				
			||||||
 * delete | 
					 * | 
				
			||||||
 * | 
					 * @public | 
				
			||||||
 * @public | 
					 * @param {params} userId | 
				
			||||||
 * @param {params} userId | 
					 * @returns {Promise<any>, APIException>} | 
				
			||||||
 * @returns {Promise<any>, APIException>} | 
					 */ | 
				
			||||||
 */ | 
					exports.delete = async (req, res, next) => { | 
				
			||||||
exports.delete = async (req, res, next) => { | 
					    const { user } = req.locals; | 
				
			||||||
    const { user } = req.locals; | 
					    // const new_user = Object.assign(
 | 
				
			||||||
    // const new_user = Object.assign(
 | 
					    //     user, 
 | 
				
			||||||
    //     user, 
 | 
					    //     isactive : false
 | 
				
			||||||
    //     isactive : false
 | 
					    // )
 | 
				
			||||||
    // )
 | 
					
 | 
				
			||||||
 | 
					    return User.update( | 
				
			||||||
    return User.update( | 
					        { is_active: false}, | 
				
			||||||
        { is_active: false}, | 
					        { | 
				
			||||||
        { | 
					            where: { | 
				
			||||||
            where: { | 
					                id: user.id | 
				
			||||||
                id: user.id | 
					            } | 
				
			||||||
            } | 
					        } | 
				
			||||||
        } | 
					    ).then( () => { | 
				
			||||||
    ).then( () => { | 
					        res.json({ | 
				
			||||||
        res.json({ | 
					            code: 0, | 
				
			||||||
            code: 0, | 
					            message: messages.REMOVE_SUCCESS | 
				
			||||||
            message: messages.REMOVE_SUCCESS | 
					        }); | 
				
			||||||
        }); | 
					    }).catch(ex => { | 
				
			||||||
    }).catch(ex => { | 
					        ErrorHandler(ex, req, res, next); | 
				
			||||||
        ErrorHandler(ex, req, res, next); | 
					    }); | 
				
			||||||
    }); | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					exports.getStaffPermission = async (req, res, next) => { | 
				
			||||||
exports.getStaffPermission = async (req, res, next) => { | 
					    const { story } = req.locals; | 
				
			||||||
    const { story } = req.locals; | 
					    return res.json({ | 
				
			||||||
    return res.json({ | 
					        code: 0, | 
				
			||||||
        code: 0, | 
					        data: story | 
				
			||||||
        data: story | 
					    }); | 
				
			||||||
    }); | 
					}; | 
				
			||||||
}; | 
					exports.updatePassword = async(req,res,next) => { 
 | 
				
			||||||
exports.updatePassword = async(req,res,next) => { 
 | 
					    const {new_password} = req.body; | 
				
			||||||
    const {new_password} = req.body; | 
					    const {user} = req.locals; | 
				
			||||||
    const {user} = req.locals; | 
					    // console.log(user);
 | 
				
			||||||
    // console.log(user);
 | 
					    if (user) { 
 | 
				
			||||||
    if (user) { 
 | 
					        const rounds = 10; | 
				
			||||||
        const rounds = 10; | 
					        const new_pass = await hash(new_password, rounds); 
 | 
				
			||||||
        const new_pass = await hash(new_password, rounds); 
 | 
					        return User.update( | 
				
			||||||
        return User.update( | 
					            {password: new_pass}, | 
				
			||||||
            {password: new_pass}, | 
					            { | 
				
			||||||
            { | 
					                where: { | 
				
			||||||
                where: { | 
					                    id: user.id | 
				
			||||||
                    id: user.id | 
					                } | 
				
			||||||
                } | 
					            }, | 
				
			||||||
            }, | 
					        ).then( async () => { | 
				
			||||||
        ).then( async () => { | 
					            res.json({               
 | 
				
			||||||
            res.json({               
 | 
					                code: 0, | 
				
			||||||
                code: 0, | 
					                message: messages.UPDATE_SUCCESS | 
				
			||||||
                message: messages.UPDATE_SUCCESS | 
					            }); | 
				
			||||||
            }); | 
					        }).catch(ex => { | 
				
			||||||
        }).catch(ex => { | 
					            ErrorHandler(ex, req, res, next); | 
				
			||||||
            ErrorHandler(ex, req, res, next); | 
					        }); | 
				
			||||||
        }); | 
					    };   
 | 
				
			||||||
    };   
 | 
					 | 
				
			||||||
}; | 
					}; | 
				
			||||||
@ -1,23 +1,17 @@ | 
				
			|||||||
 | 
					
 | 
				
			||||||
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,42 +1,38 @@ | 
				
			|||||||
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 { uploader } from '../../../common/services/adapters/upload-adapter'; | 
					import controller from '../../controllers/v1/image.controller'; | 
				
			||||||
import controller from '../../controllers/v1/image.controller'; | 
					// import {
 | 
				
			||||||
// import {
 | 
					//     uploadValidation
 | 
				
			||||||
//     uploadValidation
 | 
					// } from '../../validations/v1/image.validation';
 | 
				
			||||||
// } from '../../validations/v1/image.validation';
 | 
					
 | 
				
			||||||
 | 
					const router = express.Router(); | 
				
			||||||
const router = express.Router(); | 
					
 | 
				
			||||||
 | 
					router | 
				
			||||||
router | 
					    .route('/upload-single') | 
				
			||||||
    .route('/upload-single') | 
					    .post( | 
				
			||||||
    .post( | 
					        // authorize([Permissions.IMAGE_UPLOAD]),
 | 
				
			||||||
        // authorize([Permissions.IMAGE_UPLOAD]),
 | 
					        // validate(uploadValidation),
 | 
				
			||||||
        // validate(uploadValidation),
 | 
					        uploader.single('file'), | 
				
			||||||
        uploader.single('file'), | 
					        controller.uploadSingle | 
				
			||||||
        controller.uploadSingle | 
					    ); | 
				
			||||||
    ); | 
					
 | 
				
			||||||
 | 
					router | 
				
			||||||
router | 
					    .route('/upload-multiple') | 
				
			||||||
    .route('/upload-multiple/:id') | 
					    .post( | 
				
			||||||
    .post( | 
					        // authorize([Permissions.IMAGE_UPLOAD]),
 | 
				
			||||||
        // authorize([Permissions.IMAGE_UPLOAD]),
 | 
					        // validate(uploadValidation),
 | 
				
			||||||
        // validate(uploadValidation),
 | 
					        uploader.array('file', 100), | 
				
			||||||
        userMiddleware.load, | 
					        controller.uploadMultiple | 
				
			||||||
        uploader.array('file', 100), | 
					    ); | 
				
			||||||
        controller.uploadMultiple | 
					router | 
				
			||||||
    ); | 
					    .route('/upload-file') | 
				
			||||||
router | 
					    .post( | 
				
			||||||
    .route('/upload-file') | 
					        // authorize([Permissions.IMAGE_UPLOAD]),
 | 
				
			||||||
    .post( | 
					        controller.uploadFile | 
				
			||||||
        // authorize([Permissions.IMAGE_UPLOAD]),
 | 
					    ); | 
				
			||||||
        controller.uploadFile | 
					
 | 
				
			||||||
    ); | 
					export default router; | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default router; | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,54 +1,51 @@ | 
				
			|||||||
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,409 +1,408 @@ | 
				
			|||||||
/* 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, | 
				
			||||||
        timestamps: false, | 
					        schema: serviceName, | 
				
			||||||
        schema: serviceName, | 
					        sequelize: sequelize, | 
				
			||||||
        sequelize: sequelize, | 
					        modelName: 'file_config', | 
				
			||||||
        modelName: 'file_config', | 
					        tableName: 'tbl_file_configs' | 
				
			||||||
        tableName: 'tbl_file_configs' | 
					    } | 
				
			||||||
    } | 
					); | 
				
			||||||
); | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Register event emiter | 
				
			||||||
 * Register event emiter | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.Events = { | 
				
			||||||
FileConfig.Events = { | 
					    FILE_CONFIG_CREATED: `${serviceName}.file-config.created`, | 
				
			||||||
    FILE_CONFIG_CREATED: `${serviceName}.file-config.created`, | 
					    FILE_CONFIG_UPDATED: `${serviceName}.file-config.updated`, | 
				
			||||||
    FILE_CONFIG_UPDATED: `${serviceName}.file-config.updated`, | 
					    FILE_CONFIG_DELETED: `${serviceName}.file-config.deleted`, | 
				
			||||||
    FILE_CONFIG_DELETED: `${serviceName}.file-config.deleted`, | 
					}; | 
				
			||||||
}; | 
					FileConfig.EVENT_SOURCE = `${serviceName}.file-config`; | 
				
			||||||
FileConfig.EVENT_SOURCE = `${serviceName}.file-config`; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Add your | 
				
			||||||
 * Add your | 
					 * - pre-save hooks | 
				
			||||||
 * - pre-save hooks | 
					 * - validations | 
				
			||||||
 * - validations | 
					 * - virtuals | 
				
			||||||
 * - virtuals | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.addHook('afterCreate', () => { }); | 
				
			||||||
FileConfig.addHook('afterCreate', () => { }); | 
					
 | 
				
			||||||
 | 
					FileConfig.addHook('afterUpdate', () => { }); | 
				
			||||||
FileConfig.addHook('afterUpdate', () => { }); | 
					
 | 
				
			||||||
 | 
					FileConfig.addHook('afterDestroy', () => { }); | 
				
			||||||
FileConfig.addHook('afterDestroy', () => { }); | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Load query | 
				
			||||||
 * Load query | 
					 * @param {*} params | 
				
			||||||
 * @param {*} params | 
					 */ | 
				
			||||||
 */ | 
					function filterConditions(params) { | 
				
			||||||
function filterConditions(params) { | 
					    const options = omitBy(params, isNil); | 
				
			||||||
    const options = omitBy(params, isNil); | 
					    options.is_active = true; | 
				
			||||||
    options.is_active = true; | 
					
 | 
				
			||||||
 | 
					    // TODO: load condition
 | 
				
			||||||
    // TODO: load condition
 | 
					    if (options.name) { | 
				
			||||||
    if (options.name) { | 
					        options.name = { | 
				
			||||||
        options.name = { | 
					            [Op.iLike]: `%${options.name}%` | 
				
			||||||
            [Op.iLike]: `%${options.name}%` | 
					        }; | 
				
			||||||
        }; | 
					    } | 
				
			||||||
    } | 
					
 | 
				
			||||||
 | 
					    return options; | 
				
			||||||
    return options; | 
					} | 
				
			||||||
} | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Load sort query | 
				
			||||||
 * Load sort query | 
					 * @param {*} sort_by | 
				
			||||||
 * @param {*} sort_by | 
					 * @param {*} order_by | 
				
			||||||
 * @param {*} order_by | 
					 */ | 
				
			||||||
 */ | 
					function sortConditions({ sort_by, order_by }) { | 
				
			||||||
function sortConditions({ sort_by, order_by }) { | 
					    let sort = null; | 
				
			||||||
    let sort = null; | 
					    switch (sort_by) { | 
				
			||||||
    switch (sort_by) { | 
					        case 'created_at': | 
				
			||||||
        case 'created_at': | 
					            sort = ['created_at', order_by]; | 
				
			||||||
            sort = ['created_at', order_by]; | 
					            break; | 
				
			||||||
            break; | 
					        case 'updated_at': | 
				
			||||||
        case 'updated_at': | 
					            sort = ['updated_at', order_by]; | 
				
			||||||
            sort = ['updated_at', order_by]; | 
					            break; | 
				
			||||||
            break; | 
					        default: sort = ['created_at', 'DESC']; | 
				
			||||||
        default: sort = ['created_at', 'DESC']; | 
					            break; | 
				
			||||||
            break; | 
					    } | 
				
			||||||
    } | 
					    return sort; | 
				
			||||||
    return sort; | 
					} | 
				
			||||||
} | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Transform postgres model to expose object | 
				
			||||||
 * Transform postgres model to expose object | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.transform = (params) => { | 
				
			||||||
FileConfig.transform = (params) => { | 
					    const transformed = {}; | 
				
			||||||
    const transformed = {}; | 
					    const fields = [ | 
				
			||||||
    const fields = [ | 
					        'id', | 
				
			||||||
        'id', | 
					        'name', | 
				
			||||||
        'name', | 
					        'type', | 
				
			||||||
        'type', | 
					        'group', | 
				
			||||||
        'group', | 
					        'config', | 
				
			||||||
        'config', | 
					        'created_by' | 
				
			||||||
        'created_by' | 
					    ]; | 
				
			||||||
    ]; | 
					    fields.forEach((field) => { | 
				
			||||||
    fields.forEach((field) => { | 
					        transformed[field] = params[field]; | 
				
			||||||
        transformed[field] = params[field]; | 
					    }); | 
				
			||||||
    }); | 
					
 | 
				
			||||||
 | 
					    // pipe date
 | 
				
			||||||
    // pipe date
 | 
					    const dateFields = [ | 
				
			||||||
    const dateFields = [ | 
					        'created_at', | 
				
			||||||
        'created_at', | 
					        'updated_at' | 
				
			||||||
        'updated_at' | 
					    ]; | 
				
			||||||
    ]; | 
					    dateFields.forEach((field) => { | 
				
			||||||
    dateFields.forEach((field) => { | 
					        if (params[field]) { | 
				
			||||||
        if (params[field]) { | 
					            transformed[field] = moment(params[field]).unix(); | 
				
			||||||
            transformed[field] = moment(params[field]).unix(); | 
					        } else { | 
				
			||||||
        } else { | 
					            transformed[field] = null; | 
				
			||||||
            transformed[field] = null; | 
					        } | 
				
			||||||
        } | 
					    }); | 
				
			||||||
    }); | 
					
 | 
				
			||||||
 | 
					    return transformed; | 
				
			||||||
    return transformed; | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Get all changed properties | 
				
			||||||
 * Get all changed properties | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.getChangedProperties = ({ newModel, oldModel }) => { | 
				
			||||||
FileConfig.getChangedProperties = ({ newModel, oldModel }) => { | 
					    const changedProperties = []; | 
				
			||||||
    const changedProperties = []; | 
					    const allChangableProperties = [ | 
				
			||||||
    const allChangableProperties = [ | 
					        'name', | 
				
			||||||
        'name', | 
					        'type', | 
				
			||||||
        'type', | 
					        'group', | 
				
			||||||
        'group', | 
					        'config', | 
				
			||||||
        'config', | 
					        'status', | 
				
			||||||
        'status', | 
					        'status_name' | 
				
			||||||
        'status_name' | 
					    ]; | 
				
			||||||
    ]; | 
					    if (!oldModel) { | 
				
			||||||
    if (!oldModel) { | 
					        return allChangableProperties; | 
				
			||||||
        return allChangableProperties; | 
					    } | 
				
			||||||
    } | 
					
 | 
				
			||||||
 | 
					    allChangableProperties.forEach((field) => { | 
				
			||||||
    allChangableProperties.forEach((field) => { | 
					        if ( | 
				
			||||||
        if ( | 
					            !isUndefined(newModel[field]) && | 
				
			||||||
            !isUndefined(newModel[field]) && | 
					            !isEqual(newModel[field], oldModel[field]) | 
				
			||||||
            !isEqual(newModel[field], oldModel[field]) | 
					        ) { | 
				
			||||||
        ) { | 
					            changedProperties.push(field); | 
				
			||||||
            changedProperties.push(field); | 
					        } | 
				
			||||||
        } | 
					    }); | 
				
			||||||
    }); | 
					
 | 
				
			||||||
 | 
					    return changedProperties; | 
				
			||||||
    return changedProperties; | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Detail | 
				
			||||||
 * Detail | 
					 * | 
				
			||||||
 * | 
					 * @public | 
				
			||||||
 * @public | 
					 * @param {string} group | 
				
			||||||
 * @param {string} group | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.get = async (operation) => { | 
				
			||||||
FileConfig.get = async (operation) => { | 
					    try { | 
				
			||||||
    try { | 
					        const data = await FileConfig.findOne({ | 
				
			||||||
        const data = await FileConfig.findOne({ | 
					            where: { | 
				
			||||||
            where: { | 
					                type: operation.type, | 
				
			||||||
                type: operation.type, | 
					                group: operation.group, | 
				
			||||||
                group: operation.group, | 
					                is_active: true | 
				
			||||||
                is_active: true | 
					            } | 
				
			||||||
            } | 
					        }); | 
				
			||||||
        }); | 
					        if (!data) { | 
				
			||||||
        if (!data) { | 
					            throw new APIError({ | 
				
			||||||
            throw new APIError({ | 
					                status: httpStatus.NOT_FOUND, | 
				
			||||||
                status: httpStatus.NOT_FOUND, | 
					                message: 'Không tìm thấy file!' | 
				
			||||||
                message: 'Không tìm thấy file!' | 
					            }); | 
				
			||||||
            }); | 
					        } | 
				
			||||||
        } | 
					        return data; | 
				
			||||||
        return data; | 
					    } catch (ex) { | 
				
			||||||
    } catch (ex) { | 
					        throw 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} skip - Number of users to be skipped. | 
					 * @param {number} limit - Limit number of users to be returned. | 
				
			||||||
 * @param {number} limit - Limit number of users to be returned. | 
					 * @returns {Promise<Supplider[]>} | 
				
			||||||
 * @returns {Promise<Supplider[]>} | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.list = async ({ | 
				
			||||||
FileConfig.list = async ({ | 
					    name, | 
				
			||||||
    name, | 
					
 | 
				
			||||||
 | 
					    // sort
 | 
				
			||||||
    // sort
 | 
					    sort_by, | 
				
			||||||
    sort_by, | 
					    order_by, | 
				
			||||||
    order_by, | 
					    skip = 0, | 
				
			||||||
    skip = 0, | 
					    limit = 20, | 
				
			||||||
    limit = 20, | 
					}) => { | 
				
			||||||
}) => { | 
					    const options = filterConditions({ | 
				
			||||||
    const options = filterConditions({ | 
					        name | 
				
			||||||
        name | 
					    }); | 
				
			||||||
    }); | 
					    const sort = sortConditions({ sort_by, order_by }); | 
				
			||||||
    const sort = sortConditions({ sort_by, order_by }); | 
					    return FileConfig.findAll({ | 
				
			||||||
    return FileConfig.findAll({ | 
					        where: options, | 
				
			||||||
        where: options, | 
					        order: [sort], | 
				
			||||||
        order: [sort], | 
					        offset: skip, | 
				
			||||||
        offset: skip, | 
					        limit: limit | 
				
			||||||
        limit: limit | 
					    }); | 
				
			||||||
    }); | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Total records. | 
				
			||||||
 * Total records. | 
					 * | 
				
			||||||
 * | 
					 * @param {number} skip - Number of users to be skipped. | 
				
			||||||
 * @param {number} skip - Number of users to be skipped. | 
					 * @param {number} limit - Limit number of users to be returned. | 
				
			||||||
 * @param {number} limit - Limit number of users to be returned. | 
					 * @returns {Promise<Number>} | 
				
			||||||
 * @returns {Promise<Number>} | 
					 */ | 
				
			||||||
 */ | 
					FileConfig.totalRecords = ({ | 
				
			||||||
FileConfig.totalRecords = ({ | 
					    name | 
				
			||||||
    name | 
					}) => { | 
				
			||||||
}) => { | 
					    const options = filterConditions({ | 
				
			||||||
    const options = filterConditions({ | 
					        name | 
				
			||||||
        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,278 +1,256 @@ | 
				
			|||||||
/* 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 postgres from '../../config/postgres'; | 
					import { serviceName } from '../../config/vars'; | 
				
			||||||
import APIError from '../utils/APIException'; | 
					import postgres from '../../config/postgres'; | 
				
			||||||
 | 
					import APIError from '../utils/APIException'; | 
				
			||||||
/** | 
					
 | 
				
			||||||
 * Create connection | 
					/** | 
				
			||||||
 */ | 
					 * Create connection | 
				
			||||||
const { sequelize } = postgres; | 
					 */ | 
				
			||||||
class File extends Model { } | 
					const { sequelize } = postgres; | 
				
			||||||
 | 
					class File extends Model { } | 
				
			||||||
const PUBLIC_FIELDS = [ | 
					
 | 
				
			||||||
    'name', | 
					const PUBLIC_FIELDS = [ | 
				
			||||||
    'title', | 
					    'name', | 
				
			||||||
    'payload' | 
					    'title', | 
				
			||||||
]; | 
					    'payload' | 
				
			||||||
 | 
					]; | 
				
			||||||
/** | 
					
 | 
				
			||||||
 * File Schema | 
					/** | 
				
			||||||
 * @public | 
					 * File Schema | 
				
			||||||
 */ | 
					 * @public | 
				
			||||||
File.init( | 
					 */ | 
				
			||||||
    { | 
					File.init( | 
				
			||||||
        id: { | 
					    { | 
				
			||||||
            type: DataTypes.INTEGER, | 
					        id: { | 
				
			||||||
            autoIncrement: true, | 
					            type: DataTypes.INTEGER, | 
				
			||||||
            primaryKey: true | 
					            autoIncrement: true, | 
				
			||||||
        }, | 
					            primaryKey: true | 
				
			||||||
        url: { | 
					        }, | 
				
			||||||
            type: DataTypes.STRING(255), | 
					        name: { | 
				
			||||||
            allowNull: false | 
					            type: DataTypes.STRING(255), | 
				
			||||||
        }, | 
					            allowNull: false | 
				
			||||||
        name: { | 
					        }, | 
				
			||||||
            type: DataTypes.STRING(255), | 
					        url: { | 
				
			||||||
            defaultValue: null | 
					            type: DataTypes.STRING(255), | 
				
			||||||
        }, | 
					            allowNull: false | 
				
			||||||
        title: { | 
					        }, | 
				
			||||||
            type: DataTypes.STRING(255), | 
					        download_count: { | 
				
			||||||
            defaultValue: null | 
					            type: DataTypes.NUMBER, | 
				
			||||||
        }, | 
					            allowNull: true, | 
				
			||||||
        payload: { | 
					            defaultValue: 0 | 
				
			||||||
            type: DataTypes.JSONB, | 
					        } | 
				
			||||||
            defaultValue: null // id | code | name
 | 
					
 | 
				
			||||||
        }, | 
					    }, | 
				
			||||||
 | 
					    { | 
				
			||||||
        // manager
 | 
					        timestamps: false, | 
				
			||||||
        is_active: { | 
					        sequelize: sequelize, | 
				
			||||||
            type: DataTypes.BOOLEAN, | 
					        schema: serviceName, | 
				
			||||||
            defaultValue: true | 
					        modelName: 'file', | 
				
			||||||
        }, | 
					        tableName: 'tbl_files' | 
				
			||||||
        created_at: { | 
					    } | 
				
			||||||
            type: DataTypes.DATE, | 
					); | 
				
			||||||
            defaultValue: DataTypes.NOW | 
					
 | 
				
			||||||
        }, | 
					/** | 
				
			||||||
        updated_at: { | 
					 * Register event emiter | 
				
			||||||
            type: DataTypes.DATE, | 
					 */ | 
				
			||||||
            defaultValue: DataTypes.NOW | 
					File.Events = { | 
				
			||||||
        }, | 
					    File_CREATED: `${serviceName}.file.created`, | 
				
			||||||
        created_by: { | 
					    File_UPDATED: `${serviceName}.file.updated`, | 
				
			||||||
            type: DataTypes.JSONB, | 
					    File_DELETED: `${serviceName}.file.deleted`, | 
				
			||||||
            defaultValue: null // id | name
 | 
					}; | 
				
			||||||
        }, | 
					File.EVENT_SOURCE = `${serviceName}.file`; | 
				
			||||||
        download_count: { | 
					
 | 
				
			||||||
            type: DataTypes.INTEGER, | 
					/** | 
				
			||||||
            defaultValue: 0 | 
					 * Add your | 
				
			||||||
        } | 
					 * - pre-save hooks | 
				
			||||||
    }, | 
					 * - validations | 
				
			||||||
    { | 
					 * - virtuals | 
				
			||||||
        timestamps: false, | 
					 */ | 
				
			||||||
        sequelize: sequelize, | 
					File.addHook('afterCreate', () => { }); | 
				
			||||||
        schema: serviceName, | 
					
 | 
				
			||||||
        modelName: 'file', | 
					File.addHook('afterUpdate', () => { }); | 
				
			||||||
        tableName: 'tbl_files' | 
					
 | 
				
			||||||
    } | 
					File.addHook('afterDestroy', () => { }); | 
				
			||||||
); | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Load query | 
				
			||||||
 * Register event emiter | 
					 * @param {*} params | 
				
			||||||
 */ | 
					 */ | 
				
			||||||
File.Events = { | 
					function filterConditions(params) { | 
				
			||||||
    File_CREATED: `${serviceName}.file.created`, | 
					    const options = omitBy(params, isNil); | 
				
			||||||
    File_UPDATED: `${serviceName}.file.updated`, | 
					    options.is_active = true; | 
				
			||||||
    File_DELETED: `${serviceName}.file.deleted`, | 
					
 | 
				
			||||||
}; | 
					    // TODO: load condition
 | 
				
			||||||
File.EVENT_SOURCE = `${serviceName}.file`; | 
					    if (options.name) { | 
				
			||||||
 | 
					        options.name = { | 
				
			||||||
/** | 
					            [Op.iLike]: `%${options.name}%` | 
				
			||||||
 * Add your | 
					        }; | 
				
			||||||
 * - pre-save hooks | 
					    } | 
				
			||||||
 * - validations | 
					
 | 
				
			||||||
 * - virtuals | 
					    return options; | 
				
			||||||
 */ | 
					} | 
				
			||||||
File.addHook('afterCreate', () => { }); | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
File.addHook('afterUpdate', () => { }); | 
					 * Load sort query | 
				
			||||||
 | 
					 * @param {*} sort_by | 
				
			||||||
File.addHook('afterDestroy', () => { }); | 
					 * @param {*} order_by | 
				
			||||||
 | 
					 */ | 
				
			||||||
/** | 
					function sortConditions({ sort_by, order_by }) { | 
				
			||||||
 * Load query | 
					    let sort = null; | 
				
			||||||
 * @param {*} params | 
					    switch (sort_by) { | 
				
			||||||
 */ | 
					        case 'created_at': | 
				
			||||||
function filterConditions(params) { | 
					            sort = ['created_at', order_by]; | 
				
			||||||
    const options = omitBy(params, isNil); | 
					            break; | 
				
			||||||
    options.is_active = true; | 
					        case 'updated_at': | 
				
			||||||
 | 
					            sort = ['updated_at', order_by]; | 
				
			||||||
    // TODO: load condition
 | 
					            break; | 
				
			||||||
    if (options.name) { | 
					        default: sort = ['created_at', 'DESC']; | 
				
			||||||
        options.name = { | 
					            break; | 
				
			||||||
            [Op.iLike]: `%${options.name}%` | 
					    } | 
				
			||||||
        }; | 
					    return sort; | 
				
			||||||
    } | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
    return options; | 
					/** | 
				
			||||||
} | 
					 * Transform postgres model to expose object | 
				
			||||||
 | 
					 */ | 
				
			||||||
/** | 
					File.transform = (params) => { | 
				
			||||||
 * Load sort query | 
					    const transformed = {}; | 
				
			||||||
 * @param {*} sort_by | 
					    const fields = [ | 
				
			||||||
 * @param {*} order_by | 
					        'id', | 
				
			||||||
 */ | 
					        'name', | 
				
			||||||
function sortConditions({ sort_by, order_by }) { | 
					        'payload', | 
				
			||||||
    let sort = null; | 
					        'created_by' | 
				
			||||||
    switch (sort_by) { | 
					    ]; | 
				
			||||||
        case 'created_at': | 
					    fields.forEach((field) => { | 
				
			||||||
            sort = ['created_at', order_by]; | 
					        transformed[field] = params[field]; | 
				
			||||||
            break; | 
					    }); | 
				
			||||||
        case 'updated_at': | 
					
 | 
				
			||||||
            sort = ['updated_at', order_by]; | 
					    // pipe date
 | 
				
			||||||
            break; | 
					    const dateFields = [ | 
				
			||||||
        default: sort = ['created_at', 'DESC']; | 
					        'created_at', | 
				
			||||||
            break; | 
					        'updated_at' | 
				
			||||||
    } | 
					    ]; | 
				
			||||||
    return sort; | 
					    dateFields.forEach((field) => { | 
				
			||||||
} | 
					        if (params[field]) { | 
				
			||||||
 | 
					            transformed[field] = moment(params[field]).unix(); | 
				
			||||||
/** | 
					        } else { | 
				
			||||||
 * Transform postgres model to expose object | 
					            transformed[field] = null; | 
				
			||||||
 */ | 
					        } | 
				
			||||||
File.transform = (params) => { | 
					    }); | 
				
			||||||
    const transformed = {}; | 
					
 | 
				
			||||||
    const fields = [ | 
					    return transformed; | 
				
			||||||
        'id', | 
					}; | 
				
			||||||
        'name', | 
					
 | 
				
			||||||
        'payload', | 
					/** | 
				
			||||||
        'created_by' | 
					 * Get all changed properties | 
				
			||||||
    ]; | 
					 */ | 
				
			||||||
    fields.forEach((field) => { | 
					File.getChangedProperties = ({ newModel, oldModel }) => { | 
				
			||||||
        transformed[field] = params[field]; | 
					    const changedProperties = []; | 
				
			||||||
    }); | 
					    const allChangableProperties = [ | 
				
			||||||
 | 
					        'id', | 
				
			||||||
    // pipe date
 | 
					        'name', | 
				
			||||||
    const dateFields = [ | 
					        'payload', | 
				
			||||||
        'created_at', | 
					    ]; | 
				
			||||||
        'updated_at' | 
					    if (!oldModel) { | 
				
			||||||
    ]; | 
					        return allChangableProperties; | 
				
			||||||
    dateFields.forEach((field) => { | 
					    } | 
				
			||||||
        if (params[field]) { | 
					
 | 
				
			||||||
            transformed[field] = moment(params[field]).unix(); | 
					    allChangableProperties.forEach((field) => { | 
				
			||||||
        } else { | 
					        if ( | 
				
			||||||
            transformed[field] = null; | 
					            !isUndefined(newModel[field]) && | 
				
			||||||
        } | 
					            !isEqual(newModel[field], oldModel[field]) | 
				
			||||||
    }); | 
					        ) { | 
				
			||||||
 | 
					            changedProperties.push(field); | 
				
			||||||
    return transformed; | 
					        } | 
				
			||||||
}; | 
					    }); | 
				
			||||||
 | 
					
 | 
				
			||||||
/** | 
					    return changedProperties; | 
				
			||||||
 * Get all changed properties | 
					}; | 
				
			||||||
 */ | 
					
 | 
				
			||||||
File.getChangedProperties = ({ newModel, oldModel }) => { | 
					/** | 
				
			||||||
    const changedProperties = []; | 
					 * Detail | 
				
			||||||
    const allChangableProperties = [ | 
					 * | 
				
			||||||
        'id', | 
					 * @public | 
				
			||||||
        'name', | 
					 * @param {string} id | 
				
			||||||
        'payload', | 
					 */ | 
				
			||||||
    ]; | 
					File.get = async (id) => { | 
				
			||||||
    if (!oldModel) { | 
					    try { | 
				
			||||||
        return allChangableProperties; | 
					        const data = await File.findOne({ | 
				
			||||||
    } | 
					            where: { | 
				
			||||||
 | 
					                id, | 
				
			||||||
    allChangableProperties.forEach((field) => { | 
					                is_active: true | 
				
			||||||
        if ( | 
					            } | 
				
			||||||
            !isUndefined(newModel[field]) && | 
					        }); | 
				
			||||||
            !isEqual(newModel[field], oldModel[field]) | 
					        if (!data) { | 
				
			||||||
        ) { | 
					            throw new APIError({ | 
				
			||||||
            changedProperties.push(field); | 
					                status: httpStatus.NOT_FOUND, | 
				
			||||||
        } | 
					                message: 'Không tìm thấy địa chỉ file!' | 
				
			||||||
    }); | 
					            }); | 
				
			||||||
 | 
					        } | 
				
			||||||
    return changedProperties; | 
					        return data; | 
				
			||||||
}; | 
					    } catch (ex) { | 
				
			||||||
 | 
					        throw ex; | 
				
			||||||
/** | 
					    } | 
				
			||||||
 * Detail | 
					}; | 
				
			||||||
 * | 
					
 | 
				
			||||||
 * @public | 
					/** | 
				
			||||||
 * @param {string} id | 
					 * List users in descending order of 'createdAt' timestamp. | 
				
			||||||
 */ | 
					 * | 
				
			||||||
File.get = async (id) => { | 
					 * @param {number} skip - Number of users to be skipped. | 
				
			||||||
    try { | 
					 * @param {number} limit - Limit number of users to be returned. | 
				
			||||||
        const data = await File.findOne({ | 
					 * @returns {Promise<Supplider[]>} | 
				
			||||||
            where: { | 
					 */ | 
				
			||||||
                id, | 
					File.list = async ({ | 
				
			||||||
                is_active: true | 
					    name, | 
				
			||||||
            } | 
					
 | 
				
			||||||
        }); | 
					    // sort
 | 
				
			||||||
        if (!data) { | 
					    sort_by, | 
				
			||||||
            throw new APIError({ | 
					    order_by, | 
				
			||||||
                status: httpStatus.NOT_FOUND, | 
					    skip = 0, | 
				
			||||||
                message: 'Không tìm thấy địa chỉ tỉnh/thành!' | 
					    limit = 20, | 
				
			||||||
            }); | 
					}) => { | 
				
			||||||
        } | 
					    const options = filterConditions({ | 
				
			||||||
        return data; | 
					        name | 
				
			||||||
    } catch (ex) { | 
					    }); | 
				
			||||||
        throw ex; | 
					    const sort = sortConditions({ sort_by, order_by }); | 
				
			||||||
    } | 
					    return File.findAll({ | 
				
			||||||
}; | 
					        where: options, | 
				
			||||||
 | 
					        order: [sort], | 
				
			||||||
/** | 
					        offset: skip, | 
				
			||||||
 * List users in descending order of 'createdAt' timestamp. | 
					        limit: limit | 
				
			||||||
 * | 
					    }); | 
				
			||||||
 * @param {number} skip - Number of users to be skipped. | 
					}; | 
				
			||||||
 * @param {number} limit - Limit number of users to be returned. | 
					
 | 
				
			||||||
 * @returns {Promise<Supplider[]>} | 
					/** | 
				
			||||||
 */ | 
					 * Total records. | 
				
			||||||
File.list = async ({ | 
					 * | 
				
			||||||
    name, | 
					 * @param {number} skip - Number of users to be skipped. | 
				
			||||||
    // sort
 | 
					 * @param {number} limit - Limit number of users to be returned. | 
				
			||||||
    sort_by, | 
					 * @returns {Promise<Number>} | 
				
			||||||
    order_by, | 
					 */ | 
				
			||||||
    skip = 0, | 
					File.totalRecords = ({ | 
				
			||||||
    limit = 20, | 
					    name | 
				
			||||||
}) => { | 
					}) => { | 
				
			||||||
    const options = filterConditions({ | 
					    const options = filterConditions({ | 
				
			||||||
        name | 
					        name | 
				
			||||||
    }); | 
					    }); | 
				
			||||||
    const sort = sortConditions({ sort_by, order_by }); | 
					
 | 
				
			||||||
    return File.findAll({ | 
					    return File.count({ where: options }); | 
				
			||||||
        where: options, | 
					}; | 
				
			||||||
        order: [sort], | 
					
 | 
				
			||||||
        offset: skip, | 
					/** | 
				
			||||||
        limit: limit | 
					 * Filter only allowed fields from File | 
				
			||||||
    }); | 
					 * | 
				
			||||||
}; | 
					 * @param {Object} params | 
				
			||||||
 | 
					 */ | 
				
			||||||
/** | 
					File.filterParams = (params) => pick(params, PUBLIC_FIELDS); | 
				
			||||||
 * Total records. | 
					
 | 
				
			||||||
 * | 
					/** | 
				
			||||||
 * @param {number} skip - Number of users to be skipped. | 
					 * @typedef File | 
				
			||||||
 * @param {number} limit - Limit number of users to be returned. | 
					 */ | 
				
			||||||
 * @returns {Promise<Number>} | 
					export default File; | 
				
			||||||
 */ | 
					 | 
				
			||||||
File.totalRecords = ({ | 
					 | 
				
			||||||
    name | 
					 | 
				
			||||||
}) => { | 
					 | 
				
			||||||
    const options = filterConditions({ | 
					 | 
				
			||||||
        name | 
					 | 
				
			||||||
    }); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return File.count({ where: options }); | 
					 | 
				
			||||||
}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** | 
					 | 
				
			||||||
 * Filter only allowed fields from File | 
					 | 
				
			||||||
 * | 
					 | 
				
			||||||
 * @param {Object} params | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
File.filterParams = (params) => pick(params, PUBLIC_FIELDS); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** | 
					 | 
				
			||||||
 * @typedef File | 
					 | 
				
			||||||
 */ | 
					 | 
				
			||||||
export default File; | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,293 +1,292 @@ | 
				
			|||||||
/* 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 | 
				
			||||||
 * Add your | 
					 * - pre-save hooks | 
				
			||||||
 * - pre-save hooks | 
					 * - validations | 
				
			||||||
 * - validations | 
					 * - virtuals | 
				
			||||||
 * - virtuals | 
					 */ | 
				
			||||||
 */ | 
					Image.addHook('afterCreate', () => { }); | 
				
			||||||
Image.addHook('afterCreate', () => { }); | 
					
 | 
				
			||||||
 | 
					Image.addHook('afterUpdate', () => { }); | 
				
			||||||
Image.addHook('afterUpdate', () => { }); | 
					
 | 
				
			||||||
 | 
					Image.addHook('afterDestroy', () => { }); | 
				
			||||||
Image.addHook('afterDestroy', () => { }); | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Load query | 
				
			||||||
 * Load query | 
					 * @param {*} params | 
				
			||||||
 * @param {*} params | 
					 */ | 
				
			||||||
 */ | 
					function filterConditions(params) { | 
				
			||||||
function filterConditions(params) { | 
					    const options = omitBy(params, isNil); | 
				
			||||||
    const options = omitBy(params, isNil); | 
					    options.is_active = true; | 
				
			||||||
    options.is_active = true; | 
					
 | 
				
			||||||
 | 
					    // TODO: load condition
 | 
				
			||||||
    // TODO: load condition
 | 
					    if (options.name) { | 
				
			||||||
    if (options.name) { | 
					        options.name = { | 
				
			||||||
        options.name = { | 
					            [Op.iLike]: `%${options.name}%` | 
				
			||||||
            [Op.iLike]: `%${options.name}%` | 
					        }; | 
				
			||||||
        }; | 
					    } | 
				
			||||||
    } | 
					
 | 
				
			||||||
 | 
					    return options; | 
				
			||||||
    return options; | 
					} | 
				
			||||||
} | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Load sort query | 
				
			||||||
 * Load sort query | 
					 * @param {*} sort_by | 
				
			||||||
 * @param {*} sort_by | 
					 * @param {*} order_by | 
				
			||||||
 * @param {*} order_by | 
					 */ | 
				
			||||||
 */ | 
					function sortConditions({ sort_by, order_by }) { | 
				
			||||||
function sortConditions({ sort_by, order_by }) { | 
					    let sort = null; | 
				
			||||||
    let sort = null; | 
					    switch (sort_by) { | 
				
			||||||
    switch (sort_by) { | 
					        case 'created_at': | 
				
			||||||
        case 'created_at': | 
					            sort = ['created_at', order_by]; | 
				
			||||||
            sort = ['created_at', order_by]; | 
					            break; | 
				
			||||||
            break; | 
					        case 'updated_at': | 
				
			||||||
        case 'updated_at': | 
					            sort = ['updated_at', order_by]; | 
				
			||||||
            sort = ['updated_at', order_by]; | 
					            break; | 
				
			||||||
            break; | 
					        default: sort = ['created_at', 'DESC']; | 
				
			||||||
        default: sort = ['created_at', 'DESC']; | 
					            break; | 
				
			||||||
            break; | 
					    } | 
				
			||||||
    } | 
					    return sort; | 
				
			||||||
    return sort; | 
					} | 
				
			||||||
} | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Transform postgres model to expose object | 
				
			||||||
 * Transform postgres model to expose object | 
					 */ | 
				
			||||||
 */ | 
					Image.transform = (params) => { | 
				
			||||||
Image.transform = (params) => { | 
					    const transformed = {}; | 
				
			||||||
    const transformed = {}; | 
					    const fields = [ | 
				
			||||||
    const fields = [ | 
					        'id', | 
				
			||||||
        'id', | 
					        'name', | 
				
			||||||
        'name', | 
					        'payload', | 
				
			||||||
        'payload', | 
					        'created_by' | 
				
			||||||
        'created_by' | 
					    ]; | 
				
			||||||
    ]; | 
					    fields.forEach((field) => { | 
				
			||||||
    fields.forEach((field) => { | 
					        transformed[field] = params[field]; | 
				
			||||||
        transformed[field] = params[field]; | 
					    }); | 
				
			||||||
    }); | 
					
 | 
				
			||||||
 | 
					    // pipe date
 | 
				
			||||||
    // pipe date
 | 
					    const dateFields = [ | 
				
			||||||
    const dateFields = [ | 
					        'created_at', | 
				
			||||||
        'created_at', | 
					        'updated_at' | 
				
			||||||
        'updated_at' | 
					    ]; | 
				
			||||||
    ]; | 
					    dateFields.forEach((field) => { | 
				
			||||||
    dateFields.forEach((field) => { | 
					        if (params[field]) { | 
				
			||||||
        if (params[field]) { | 
					            transformed[field] = moment(params[field]).unix(); | 
				
			||||||
            transformed[field] = moment(params[field]).unix(); | 
					        } else { | 
				
			||||||
        } else { | 
					            transformed[field] = null; | 
				
			||||||
            transformed[field] = null; | 
					        } | 
				
			||||||
        } | 
					    }); | 
				
			||||||
    }); | 
					
 | 
				
			||||||
 | 
					    return transformed; | 
				
			||||||
    return transformed; | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Get all changed properties | 
				
			||||||
 * Get all changed properties | 
					 */ | 
				
			||||||
 */ | 
					Image.getChangedProperties = ({ newModel, oldModel }) => { | 
				
			||||||
Image.getChangedProperties = ({ newModel, oldModel }) => { | 
					    const changedProperties = []; | 
				
			||||||
    const changedProperties = []; | 
					    const allChangableProperties = [ | 
				
			||||||
    const allChangableProperties = [ | 
					        'id', | 
				
			||||||
        'id', | 
					        'name', | 
				
			||||||
        'name', | 
					        'payload', | 
				
			||||||
        'payload', | 
					    ]; | 
				
			||||||
    ]; | 
					    if (!oldModel) { | 
				
			||||||
    if (!oldModel) { | 
					        return allChangableProperties; | 
				
			||||||
        return allChangableProperties; | 
					    } | 
				
			||||||
    } | 
					
 | 
				
			||||||
 | 
					    allChangableProperties.forEach((field) => { | 
				
			||||||
    allChangableProperties.forEach((field) => { | 
					        if ( | 
				
			||||||
        if ( | 
					            !isUndefined(newModel[field]) && | 
				
			||||||
            !isUndefined(newModel[field]) && | 
					            !isEqual(newModel[field], oldModel[field]) | 
				
			||||||
            !isEqual(newModel[field], oldModel[field]) | 
					        ) { | 
				
			||||||
        ) { | 
					            changedProperties.push(field); | 
				
			||||||
            changedProperties.push(field); | 
					        } | 
				
			||||||
        } | 
					    }); | 
				
			||||||
    }); | 
					
 | 
				
			||||||
 | 
					    return changedProperties; | 
				
			||||||
    return changedProperties; | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Detail | 
				
			||||||
 * Detail | 
					 * | 
				
			||||||
 * | 
					 * @public | 
				
			||||||
 * @public | 
					 * @param {string} id | 
				
			||||||
 * @param {string} id | 
					 */ | 
				
			||||||
 */ | 
					Image.get = async (id) => { | 
				
			||||||
Image.get = async (id) => { | 
					    try { | 
				
			||||||
    try { | 
					        const data = await Image.findOne({ | 
				
			||||||
        const data = await Image.findOne({ | 
					            where: { | 
				
			||||||
            where: { | 
					                id, | 
				
			||||||
                id, | 
					                is_active: true | 
				
			||||||
                is_active: true | 
					            } | 
				
			||||||
            } | 
					        }); | 
				
			||||||
        }); | 
					        if (!data) { | 
				
			||||||
        if (!data) { | 
					            throw new APIError({ | 
				
			||||||
            throw new APIError({ | 
					                status: httpStatus.NOT_FOUND, | 
				
			||||||
                status: httpStatus.NOT_FOUND, | 
					                message: 'Không tìm thấy địa chỉ tỉnh/thành!' | 
				
			||||||
                message: 'Không tìm thấy địa chỉ tỉnh/thành!' | 
					            }); | 
				
			||||||
            }); | 
					        } | 
				
			||||||
        } | 
					        return data; | 
				
			||||||
        return data; | 
					    } catch (ex) { | 
				
			||||||
    } catch (ex) { | 
					        throw 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} skip - Number of users to be skipped. | 
					 * @param {number} limit - Limit number of users to be returned. | 
				
			||||||
 * @param {number} limit - Limit number of users to be returned. | 
					 * @returns {Promise<Supplider[]>} | 
				
			||||||
 * @returns {Promise<Supplider[]>} | 
					 */ | 
				
			||||||
 */ | 
					Image.list = async ({ | 
				
			||||||
Image.list = async ({ | 
					    name, | 
				
			||||||
    name, | 
					
 | 
				
			||||||
 | 
					    // sort
 | 
				
			||||||
    // sort
 | 
					    sort_by, | 
				
			||||||
    sort_by, | 
					    order_by, | 
				
			||||||
    order_by, | 
					    skip = 0, | 
				
			||||||
    skip = 0, | 
					    limit = 20, | 
				
			||||||
    limit = 20, | 
					}) => { | 
				
			||||||
}) => { | 
					    const options = filterConditions({ | 
				
			||||||
    const options = filterConditions({ | 
					        name | 
				
			||||||
        name | 
					    }); | 
				
			||||||
    }); | 
					    const sort = sortConditions({ sort_by, order_by }); | 
				
			||||||
    const sort = sortConditions({ sort_by, order_by }); | 
					    return Image.findAll({ | 
				
			||||||
    return Image.findAll({ | 
					        where: options, | 
				
			||||||
        where: options, | 
					        order: [sort], | 
				
			||||||
        order: [sort], | 
					        offset: skip, | 
				
			||||||
        offset: skip, | 
					        limit: limit | 
				
			||||||
        limit: limit | 
					    }); | 
				
			||||||
    }); | 
					}; | 
				
			||||||
}; | 
					
 | 
				
			||||||
 | 
					/** | 
				
			||||||
/** | 
					 * Total records. | 
				
			||||||
 * Total records. | 
					 * | 
				
			||||||
 * | 
					 * @param {number} skip - Number of users to be skipped. | 
				
			||||||
 * @param {number} skip - Number of users to be skipped. | 
					 * @param {number} limit - Limit number of users to be returned. | 
				
			||||||
 * @param {number} limit - Limit number of users to be returned. | 
					 * @returns {Promise<Number>} | 
				
			||||||
 * @returns {Promise<Number>} | 
					 */ | 
				
			||||||
 */ | 
					Image.totalRecords = ({ | 
				
			||||||
Image.totalRecords = ({ | 
					    name | 
				
			||||||
    name | 
					}) => { | 
				
			||||||
}) => { | 
					    const options = filterConditions({ | 
				
			||||||
    const options = filterConditions({ | 
					        name | 
				
			||||||
        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,125 +1,114 @@ | 
				
			|||||||
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}` }); | 
				
			||||||
            console.log(`creat default ${filePath}/${id}` ); | 
					        } else { | 
				
			||||||
 | 
					            multer({ dest: `${filePath}` }); | 
				
			||||||
        } else { | 
					        } | 
				
			||||||
            multer({ dest: `${filePath}` }); | 
					        // multer({ dest: `${filePath}/images/games` });
 | 
				
			||||||
            console.log(`creat default ${filePath}` ); | 
					        // multer({ dest: `${filePath}/images/stories` });
 | 
				
			||||||
 | 
					        // multer({ dest: `${filePath}/images/chapters` });
 | 
				
			||||||
        } | 
					        // multer({ dest: `${filePath}/images/vouchers` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/games` });
 | 
					        // multer({ dest: `${filePath}/images/products` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/stories` });
 | 
					        // multer({ dest: `${filePath}/images/customers` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/chapters` });
 | 
					        // multer({ dest: `${filePath}/images/promotions` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/vouchers` });
 | 
					
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/products` });
 | 
					        // // configuration
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/customers` });
 | 
					        // multer({ dest: `${filePath}/images/banners` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/promotions` });
 | 
					        // multer({ dest: `${filePath}/images/categories` });
 | 
				
			||||||
 | 
					        // multer({ dest: `${filePath}/images/upload/default` });
 | 
				
			||||||
        // // configuration
 | 
					        return true; | 
				
			||||||
        // multer({ dest: `${filePath}/images/banners` });
 | 
					    } catch (ex) { | 
				
			||||||
        // multer({ dest: `${filePath}/images/categories` });
 | 
					        return false; | 
				
			||||||
        // multer({ dest: `${filePath}/images/upload/default` });
 | 
					    } | 
				
			||||||
        return true; | 
					}; | 
				
			||||||
    } catch (ex) { | 
					const createFolder = ({ path }) => { | 
				
			||||||
        return false; | 
					    try { | 
				
			||||||
    } | 
					        console.log(`${filePath}/${path}`); | 
				
			||||||
}; | 
					        multer({ dest: `${filePath}/${path}` }); | 
				
			||||||
const createFolder = ({ path }) => { | 
					
 | 
				
			||||||
    try { | 
					
 | 
				
			||||||
        console.log(`${filePath}/${path}`); | 
					        // multer({ dest: `${filePath}/images/games` });
 | 
				
			||||||
        multer({ dest: `${filePath}/${path}` }); | 
					        // multer({ dest: `${filePath}/images/stories` });
 | 
				
			||||||
    
 | 
					        // multer({ dest: `${filePath}/images/chapters` });
 | 
				
			||||||
 | 
					        // multer({ dest: `${filePath}/images/vouchers` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/games` });
 | 
					        // multer({ dest: `${filePath}/images/products` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/stories` });
 | 
					        // multer({ dest: `${filePath}/images/customers` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/chapters` });
 | 
					        // multer({ dest: `${filePath}/images/promotions` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/vouchers` });
 | 
					
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/products` });
 | 
					        // // configuration
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/customers` });
 | 
					        // multer({ dest: `${filePath}/images/banners` });
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/promotions` });
 | 
					        // multer({ dest: `${filePath}/images/categories` });
 | 
				
			||||||
 | 
					        // multer({ dest: `${filePath}/images/upload/default` });
 | 
				
			||||||
        // // configuration
 | 
					        // console.log(multer);
 | 
				
			||||||
        // multer({ dest: `${filePath}/images/banners` });
 | 
					        return true; | 
				
			||||||
        // multer({ dest: `${filePath}/images/categories` });
 | 
					    } catch (ex) { | 
				
			||||||
        // multer({ dest: `${filePath}/images/upload/default` });
 | 
					        return false; | 
				
			||||||
        // console.log(multer);
 | 
					    } | 
				
			||||||
        return true; | 
					}; | 
				
			||||||
    } catch (ex) { | 
					/** add image to storage follow group */ | 
				
			||||||
        return false; | 
					const storage = multer.diskStorage({ | 
				
			||||||
    } | 
					    destination: (req, file, cb) => { | 
				
			||||||
}; | 
					        cb(null, filePath); | 
				
			||||||
/** add image to storage follow group */ | 
					    }, | 
				
			||||||
const storage = multer.diskStorage({ | 
					    filename: (req, file, cb) => { | 
				
			||||||
    destination: (req, file, cb) => { | 
					        /** | 
				
			||||||
        cb(null, filePath); | 
					         * setup folder follow date | 
				
			||||||
    }, | 
					         */ | 
				
			||||||
    filename: (req, file, cb) => { | 
					        createDefaultFolder({}); | 
				
			||||||
        /** | 
					        console.log('run in herer', req.query.path, file); | 
				
			||||||
         * setup folder follow date | 
					        /** | 
				
			||||||
         */ | 
					         * save image follow type | 
				
			||||||
        createDefaultFolder(req.params.id); | 
					         */ | 
				
			||||||
        console.log('run in herer', req.query.path, file); | 
					        const path = req.query.path; | 
				
			||||||
      
 | 
					
 | 
				
			||||||
        /** | 
					        // const fileName = file.originalname.includes('.')
 | 
				
			||||||
         * save image follow type | 
					        //     ? file.originalname.slice(0, file.originalname.lastIndexOf('.'))
 | 
				
			||||||
         */ | 
					        //     : file.originalname;
 | 
				
			||||||
 | 
					        cb( | 
				
			||||||
        // let path = req.locals.user.id;
 | 
					            null, | 
				
			||||||
        // console.log(path);
 | 
					            `/${path}/${file.originalname.replace(/[\s()]/g, '')}` | 
				
			||||||
        let path = req.params.id; | 
					        ); | 
				
			||||||
        console.log(path); | 
					    } | 
				
			||||||
        console.log(file); | 
					}); | 
				
			||||||
 | 
					
 | 
				
			||||||
        // const fileName = file.originalname.includes('.')
 | 
					const fileFilter = (req, file, cb) => { | 
				
			||||||
        //     ? file.originalname.slice(0, file.originalname.lastIndexOf('.'))
 | 
					    // if (
 | 
				
			||||||
        //     : file.originalname;
 | 
					    //     file.mimetype === 'image/jpeg' ||
 | 
				
			||||||
        cb( | 
					    //     file.mimetype === 'image/webp' ||
 | 
				
			||||||
            null, | 
					    //     file.mimetype === 'image/png' ||
 | 
				
			||||||
            `/${path}/${file.originalname.replace(/\s/g, '')}` | 
					    //     file.mimetype === 'image/gif' ||
 | 
				
			||||||
        ); | 
					    // ) {
 | 
				
			||||||
    } | 
					    //     cb(null, true);
 | 
				
			||||||
}); | 
					    // } else {
 | 
				
			||||||
 | 
					    //     cb(null, false);
 | 
				
			||||||
const fileFilter = (req, file, cb) => { | 
					    // }
 | 
				
			||||||
    // if (
 | 
					    cb(null, true); | 
				
			||||||
    //     file.mimetype === 'image/jpeg' ||
 | 
					}; | 
				
			||||||
    //     file.mimetype === 'image/webp' ||
 | 
					
 | 
				
			||||||
    //     file.mimetype === 'image/png' ||
 | 
					const uploader = multer({ | 
				
			||||||
    //     file.mimetype === 'image/gif' ||
 | 
					    storage, | 
				
			||||||
    // ) {
 | 
					    limits: { | 
				
			||||||
    //     cb(null, true);
 | 
					        fileSize: 1024 * 1024 * 5048 // 5MB
 | 
				
			||||||
    // } else {
 | 
					    }, | 
				
			||||||
    //     cb(null, false);
 | 
					    fileFilter | 
				
			||||||
    // }
 | 
					}); | 
				
			||||||
    cb(null, true); | 
					
 | 
				
			||||||
}; | 
					module.exports = { | 
				
			||||||
 | 
					    createDefaultFolder, | 
				
			||||||
const uploader = multer({ | 
					    createFolder, | 
				
			||||||
    storage, | 
					    uploader, | 
				
			||||||
    limits: { | 
					    fileFilter | 
				
			||||||
        fileSize: 1024 * 1024 * 2048 // 5MB
 | 
					}; | 
				
			||||||
    }, | 
					 | 
				
			||||||
    fileFilter | 
					 | 
				
			||||||
}); | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = { | 
					 | 
				
			||||||
    createDefaultFolder, | 
					 | 
				
			||||||
    createFolder, | 
					 | 
				
			||||||
    uploader, | 
					 | 
				
			||||||
    fileFilter | 
					 | 
				
			||||||
}; | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
					Loading…
					
					
				
		Reference in new issue