Init
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
PORT=6060
|
||||||
|
SECRET=fs4ebJ87dfyu87sdHdfgd
|
||||||
|
ACCESS_TOKEN_SECERT=J78fsd7fd8f9M8fdfJDSOW0fd
|
||||||
|
ACCESS_TOKEN_SECERT_ADMIN=J78fF4fsFHf9Mdfsdf54fFeW0fdds
|
||||||
|
CONNECTION_STRING=mongodb://root:K0W9aON8qOTYVui28Ir4qeFn@robin.iran.liara.ir:30448/asan-market?authSource=admin
|
||||||
|
CONNECTION_STRING_LOCAL=mongodb://127.0.0.1:27017/asan-market?authSource=admin
|
||||||
|
MERCHANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
EMAIL_HOST=
|
||||||
|
EMAIL_PORT=
|
||||||
|
EMAIL_USER=
|
||||||
|
EMAIL_PASS=
|
||||||
|
EMAIL_ADDRESS=
|
||||||
|
SMS_USER=
|
||||||
|
SMS_PASS=
|
||||||
|
SMS_NUMBER=
|
||||||
|
URLIMAGE=https://api-asanmarket.iran.liara.run
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
jquery: true
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
parser: '@babel/eslint-parser',
|
||||||
|
requireConfigFile: false
|
||||||
|
},
|
||||||
|
extends: ['@nuxtjs', 'plugin:nuxt/recommended', 'prettier'],
|
||||||
|
plugins: [],
|
||||||
|
// add your custom rules here
|
||||||
|
rules: {
|
||||||
|
'no-console': 'off',
|
||||||
|
camelcase: 'off',
|
||||||
|
'no-async-promise-executor': 'off',
|
||||||
|
'vue/no-v-html': 'off',
|
||||||
|
'vue/prop-name-casing': 'off'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/node_modules
|
||||||
|
.png
|
||||||
|
.jpg
|
||||||
|
.web
|
||||||
|
|
||||||
|
*.png
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
const db = async () => {
|
||||||
|
try {
|
||||||
|
const connect = await mongoose.connect(process.env.CONNECTION_STRING);
|
||||||
|
console.log(
|
||||||
|
"Database connected: ",
|
||||||
|
connect.connection.host,
|
||||||
|
connect.connection.name
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("Retry for DB");
|
||||||
|
db();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = db;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
const nodemailer = require("nodemailer");
|
||||||
|
|
||||||
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: process.env.EMAIL_HOST,
|
||||||
|
port: process.env.EMAIL_PORT,
|
||||||
|
secure: true,
|
||||||
|
auth: {
|
||||||
|
user: process.env.EMAIL_USER,
|
||||||
|
pass: process.env.EMAIL_PASS,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const email = async (to, subject, text, html) => {
|
||||||
|
|
||||||
|
const info = await transporter.sendMail({
|
||||||
|
from: `"Asan Market" ${process.env.EMAIL_ADDRESS}`, // sender address
|
||||||
|
to: to, // list of receivers
|
||||||
|
subject: subject, // Subject line
|
||||||
|
text: text, // plain text body
|
||||||
|
html: html, // html body
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
module.exports = email;
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
const axios = require('axios')
|
||||||
|
|
||||||
|
const accountInfo = {
|
||||||
|
Username: '000',
|
||||||
|
Password: '000',
|
||||||
|
Number: '000',
|
||||||
|
url: 'http://www.afe.ir/WebService/V4/BoxService.asmx'
|
||||||
|
}
|
||||||
|
|
||||||
|
/////// http post soap method
|
||||||
|
module.exports.sms = (mobileNumbersArray, message) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
function renderMobileNumbers(array) {
|
||||||
|
if (Array.isArray(array)) {
|
||||||
|
return array.map(item => `<string>${item}</string>`).join('')
|
||||||
|
} else {
|
||||||
|
return `<string>${array}</string>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const xml = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
||||||
|
<soap:Body>
|
||||||
|
<SendMessage xmlns="http://www.afe.ir/">
|
||||||
|
<Username>${accountInfo.Username}</Username>
|
||||||
|
<Password>${accountInfo.Password}</Password>
|
||||||
|
<Number>${accountInfo.Number}</Number>
|
||||||
|
<Mobile>
|
||||||
|
${renderMobileNumbers(mobileNumbersArray)}
|
||||||
|
</Mobile>
|
||||||
|
<Message>${message}</Message>
|
||||||
|
<Type>1</Type>
|
||||||
|
</SendMessage>
|
||||||
|
</soap:Body>
|
||||||
|
</soap:Envelope>`
|
||||||
|
|
||||||
|
axios
|
||||||
|
.post(accountInfo.url, xml, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/xml; charset=utf-8',
|
||||||
|
SOAPAction: 'http://www.afe.ir/SendMessage'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
resolve(res)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(
|
||||||
|
'this is sms module error ------------------ status code: %s error message: %s ',
|
||||||
|
err.response.status,
|
||||||
|
err.response.data
|
||||||
|
)
|
||||||
|
resolve(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
exports.constants = {
|
||||||
|
VALIDATION_ERROR: 400,
|
||||||
|
UNAUTHORIZED: 401,
|
||||||
|
FORBIDOEN: 403,
|
||||||
|
NOT_FOUND: 404,
|
||||||
|
SERVER_ERROR: 500,
|
||||||
|
SITE_UNAUTHORIZED: 422,
|
||||||
|
TOO_MANY: 429,
|
||||||
|
};
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
const asyncHandler = require("express-async-handler");
|
||||||
|
const News = require("../models/newsModels");
|
||||||
|
const { email } = require("../config/emailConnection");
|
||||||
|
const { checkValidations } = require("../plugins/HelperFunctions")
|
||||||
|
const { body, validationResult } = require('express-validator')
|
||||||
|
const { _sr } = require("../plugins/resServer")
|
||||||
|
const { rateLimit } = require('express-rate-limit')
|
||||||
|
|
||||||
|
const limiter = rateLimit({
|
||||||
|
windowMs: 24 * 60 * 60 * 1000, // 1 minutes
|
||||||
|
limit: 1, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
|
||||||
|
standardHeaders: 'draft-7', // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
|
||||||
|
legacyHeaders: false, // Disable the `X-RateLimit-*` headers.
|
||||||
|
message: { msg: "Too many requests, please try again later." }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@desc Add new email
|
||||||
|
*@route POST /api/news/
|
||||||
|
*@access private
|
||||||
|
*/
|
||||||
|
const addEmail = [
|
||||||
|
[
|
||||||
|
body('email').notEmpty().isEmail().withMessage(_sr.fa.required.email),
|
||||||
|
],
|
||||||
|
checkValidations(validationResult),
|
||||||
|
limiter,
|
||||||
|
asyncHandler(async (req, res) => {
|
||||||
|
const { email } = req.body
|
||||||
|
const alreadyEmail = await News.findOne({ email })
|
||||||
|
if (alreadyEmail) {
|
||||||
|
res.status(400);
|
||||||
|
throw new Error(_sr.fa.duplicated.email);
|
||||||
|
}
|
||||||
|
const emailAdded = await News.create({
|
||||||
|
email
|
||||||
|
})
|
||||||
|
res.status(200).json(emailAdded)
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
baseRoute: "/news",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
off: false,
|
||||||
|
route: "/",
|
||||||
|
method: "post",
|
||||||
|
middleware: [],
|
||||||
|
use: addEmail
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
};
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
const asyncHandler = require("express-async-handler");
|
||||||
|
const Site = require("../models/siteModels");
|
||||||
|
const { _sr } = require("../plugins/resServer")
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@desc Get all site
|
||||||
|
*@route GET /api/sites/
|
||||||
|
*@access Public
|
||||||
|
*/
|
||||||
|
const getSite = asyncHandler(async (req, res) => {
|
||||||
|
const profile = await Site.findOne({ profile: "main" });
|
||||||
|
res.status(200).json(profile);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*@desc Update a site
|
||||||
|
*@route PUT /api/sites/
|
||||||
|
*@access private
|
||||||
|
*/
|
||||||
|
const updateSite = [
|
||||||
|
asyncHandler(async (req, res) => {
|
||||||
|
const site = await Site.findOneAndUpdate(
|
||||||
|
{ profile: "main" },
|
||||||
|
req.body,
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!site) {
|
||||||
|
res.status(404);
|
||||||
|
throw new Error(_sr.fa.not_found.item_id);
|
||||||
|
}
|
||||||
|
res.status(200).json(site);
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
baseRoute: "/sites",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
off: false,
|
||||||
|
route: "/",
|
||||||
|
method: "get",
|
||||||
|
middleware: ['validateAdminToken', 'hasPermission'],
|
||||||
|
permission: "SITE",
|
||||||
|
use: getSite
|
||||||
|
},
|
||||||
|
{
|
||||||
|
off: false,
|
||||||
|
route: "/id/:id",
|
||||||
|
method: "put",
|
||||||
|
middleware: ['validateAdminToken', 'hasPermission'],
|
||||||
|
permission: "SITE",
|
||||||
|
use: updateSite
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./*"],
|
||||||
|
"@/*": ["./*"],
|
||||||
|
"~~/*": ["./*"],
|
||||||
|
"@@/*": ["./*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"app":"api-asanmarket",
|
||||||
|
"port":"5050",
|
||||||
|
"disks":[
|
||||||
|
{
|
||||||
|
"name": "uploads",
|
||||||
|
"mountTo": "uploads"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"node": {
|
||||||
|
"version": "18"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
const { constants } = require("../constants");
|
||||||
|
const errorHandler = (err, req, res, next) => {
|
||||||
|
const statusCode = res.statusCode ? res.statusCode : 500;
|
||||||
|
|
||||||
|
switch (statusCode) {
|
||||||
|
case constants.VALIDATION_ERROR:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Validation Failed ",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case constants.NOT_FOUND:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Not found ",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case constants.FORBIDOEN:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Forbidoen ",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case constants.SERVER_ERROR:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Server Error ",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case constants.UNAUTHORIZED:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Unauthorized ",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case constants.SITE_UNAUTHORIZED:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Site Unauthorized ",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case constants.TOO_MANY:
|
||||||
|
res.status(statusCode).json({
|
||||||
|
title: "Too many request",
|
||||||
|
msg: err.message,
|
||||||
|
stackTrace: err.stack,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(err);
|
||||||
|
res.status(500).json({ err: err.message, msg: "Unhandled error" })
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = { name: "errorHandler", run: errorHandler };
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const asyncHandler = require("express-async-handler");
|
||||||
|
const User = require("../models/userModels");
|
||||||
|
|
||||||
|
|
||||||
|
const hasPerma = (perm) => {
|
||||||
|
return asyncHandler(async (req, res, next) => {
|
||||||
|
const user = await User.findId(req.user.id)
|
||||||
|
if (user && (user.permissions.includes(perm) || !user.permissions.includes("ADMIN"))) {
|
||||||
|
return next()
|
||||||
|
} else {
|
||||||
|
res.status(401); throw new Error('کاربر مجوز لازم را ندارد');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = { name: "hasPermission", run: hasPerma };
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const asyncHandler = require("express-async-handler");
|
||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const Admin = require("../models/adminModels");
|
||||||
|
const validateAdminToken = asyncHandler(async (req, res, next) => {
|
||||||
|
let token = req.headers.siteuser || req.headers.SiteUser;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
res.status(401);
|
||||||
|
throw new Error("User is not authorized(N)");
|
||||||
|
} else {
|
||||||
|
const tokenA = await Admin.findOne({ token })
|
||||||
|
if (tokenA) {
|
||||||
|
jwt.verify(token, process.env.ACCESS_TOKEN_SECERT_ADMIN, (err, decoded) => {
|
||||||
|
if (err) {
|
||||||
|
res.status(401);
|
||||||
|
throw new Error("User is not authorized(JWT E)");
|
||||||
|
}
|
||||||
|
req.admin = decoded.user;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(401);
|
||||||
|
throw new Error("User is not authorized(DB N)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
module.exports = { name: "validateAdminToken", run: validateAdminToken };
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const asyncHandler = require("express-async-handler");
|
||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const User = require("../models/userModels");
|
||||||
|
|
||||||
|
const validateToken = asyncHandler(async (req, res, next) => {
|
||||||
|
let token = req.headers.authorization || req.headers.Authorization;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
res.status(401);
|
||||||
|
throw new Error("User is not authorized(N)");
|
||||||
|
} else {
|
||||||
|
const tokenA = await User.findOne({ token })
|
||||||
|
if (tokenA) {
|
||||||
|
jwt.verify(token, process.env.ACCESS_TOKEN_SECERT, (err, decoded) => {
|
||||||
|
if (err) {
|
||||||
|
res.status(401);
|
||||||
|
throw new Error("User is not authorized(JWT E)");
|
||||||
|
}
|
||||||
|
req.user = decoded.user;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(401);
|
||||||
|
throw new Error("User is not authorized(DB N)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
module.exports = { name: "validateToken", run: validateToken };
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const newsSchema = new mongoose.Schema({
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
unique: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
versionKey: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = mongoose.model("News", newsSchema);
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
|
const siteSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
profile: {
|
||||||
|
type: String,
|
||||||
|
default: "main",
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
name:{
|
||||||
|
type: String,
|
||||||
|
default: "Dlearn",
|
||||||
|
},
|
||||||
|
desc:{
|
||||||
|
type: String,
|
||||||
|
default: "Dlearn, marketplace core by Swift",
|
||||||
|
},
|
||||||
|
logo:{
|
||||||
|
type: String,
|
||||||
|
default: "/upload/Default.png",
|
||||||
|
},
|
||||||
|
tel1:{
|
||||||
|
type: String,
|
||||||
|
default: "+9391885657",
|
||||||
|
},
|
||||||
|
tel2:{
|
||||||
|
type: String,
|
||||||
|
default: "+9391885657",
|
||||||
|
},
|
||||||
|
address:{
|
||||||
|
type: String,
|
||||||
|
default: "Iran, Markazi",
|
||||||
|
},
|
||||||
|
socialMedia:[
|
||||||
|
{
|
||||||
|
kind: String,
|
||||||
|
address:String
|
||||||
|
}
|
||||||
|
],
|
||||||
|
emailHost:String,
|
||||||
|
emailPort:String,
|
||||||
|
emailUser:String,
|
||||||
|
emailPass:String,
|
||||||
|
smsNumber:String,
|
||||||
|
smsUser:String,
|
||||||
|
smsPass:String,
|
||||||
|
underConstruction:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
versionKey: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = mongoose.model("Site", siteSchema);
|
||||||
Generated
+4648
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "asanmarket",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js",
|
||||||
|
"dev": "nodemon server.js"
|
||||||
|
},
|
||||||
|
"author": "swift",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.6.2",
|
||||||
|
"bcrypt": "^5.1.0",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"cron": "^3.1.6",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"express-async-handler": "^1.2.0",
|
||||||
|
"express-fileupload": "^1.4.1",
|
||||||
|
"express-rate-limit": "^7.2.0",
|
||||||
|
"express-route-detector": "^1.1.0",
|
||||||
|
"express-sharp": "^4.2.41",
|
||||||
|
"express-validator": "^7.0.1",
|
||||||
|
"jsonwebtoken": "^9.0.0",
|
||||||
|
"moment": "^2.29.4",
|
||||||
|
"mongodb": "^5.6.0",
|
||||||
|
"mongoose": "^7.3.1",
|
||||||
|
"mongoose-sequence": "^6.0.1",
|
||||||
|
"nodemailer": "^6.9.4",
|
||||||
|
"nodemon": "^2.0.22",
|
||||||
|
"swiftly-tools": "1.2.82"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const checkValidations = validationResult => {
|
||||||
|
return (req, res, next) => {
|
||||||
|
const errors = validationResult(req)
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
const msg = {}
|
||||||
|
errors.errors.forEach(err => {
|
||||||
|
msg[err.path] = err.msg
|
||||||
|
});
|
||||||
|
res.status(422).json(msg)
|
||||||
|
} else next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function filterDatesWithinDays(data, days, status) {
|
||||||
|
const currentDate = new Date();
|
||||||
|
const sevenDaysAgo = new Date(currentDate.getTime() - days * 24 * 60 * 60 * 1000);
|
||||||
|
if (status) {
|
||||||
|
return data.orders.filter(item => {
|
||||||
|
const itemDate = new Date(item.orderDate);
|
||||||
|
return itemDate >= sevenDaysAgo && itemDate <= currentDate && item.status == status;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return data.orders.filter(item => {
|
||||||
|
const itemDate = new Date(item.orderDate);
|
||||||
|
return itemDate >= sevenDaysAgo && itemDate <= currentDate;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function filterWithStatus(data, status) {
|
||||||
|
return data.orders.filter(item => {
|
||||||
|
return item.status == status;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const sumProductsById = (data) => {
|
||||||
|
const sumArray = [];
|
||||||
|
const map = {};
|
||||||
|
|
||||||
|
data.forEach(item => {
|
||||||
|
item.products.forEach(pd=>{
|
||||||
|
const productId = pd.product.uid;
|
||||||
|
const product = pd.product;
|
||||||
|
const price = pd.price;
|
||||||
|
|
||||||
|
if (!map[productId]) {
|
||||||
|
map[productId] = { product, total: 0, quantity: 0 };
|
||||||
|
sumArray.push(map[productId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
map[productId].total += price;
|
||||||
|
map[productId].quantity = product.stockQuantity;
|
||||||
|
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
return (sumArray.sort((a, b) => a - b)).slice(0, 5);
|
||||||
|
};
|
||||||
|
|
||||||
|
function filterQuantityHigh3(data) {
|
||||||
|
return data.products.filter(item => {
|
||||||
|
return item.stockQuantity > 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterQuantityLow3(data) {
|
||||||
|
return data.products.filter(item => {
|
||||||
|
return item.stockQuantity <= 3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterZeroStock(data) {
|
||||||
|
return data.products.filter(item => {
|
||||||
|
return item.stockQuantity == 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
filterDatesWithinDays,
|
||||||
|
sumProductsById,
|
||||||
|
filterWithStatus,
|
||||||
|
filterQuantityHigh3,
|
||||||
|
filterQuantityLow3,
|
||||||
|
filterZeroStock,
|
||||||
|
checkValidations
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
populate: {
|
||||||
|
productPopAdmin: 'comments shopID sub brandID'
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
userCustom: 'firstName lastName phoneNumber cellNumber',
|
||||||
|
user: 'firstName lastName',
|
||||||
|
auther: 'firstName lastName',
|
||||||
|
comment: 'firstName lastName',
|
||||||
|
productCard: 'title price specialPrice specialSell category coverImage coverPath stars orderRange uid',
|
||||||
|
productCard2: 'title category coverImage coverPath uid',
|
||||||
|
blogCard: 'link title coverImage content',
|
||||||
|
shop: 'shopName active rate desc',
|
||||||
|
brand: 'title link description logo',
|
||||||
|
category: 'main ordering link name',
|
||||||
|
shopProduct: 'title uid link price category specialPrice stockQuantity coverImage order confirmToShow createdAt updatedAt',
|
||||||
|
userMinus: '-password -token -createdAt -updatedAt -otp -otpTime -attempOtp -lastAttemp',
|
||||||
|
userProfile: 'favoriteProducts notifications',
|
||||||
|
productCart: 'title uid price specialPrice category coverImage shopID itemInBox boxSeller localSend warranty orderRange'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const moment = require("moment");
|
||||||
|
const date = moment();
|
||||||
|
|
||||||
|
const uploadImage = (image, res, type) => {
|
||||||
|
const maxSize = 15 * 1024 * 1024; // 15MB (example limit)
|
||||||
|
|
||||||
|
if (image.size > maxSize) {
|
||||||
|
res.status(500)
|
||||||
|
throw new Error("Image file size exceeds the limit")
|
||||||
|
}
|
||||||
|
let imageName =
|
||||||
|
date.format("YYYY-MM-DD") +
|
||||||
|
"-Img-" +
|
||||||
|
Math.floor(Math.random() * 900) +
|
||||||
|
100 +
|
||||||
|
image.name;
|
||||||
|
|
||||||
|
let saveToPath
|
||||||
|
let preFile
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "1":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/products", imageName);
|
||||||
|
preFile = "/uploads/products/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "2":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/blogs", imageName);
|
||||||
|
preFile = "/uploads/blogs/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "3":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/personal", imageName);
|
||||||
|
preFile = "/uploads/personal/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/none", imageName);
|
||||||
|
preFile = "/uploads/none/"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFile(saveToPath, image.data, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({ msg: "Error saving the image" });
|
||||||
|
} else {
|
||||||
|
res.status(201).json({ url: `${preFile}${imageName}` });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const uploadImages = (images, res, type) => {
|
||||||
|
const maxSize = 15 * 1024 * 1024; // 15MB (example limit)
|
||||||
|
const imageUrls = [];
|
||||||
|
|
||||||
|
if (!Array.isArray(images)) {
|
||||||
|
|
||||||
|
if (images.size > maxSize) {
|
||||||
|
res.status(500)
|
||||||
|
throw new Error("Image file size exceeds the limit")
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageName =
|
||||||
|
date.format("YYYY-MM-DD") +
|
||||||
|
"-Img-" +
|
||||||
|
Math.floor(Math.random() * 900) +
|
||||||
|
100 +
|
||||||
|
images.name;
|
||||||
|
|
||||||
|
let saveToPath
|
||||||
|
let preFile
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "1":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/products", imageName);
|
||||||
|
preFile = "/uploads/products/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "2":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/blogs", imageName);
|
||||||
|
preFile = "/uploads/blogs/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "3":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/personal", imageName);
|
||||||
|
preFile = "/uploads/personal/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "4":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/slider", imageName);
|
||||||
|
preFile = "/uploads/slider/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/none", imageName);
|
||||||
|
preFile = "/uploads/none/"
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFile(saveToPath, images.data, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({ msg: "Error saving the image" });
|
||||||
|
} else {
|
||||||
|
imageUrls.push(`${preFile}${imageName}`)
|
||||||
|
res.status(201).json({ urls: imageUrls });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
images.forEach(async (image) => {
|
||||||
|
if (image.size > maxSize) {
|
||||||
|
res.status(400)
|
||||||
|
throw new Error("Image file size exceeds the limit")
|
||||||
|
}
|
||||||
|
|
||||||
|
let imageName =
|
||||||
|
date.format("YYYY-MM-DD") +
|
||||||
|
"-Img-" +
|
||||||
|
Math.floor(Math.random() * 900) +
|
||||||
|
100 +
|
||||||
|
image.name;
|
||||||
|
|
||||||
|
let saveToPath
|
||||||
|
let preFile
|
||||||
|
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "1":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/products", imageName);
|
||||||
|
preFile = "/uploads/products/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "2":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/blogs", imageName);
|
||||||
|
preFile = "/uploads/blogs/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "3":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/personal", imageName);
|
||||||
|
preFile = "/uploads/personal/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "4":
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/slider", imageName);
|
||||||
|
preFile = "/uploads/slider/"
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
// Specify the save location
|
||||||
|
saveToPath = path.join(__dirname, "..", "uploads/none", imageName);
|
||||||
|
preFile = "/uploads/none/"
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageUrls.push(`${preFile}${imageName}`);
|
||||||
|
|
||||||
|
|
||||||
|
fs.writeFile(saveToPath, image.data, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
res.status(500)
|
||||||
|
throw new Error("Can't save images")
|
||||||
|
okd = false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
res.status(201).json({ urls: imageUrls });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteImage = (address, res) => {
|
||||||
|
const addressOf = path.join(__dirname, "..", address);
|
||||||
|
|
||||||
|
fs.unlink(addressOf, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error("Error removing image:", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
deleteImage,
|
||||||
|
uploadImage,
|
||||||
|
uploadImages,
|
||||||
|
};
|
||||||
@@ -0,0 +1,758 @@
|
|||||||
|
module.exports._sr = {
|
||||||
|
fa: {
|
||||||
|
required: {
|
||||||
|
token: 'توکن را وارد کنید',
|
||||||
|
field: 'این فیلد نباید خالی باشد',
|
||||||
|
// developer validations
|
||||||
|
remember_me: 'پارامتر remember_me الزامی است',
|
||||||
|
// registration validations
|
||||||
|
name: 'نام را وارد کنید',
|
||||||
|
first_name: 'نام را وارد کنید',
|
||||||
|
last_name: 'نام خانوادگی را وارد کنید',
|
||||||
|
email: 'ایمیل را وارد کنید',
|
||||||
|
national_code: 'کد ملی الزامی است',
|
||||||
|
email_personal: 'ایمیل شخصی الزامی است',
|
||||||
|
email_company: 'ایمیل کمپانی برای اشخاص حقوقی الزامی است',
|
||||||
|
company_name: 'درصورتی که شخص حقوقی هستید، نام کمپانی را وارد کنید',
|
||||||
|
username: 'نام کاربری را وارد کنید',
|
||||||
|
phone_number: 'شماره تماس را وارد کنید',
|
||||||
|
gender: "جنسیت خود را انتخاب کنید",
|
||||||
|
password: 'پسورد را وارد کنید',
|
||||||
|
birthdate: 'تاریخ تولد را وارد کنید',
|
||||||
|
permissions: 'مقدار دسترسی را وارد کنید',
|
||||||
|
// addressing validations
|
||||||
|
country: 'کشور را وارد کنید',
|
||||||
|
province: 'استان را وارد کنید',
|
||||||
|
city: 'شهر را وارد کنید',
|
||||||
|
address: 'آدرس را وارد کنید',
|
||||||
|
postal_code: 'کد پستی را وارد کنید',
|
||||||
|
plaque: 'پلاک را وارد کنید',
|
||||||
|
receiver_first_name: 'نام گیرنده را وارد کنید',
|
||||||
|
receiver_last_name: 'نام خانوادگی گیرنده را وارد کنید',
|
||||||
|
receiver_mobile: 'شماره موبایل گیرنده را وارد کنید',
|
||||||
|
// global (post - gallery - ...)
|
||||||
|
title: 'عنوان را وارد کنید',
|
||||||
|
caption: 'متن را وارد کنید',
|
||||||
|
description: 'توضیحات را وارد کنید',
|
||||||
|
category: 'دسته بندی را انتخاب کنید',
|
||||||
|
image: 'عکس اجباری است',
|
||||||
|
cover: 'کاور اجباری است',
|
||||||
|
file: 'فایل اجباری است',
|
||||||
|
message: 'پیام را بنویسید',
|
||||||
|
quantity: 'تعداد را وارد کنید',
|
||||||
|
date: 'تاریخ را وارد کنید',
|
||||||
|
reason: 'دلیل را انتخاب کنید',
|
||||||
|
question: 'سوال را بنویسید',
|
||||||
|
answer: 'جواب را بنویسید',
|
||||||
|
price: 'قیمت را وارد کنید',
|
||||||
|
type: 'نوع را انتخاب کنید',
|
||||||
|
discount_code: 'کد تخفیف را وارد کنید',
|
||||||
|
discount_amount: 'مقدار تخفیف را وارد کنید',
|
||||||
|
discount_expire_date: 'تاریخ انقضای کد تخفیف را مشخص کنید',
|
||||||
|
user_id: 'کاربر را انتخاب کنید',
|
||||||
|
video: 'ویدیو اجباری است',
|
||||||
|
setting_name: 'نام تنظیمات اجباری است',
|
||||||
|
setting_value: 'مقدار تنظیمات اجباری است'
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
phone_number: 'فرمت شماره تماس صحیح نیست',
|
||||||
|
email: 'فرمت ایمیل قابل قبول نیست',
|
||||||
|
number: 'مقدار باید از جنس عدد باشد',
|
||||||
|
boolean: 'مقدار باید از جنس Boolean باشد',
|
||||||
|
image: 'فرمت عکس قابل قبول نیست',
|
||||||
|
video: 'فرمت ویدیو قابل قبول نیست',
|
||||||
|
national_code: 'کد ملی صحیح نیست'
|
||||||
|
},
|
||||||
|
min_char: {
|
||||||
|
min2: 'حداقل 2 کاراکتر',
|
||||||
|
min4: 'حداقل 4 کاراکتر',
|
||||||
|
min8: 'حداقل 8 کاراکتر',
|
||||||
|
min10: 'حداقل 10 کاراکتر',
|
||||||
|
min20: 'حداقل 20 کاراکتر',
|
||||||
|
min30: 'حداقل 30 کاراکتر',
|
||||||
|
min40: 'حداقل 40 کاراکتر',
|
||||||
|
min50: 'حداقل 50 کاراکتر',
|
||||||
|
min60: 'حداقل 60 کاراکتر',
|
||||||
|
min100: 'حداقل 100 کاراکتر',
|
||||||
|
min120: 'حداقل 120 کاراکتر',
|
||||||
|
min150: 'حداقل 150 کاراکتر',
|
||||||
|
min200: 'حداقل 200 کاراکتر',
|
||||||
|
data_size: 'حجم قابل قبول حداقل: ',
|
||||||
|
image_width_size: 'عرض حداقل: ',
|
||||||
|
image_height_size: 'ارتفاع حداقل: '
|
||||||
|
},
|
||||||
|
max_char: {
|
||||||
|
max4: 'حداکثر 4 کاراکتر',
|
||||||
|
max8: 'حداکثر 8 کاراکتر',
|
||||||
|
max10: 'حداکثر 10 کاراکتر',
|
||||||
|
max15: 'حداکثر 15 کاراکتر',
|
||||||
|
max20: 'حداکثر 20 کاراکتر',
|
||||||
|
max30: 'حداکثر 30 کاراکتر',
|
||||||
|
max40: 'حداکثر 40 کاراکتر',
|
||||||
|
max50: 'حداکثر 50 کاراکتر',
|
||||||
|
max60: 'حداکثر 60 کاراکتر',
|
||||||
|
max100: 'حداکثر 100 کاراکتر',
|
||||||
|
max120: 'حداکثر 120 کاراکتر',
|
||||||
|
max150: 'حداکثر 150 کاراکتر',
|
||||||
|
max200: 'حداکثر 200 کاراکتر',
|
||||||
|
data_size: 'حجم قابل قبول حداکثر: ',
|
||||||
|
image_width_size: 'عرض حداکثر: ',
|
||||||
|
image_height_size: 'ارتفاع حداکثر: '
|
||||||
|
},
|
||||||
|
not_found: {
|
||||||
|
user_id: 'کاربری با این مشخصات وجود ندارد',
|
||||||
|
admin_id: 'ادمینی با این مشخصات وجود ندارد',
|
||||||
|
order_id: 'سفارشی با این مشخصات وجود ندارد',
|
||||||
|
item_id: 'موردی با این مشخصات وجود ندارد',
|
||||||
|
password: 'رمز عبور یا آیدی درست نیست',
|
||||||
|
user_not_exist: 'اطلاعات یوزر موجود نیست'
|
||||||
|
},
|
||||||
|
duplicated: {
|
||||||
|
username: 'این نام کاربری از قبل وجود دارد',
|
||||||
|
email: 'این ایمیل از قبل وجود دارد',
|
||||||
|
name: 'نام تکراری است',
|
||||||
|
title: 'عنوان تکراری است',
|
||||||
|
phone_number: 'این شماره تماس از قبل وجود دارد',
|
||||||
|
link: 'این لینک تکراری است',
|
||||||
|
code: ' این کد تکراری است',
|
||||||
|
item: 'این مورد تگراری است',
|
||||||
|
shop: 'این فروشگاه وجود دارد'
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
permissions: 'شما مجوز کافی ندارید ',
|
||||||
|
logged_in: 'شما وارد سیستم شدید',
|
||||||
|
not_logged_in: 'شما وارد سیستم نشدید',
|
||||||
|
logged_out: 'شما از سیستم خارج شدید',
|
||||||
|
unauthenticated: 'غیرمجاز',
|
||||||
|
recovery_link: 'لینک بازیابی فرستاده شد',
|
||||||
|
success_save: 'با موفقیت ثبت شد',
|
||||||
|
success_remove: 'با موفقیت حذف شد',
|
||||||
|
cart_empty: 'سبد خرید خالی است',
|
||||||
|
already_has_address: 'آدرس قبلا اضافه شده',
|
||||||
|
activation_code: 'کد فعالسازی برای شما ارسال شد',
|
||||||
|
activation_email: 'ایمیل فعال سازی برای شما ارسال شد',
|
||||||
|
expired_reset_link: 'این لینک بازیابی منقضی شده است',
|
||||||
|
email_not_confirmed: 'ابتدا ایمیل خود را تایید کنید،لینک فعال سازی قبلا برای شما فرستاده شده است.',
|
||||||
|
expired_activation_link: 'این لینک فعال سازی منقضی شده است',
|
||||||
|
success_activation: 'اکانت شما با موفقیت فعال شد',
|
||||||
|
passwords_not_match: 'پسورد ها یکی نیست',
|
||||||
|
problem: 'مشکلی پیش آمده، لطفا دوباره تلاش کنید.',
|
||||||
|
latinChar: 'لطفا با حروف لاتین بنویسید',
|
||||||
|
persianChar: 'لطفا با حروف فارسی بنویسید',
|
||||||
|
whiteSpace: 'بین حروف و کلمات نباید فاصله باشد',
|
||||||
|
wrongLoginEmail: 'ایمیل یا رمز ورود اشتباه است',
|
||||||
|
wrongLoginNumber: 'شماره یا رمز ورود اشتباه است',
|
||||||
|
user_not_valid: 'اطلاعات یوزر معتبر نیست',
|
||||||
|
otp: 'کد اشتباه است'
|
||||||
|
},
|
||||||
|
file_types: {
|
||||||
|
jpg: 'فقط فرمت jpg قابل قبول است',
|
||||||
|
png: 'فقط فرمت png قابل قبول است',
|
||||||
|
gif: 'فقط فرمت gif قابل قبول است',
|
||||||
|
pdf: 'فقط فرمت pdf قابل قبول است',
|
||||||
|
txt: 'فقط فرمت txt قابل قبول است',
|
||||||
|
log: 'فقط فرمت log قابل قبول است',
|
||||||
|
mp3: 'فقط فرمت mp3 قابل قبول است',
|
||||||
|
ogg: 'فقط فرمت ogg قابل قبول است',
|
||||||
|
wmv: 'فقط فرمت wmv قابل قبول است',
|
||||||
|
mp4: 'فقط فرمت mp4 قابل قبول است',
|
||||||
|
mov: 'فقط فرمت mov قابل قبول است',
|
||||||
|
mkv: 'فقط فرمت mkv قابل قبول است',
|
||||||
|
flv: 'فقط فرمت flv قابل قبول است'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
required: {
|
||||||
|
token: 'Token is required',
|
||||||
|
field: 'This field is required',
|
||||||
|
// developer validations
|
||||||
|
remember_me: 'Remember_me parameter required',
|
||||||
|
// registration validations
|
||||||
|
name: 'Enter name',
|
||||||
|
first_name: 'Enter first name',
|
||||||
|
last_name: 'Enter last name',
|
||||||
|
national_code: 'National code is required',
|
||||||
|
email: 'Enter email',
|
||||||
|
email_personal: 'Personal email is required',
|
||||||
|
email_company: 'Company email is required for legal entities',
|
||||||
|
company_name: 'Enter company name if you are a legal entity',
|
||||||
|
username: 'Enter username',
|
||||||
|
phone_number: 'Enter phone number',
|
||||||
|
password: 'Enter password',
|
||||||
|
birthdate: 'Enter birthdate',
|
||||||
|
// addressing validations
|
||||||
|
country: 'Enter country',
|
||||||
|
province: 'Enter province',
|
||||||
|
city: 'Enter city',
|
||||||
|
address: 'Enter address',
|
||||||
|
postal_code: 'Enter postal code',
|
||||||
|
plaque: 'Enter plaque',
|
||||||
|
receiver_first_name: 'Enter recipient name',
|
||||||
|
receiver_last_name: 'Enter recipient surname',
|
||||||
|
receiver_mobile: "Enter recipient's mobile number",
|
||||||
|
// global (post - gallery - ...)
|
||||||
|
title: 'Enter title',
|
||||||
|
caption: 'Enter caption',
|
||||||
|
description: 'Enter description',
|
||||||
|
category: 'Select category',
|
||||||
|
image: 'Image is required',
|
||||||
|
cover: 'Cover is required',
|
||||||
|
file: 'File is required',
|
||||||
|
message: 'Write message',
|
||||||
|
quantity: 'Enter quantity',
|
||||||
|
date: 'Enter date',
|
||||||
|
reason: 'Select reason',
|
||||||
|
question: 'Write the question',
|
||||||
|
answer: 'Write the answer',
|
||||||
|
price: 'Enter Price',
|
||||||
|
type: 'Select type',
|
||||||
|
discount_code: 'Enter discount code',
|
||||||
|
discount_amount: 'Enter discount amount',
|
||||||
|
discount_expire_date: 'Specify discount code expiration date',
|
||||||
|
user_id: 'Select user',
|
||||||
|
video: 'Video is required'
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
phone_number: 'Phone number format in incorrect',
|
||||||
|
email: 'Email format is not correct',
|
||||||
|
number: 'Value must be number',
|
||||||
|
boolean: 'Value must be Boolean',
|
||||||
|
image: 'Photo format is not acceptable',
|
||||||
|
video: 'Video format is not acceptable',
|
||||||
|
national_code: 'National code format is not correct'
|
||||||
|
},
|
||||||
|
min_char: {
|
||||||
|
min2: 'At least 2 characters',
|
||||||
|
min4: 'At least 4 characters',
|
||||||
|
min8: 'At least 8 characters',
|
||||||
|
min10: 'At least 10 characters',
|
||||||
|
min20: 'At least 20 characters',
|
||||||
|
min30: 'At least 30 characters',
|
||||||
|
min40: 'At least 40 characters',
|
||||||
|
min50: 'At least 50 characters',
|
||||||
|
min60: 'At least 60 characters',
|
||||||
|
min100: 'At least 100 characters',
|
||||||
|
min120: 'At least 120 characters',
|
||||||
|
min150: 'At least 150 characters',
|
||||||
|
min200: 'At least 200 characters',
|
||||||
|
data_size: 'Acceptable minimum size: ',
|
||||||
|
image_width_size: 'Minimum width: ',
|
||||||
|
image_height_size: 'Minimum height: '
|
||||||
|
},
|
||||||
|
max_char: {
|
||||||
|
max4: 'Maximum 4 characters',
|
||||||
|
max8: 'Maximum 8 characters',
|
||||||
|
max10: 'Maximum 10 characters',
|
||||||
|
max15: 'Maximum 15 characters',
|
||||||
|
max20: 'Maximum 20 characters',
|
||||||
|
max30: 'Maximum 30 characters',
|
||||||
|
max40: 'Maximum 40 characters',
|
||||||
|
max50: 'Maximum 50 characters',
|
||||||
|
max60: 'Maximum 60 characters',
|
||||||
|
max100: 'Maximum 100 characters',
|
||||||
|
max120: 'Maximum 120 characters',
|
||||||
|
max150: 'Maximum 150 characters',
|
||||||
|
max200: 'Maximum 200 characters',
|
||||||
|
data_size: 'Maximum acceptable size: ',
|
||||||
|
image_width_size: 'Maximum width: ',
|
||||||
|
image_height_size: 'Maximum height: '
|
||||||
|
},
|
||||||
|
not_found: {
|
||||||
|
user_id: 'There is no user with this profile',
|
||||||
|
admin_id: 'There is no admin with this profile',
|
||||||
|
order_id: 'There is no order with this profile',
|
||||||
|
item_id: 'There is no item with this specification',
|
||||||
|
password: 'Password or ID is incorrect'
|
||||||
|
},
|
||||||
|
duplicated: {
|
||||||
|
username: 'This username already exists',
|
||||||
|
email: 'This email already exists',
|
||||||
|
name: 'Name already exists',
|
||||||
|
title: 'Title already exists',
|
||||||
|
phone_number: 'Phone number already exists'
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
logged_in: 'You are logged in',
|
||||||
|
not_logged_in: 'You are not logged in',
|
||||||
|
logged_out: 'You are logged out',
|
||||||
|
unauthenticated: 'unauthenticated',
|
||||||
|
recovery_link: 'Recovery link sent',
|
||||||
|
success_save: 'Successfully saved',
|
||||||
|
success_remove: 'Successfully removed',
|
||||||
|
cart_empty: 'Cart is empty',
|
||||||
|
already_has_address: 'Already has address',
|
||||||
|
activation_code: 'Activation code sent to you',
|
||||||
|
activation_email: 'Activation email sent to you',
|
||||||
|
expired_reset_link: 'The current reset pass link has been expired',
|
||||||
|
email_not_confirmed: 'Confirm your email first, the activation link has already been sent to you.',
|
||||||
|
expired_activation_link: 'This activation link has expired',
|
||||||
|
success_activation: 'Your account has been successfully activated',
|
||||||
|
passwords_not_match: 'Passwords are not the same',
|
||||||
|
problem: 'There is a problem, please try again.',
|
||||||
|
latinChar: 'Please write in Latin letters',
|
||||||
|
persianChar: 'Please write in Persian letters',
|
||||||
|
whiteSpace: 'There should be no space between letters and words'
|
||||||
|
},
|
||||||
|
file_types: {
|
||||||
|
jpg: 'Only jpg format is acceptable',
|
||||||
|
png: 'Only png format is acceptable',
|
||||||
|
gif: 'Only gif format is acceptable',
|
||||||
|
pdf: 'Only pdf format is acceptable',
|
||||||
|
txt: 'Only txt format is acceptable',
|
||||||
|
log: 'Only log format is acceptable',
|
||||||
|
mp3: 'Only mp3 format is acceptable',
|
||||||
|
ogg: 'Only ogg format is acceptable',
|
||||||
|
wmv: 'Only wmv format is acceptable',
|
||||||
|
mp4: 'Only mp4 format is acceptable',
|
||||||
|
mov: 'Only mov format is acceptable',
|
||||||
|
mkv: 'Only mkv format is acceptable',
|
||||||
|
flv: 'Only flv format is acceptable'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
de: {
|
||||||
|
required: {
|
||||||
|
token: 'Token is required',
|
||||||
|
field: 'This field is required',
|
||||||
|
// developer validations
|
||||||
|
remember_me: 'Remember_me-Parameter erforderlich',
|
||||||
|
// registration validations
|
||||||
|
name: 'Name eingeben',
|
||||||
|
first_name: 'Name eingeben',
|
||||||
|
last_name: 'Nachnamen eingeben',
|
||||||
|
national_code: 'Nationaler Code ist erforderlich',
|
||||||
|
email: 'Email eingeben',
|
||||||
|
email_personal: 'Persönliche E-Mail ist erforderlich',
|
||||||
|
email_company: 'Für juristische Personen ist eine Unternehmens-E-Mail erforderlich',
|
||||||
|
company_name: 'Geben Sie den Firmennamen ein, wenn Sie eine juristische Person sind',
|
||||||
|
username: 'Geben Sie den Benutzernamen ein',
|
||||||
|
phone_number: 'Telefonnummer eingeben',
|
||||||
|
password: 'Passwort eingeben',
|
||||||
|
birthdate: 'Enter birthdate',
|
||||||
|
// addressing validations
|
||||||
|
country: 'Land eingeben',
|
||||||
|
province: 'Stadt betreten',
|
||||||
|
city: 'Stadt betreten',
|
||||||
|
address: 'Adresse eingeben',
|
||||||
|
postal_code: 'Postleitzahl eingeben',
|
||||||
|
plaque: 'Plakette eingeben',
|
||||||
|
receiver_first_name: 'Empfängername eingeben',
|
||||||
|
receiver_last_name: 'Nachname des Empfängers eingeben',
|
||||||
|
receiver_mobile: 'Handynummer des Empfängers eingebenr',
|
||||||
|
// global (post - gallery - ...)
|
||||||
|
title: 'Titel eingeben',
|
||||||
|
caption: 'Beschriftung eingeben',
|
||||||
|
description: 'Beschreibung eingeben',
|
||||||
|
category: 'Kategorie wählen',
|
||||||
|
image: 'Bild ist erforderlich',
|
||||||
|
cover: 'Bild ist erforderlich Abdeckung ist erforderlich',
|
||||||
|
file: 'Datei ist erforderlich',
|
||||||
|
message: 'Nachricht schreiben',
|
||||||
|
quantity: 'Menge eingeben',
|
||||||
|
date: 'Enter date',
|
||||||
|
reason: 'Grund auswählen',
|
||||||
|
question: 'Schreibe die Frage',
|
||||||
|
answer: 'Schreibe die Antwort',
|
||||||
|
price: 'Enter Price',
|
||||||
|
type: 'Select type',
|
||||||
|
discount_code: 'Enter discount code',
|
||||||
|
discount_amount: 'Enter discount amount',
|
||||||
|
discount_expire_date: 'Specify discount code expiration date',
|
||||||
|
user_id: 'Select user',
|
||||||
|
video: 'Video is required'
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
phone_number: 'Telefonnummernformat falsch',
|
||||||
|
email: 'E-Mail-Format nicht korrekt',
|
||||||
|
number: 'Wert muss Nummer sein',
|
||||||
|
boolean: 'Wert muss Boolescher Wert sein',
|
||||||
|
image: 'Photo format is not acceptable',
|
||||||
|
video: 'Video format is not acceptable',
|
||||||
|
national_code: 'Nationales Codeformat ist nicht korrekt'
|
||||||
|
},
|
||||||
|
min_char: {
|
||||||
|
min2: 'Mindestens 2 Zeichen',
|
||||||
|
min4: 'Mindestens 4 Zeichen',
|
||||||
|
min8: 'Mindestens 8 Zeichen',
|
||||||
|
min10: 'Mindestens 10 Zeichen',
|
||||||
|
min20: 'Mindestens 20 Zeichen',
|
||||||
|
min30: 'Mindestens 30 Zeichen',
|
||||||
|
min40: 'Mindestens 40 Zeichen',
|
||||||
|
min50: 'Mindestens 50 Zeichen',
|
||||||
|
min60: 'Mindestens 60 Zeichen',
|
||||||
|
min100: 'Mindestens 100 Zeichen',
|
||||||
|
min120: 'Mindestens 120 Zeichen',
|
||||||
|
min150: 'Mindestens 150 Zeichen',
|
||||||
|
min200: 'Mindestens 200 Zeichen',
|
||||||
|
data_size: 'Akzeptable Mindestgröße: ',
|
||||||
|
image_width_size: 'Mindestbreite: ',
|
||||||
|
image_height_size: 'Mindesthöhe: '
|
||||||
|
},
|
||||||
|
max_char: {
|
||||||
|
max4: 'Maximal 4 Zeichen',
|
||||||
|
max8: 'Maximal 8 Zeichen',
|
||||||
|
max10: 'Maximal 10 Zeichen',
|
||||||
|
max15: 'Maximal 15 Zeichen',
|
||||||
|
max20: 'Maximal 20 Zeichen',
|
||||||
|
max30: 'Maximal 30 Zeichen',
|
||||||
|
max40: 'Maximal 40 Zeichen',
|
||||||
|
max50: 'Maximal 50 Zeichen',
|
||||||
|
max60: 'Maximal 60 Zeichen',
|
||||||
|
max100: 'Maximal 100 Zeichen',
|
||||||
|
max120: 'Maximal 120 Zeichen',
|
||||||
|
max150: 'Maximal 150 Zeichen',
|
||||||
|
max200: 'Maximal 200 Zeichen',
|
||||||
|
data_size: 'Maximal zulässige Größe: ',
|
||||||
|
image_width_size: 'Maximale Breite: ',
|
||||||
|
image_height_size: 'Maximale Höhe: '
|
||||||
|
},
|
||||||
|
not_found: {
|
||||||
|
user_id: 'Es gibt keinen Benutzer mit diesem Profil',
|
||||||
|
admin_id: 'Es gibt keinen Administrator mit diesem Profil',
|
||||||
|
order_id: 'Es gibt keine Bestellung mit diesem Profil',
|
||||||
|
item_id: 'Es gibt keinen Artikel mit dieser Spezifikation',
|
||||||
|
password: 'Passwort oder ID ist falsch'
|
||||||
|
},
|
||||||
|
duplicated: {
|
||||||
|
username: 'Dieser Benutzername existiert bereits',
|
||||||
|
email: 'Diese E-Mail existiert bereits',
|
||||||
|
name: 'Name ist doppelt',
|
||||||
|
title: 'Titel ist doppelt',
|
||||||
|
phone_number: 'Phone number already exists'
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
logged_in: 'Sie sind angemeldet',
|
||||||
|
not_logged_in: 'Sie sind nicht angemeldet',
|
||||||
|
logged_out: 'Sie sind abgemeldet',
|
||||||
|
unauthenticated: 'nicht authentifiziert',
|
||||||
|
recovery_link: 'Wiederherstellungslink gesendet',
|
||||||
|
success_save: 'Erfolgreich gespeichert',
|
||||||
|
success_remove: 'Erfolgreich entfernt',
|
||||||
|
cart_empty: 'Warenkorb ist leer',
|
||||||
|
ready_has_address: 'Hat bereits Adresse',
|
||||||
|
activation_code: 'Activation code sent to you',
|
||||||
|
activation_email: 'Activation email sent to you',
|
||||||
|
expired_reset_link: 'Der aktuelle Reset-Pass-Link ist abgelaufen',
|
||||||
|
email_not_confirmed: 'Bestätigen Sie zuerst Ihre E-Mail, der Aktivierungslink wurde bereits an Sie gesendet.',
|
||||||
|
expired_activation_link: 'Dieser Aktivierungslink ist abgelaufen',
|
||||||
|
success_activation: 'Ihr Konto wurde erfolgreich aktiviert',
|
||||||
|
passwords_not_match: 'Passwörter sind nicht dasselbe',
|
||||||
|
problem: 'Es gibt ein Problem, bitte versuchen Sie es erneut.',
|
||||||
|
latinChar: 'Please write in Latin letters',
|
||||||
|
persianChar: 'Please write in Persian letters',
|
||||||
|
whiteSpace: 'There should be no space between letters and words'
|
||||||
|
},
|
||||||
|
file_types: {
|
||||||
|
jpg: 'Nur das jpg-Format ist akzeptabel',
|
||||||
|
png: 'Nur das png-Format ist akzeptabel',
|
||||||
|
gif: 'Nur das gif-Format ist akzeptabel',
|
||||||
|
pdf: 'Nur das PDF-Format ist akzeptabel',
|
||||||
|
txt: 'Nur das txt-Format ist akzeptabel',
|
||||||
|
log: 'Nur das log-Format ist akzeptabel',
|
||||||
|
mp3: 'Nur das mp3-Format ist akzeptabel',
|
||||||
|
ogg: 'Nur das ogg-Format ist akzeptabel',
|
||||||
|
wmv: 'Nur das wmv-Format ist akzeptabel',
|
||||||
|
mp4: 'Nur das mp4-Format ist akzeptabel',
|
||||||
|
mov: 'Nur das mov-Format ist akzeptabel',
|
||||||
|
mkv: 'Nur das mkv-Format ist akzeptabel',
|
||||||
|
flv: 'Nur das flv-Format ist akzeptabel'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tr: {
|
||||||
|
required: {
|
||||||
|
token: 'Token is required',
|
||||||
|
field: 'This field is required',
|
||||||
|
// geliştirici doğrulamaları
|
||||||
|
Remember_me: 'Remember_me parametresi gerekli',
|
||||||
|
// kayıt doğrulamaları
|
||||||
|
name: 'Adı girin',
|
||||||
|
first_name: 'Adı girin',
|
||||||
|
last_name: 'Soyadı girin',
|
||||||
|
national_code: 'Nationaler Kodu erforderlich',
|
||||||
|
email: 'E-posta girin',
|
||||||
|
email_personal: 'Kişisel e-posta gereklidir',
|
||||||
|
email_company: 'Tüzel kişiler için şirket e-postası gereklidir',
|
||||||
|
company_name: 'Tüzel kişiyseniz şirket adını girin',
|
||||||
|
username: 'Kullanıcı adını girin',
|
||||||
|
phone_number: 'Telefon numarasını girin',
|
||||||
|
password: 'Şifre girin',
|
||||||
|
birthdate: 'Enter birthdate',
|
||||||
|
// doğrulamaları adresleme
|
||||||
|
country: 'Ülke girin',
|
||||||
|
province: 'İl girin',
|
||||||
|
city: 'Şehir girin',
|
||||||
|
address: 'Adres girin',
|
||||||
|
postal_code: 'Posta kodunu girin',
|
||||||
|
plaque: 'Plak girin',
|
||||||
|
receiver_first_name: 'Alıcı adını girin',
|
||||||
|
receiver_last_name: 'Alıcının soyadını girin',
|
||||||
|
receiver_mobile: 'Alıcının cep telefonu numarasını girin',
|
||||||
|
// global (post - galeri - ...)
|
||||||
|
title: 'Başlığı girin',
|
||||||
|
caption: 'Başlık girin',
|
||||||
|
description: 'Açıklama girin',
|
||||||
|
category: 'Kategori seçin',
|
||||||
|
image: 'Resim gerekli',
|
||||||
|
cover: 'Kapak gereklidir',
|
||||||
|
file: 'Dosya gerekli',
|
||||||
|
message: 'Mesaj yaz',
|
||||||
|
quantity: 'Miktar girin',
|
||||||
|
date: 'Enter date',
|
||||||
|
reason: 'Nedeni seçin',
|
||||||
|
question: 'Soruyu yazın',
|
||||||
|
answer: 'Cevabı yaz',
|
||||||
|
price: 'Enter Price',
|
||||||
|
type: 'Select type',
|
||||||
|
discount_code: 'Enter discount code',
|
||||||
|
discount_amount: 'Enter discount amount',
|
||||||
|
discount_expire_date: 'Specify discount code expiration date',
|
||||||
|
user_id: 'Select user',
|
||||||
|
video: 'Video is required'
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
phone_number: 'Telefon numarası biçimi yanlış',
|
||||||
|
email: 'E-posta formatı doğru değil',
|
||||||
|
number: 'Değer sayı olmalıdır',
|
||||||
|
boolean: 'Değer Boole olmalıdır',
|
||||||
|
image: 'Photo format is not acceptable',
|
||||||
|
video: 'Video format is not acceptable',
|
||||||
|
national_code: 'Ulusal kod formatı doğru değil'
|
||||||
|
},
|
||||||
|
min_char: {
|
||||||
|
min2: 'En az 2 karakter',
|
||||||
|
min4: 'En az 4 karakter',
|
||||||
|
min8: 'En az 8 karakter',
|
||||||
|
min10: 'En az 10 karakter',
|
||||||
|
min20: 'En az 20 karakter',
|
||||||
|
min30: 'En az 30 karakter',
|
||||||
|
min40: 'En az 40 karakter',
|
||||||
|
min50: 'En az 50 karakter',
|
||||||
|
min60: 'En az 60 karakter',
|
||||||
|
min100: 'En az 100 karakter',
|
||||||
|
min120: 'En az 120 karakter',
|
||||||
|
min150: 'En az 150 karakter',
|
||||||
|
min200: 'En az 200 karakter',
|
||||||
|
data_size: 'Kabul edilebilir minimum boyut: ',
|
||||||
|
image_width_size: 'Minimum genişlik: ',
|
||||||
|
image_height_size: 'Minimum yükseklik: '
|
||||||
|
},
|
||||||
|
max_char: {
|
||||||
|
max4: 'Maksimum 4 karakter',
|
||||||
|
max8: 'Maksimum 8 karakter',
|
||||||
|
max10: 'Maksimum 10 karakter',
|
||||||
|
max15: 'Maksimum 15 karakter',
|
||||||
|
max20: 'Maksimum 20 karakter',
|
||||||
|
max30: 'Maksimum 30 karakter',
|
||||||
|
max40: 'Maksimum 40 karakter',
|
||||||
|
max50: 'Maksimum 50 karakter',
|
||||||
|
max60: 'Maksimum 60 karakter',
|
||||||
|
max100: 'Maksimum 100 karakter',
|
||||||
|
max120: 'Maksimum 120 karakter',
|
||||||
|
max150: 'Maksimum 150 karakter',
|
||||||
|
max200: 'Maksimum 200 karakter',
|
||||||
|
data_size: 'Kabul edilebilir maksimum boyut: ',
|
||||||
|
image_width_size: 'Maksimum genişlik: ',
|
||||||
|
image_height_size: 'Maksimum yükseklik: '
|
||||||
|
},
|
||||||
|
not_found: {
|
||||||
|
user_id: 'Bu profile sahip kullanıcı yok',
|
||||||
|
admin_id: 'Bu profile sahip yönetici yok',
|
||||||
|
order_id: 'Bu profilde sipariş yok',
|
||||||
|
item_id: 'Bu spesifikasyona sahip hiçbir öğe yok',
|
||||||
|
password: 'Şifre veya kimlik yanlış'
|
||||||
|
},
|
||||||
|
duplicated: {
|
||||||
|
username: 'Bu kullanıcı adı zaten mevcut',
|
||||||
|
email: 'Bu email zaten var',
|
||||||
|
name: 'Ad çift',
|
||||||
|
title: 'Başlık yineleniyor',
|
||||||
|
phone_number: 'Phone number already exists'
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
logged_in: 'Giriş yaptınız',
|
||||||
|
not_logged_in: 'Giriş yapmadınız',
|
||||||
|
logged_out: 'Çıkış yaptınız',
|
||||||
|
unauthenticated: 'unauthenticated',
|
||||||
|
recovery_link: 'Kurtarma bağlantısı gönderildi',
|
||||||
|
success_save: 'Başarıyla kaydedildi',
|
||||||
|
success_remove: 'Başarıyla kaldırıldı',
|
||||||
|
cart_empty: 'Sepet boş',
|
||||||
|
already_has_address: 'Zaten adresi var',
|
||||||
|
activation_code: 'Activation code sent to you',
|
||||||
|
activation_email: 'Activation email sent to you',
|
||||||
|
expired_reset_link: 'Mevcut sıfırlama geçiş bağlantısının süresi doldu',
|
||||||
|
email_not_confirmed: 'Önce e-postanızı onaylayın, aktivasyon bağlantısı size zaten gönderildi.',
|
||||||
|
expired_activation_link: 'Bu aktivasyon bağlantısının süresi doldu',
|
||||||
|
success_activation: 'Hesabınız başarıyla etkinleştirildi',
|
||||||
|
passwords_not_match: 'Şifreler aynı değil',
|
||||||
|
problem: 'Bir sorun var, lütfen tekrar deneyin.',
|
||||||
|
latinChar: 'Please write in Latin letters',
|
||||||
|
persianChar: 'Please write in Persian letters',
|
||||||
|
whiteSpace: 'There should be no space between letters and words'
|
||||||
|
},
|
||||||
|
file_types: {
|
||||||
|
jpg: 'Yalnızca jpg formatı kabul edilebilir',
|
||||||
|
png: 'Sadece png formatı kabul edilebilir',
|
||||||
|
gif: 'Yalnızca gif formatı kabul edilebilir',
|
||||||
|
pdf: 'Yalnızca pdf formatı kabul edilebilir',
|
||||||
|
txt: 'Yalnızca txt formatı kabul edilebilir',
|
||||||
|
log: 'Yalnızca log formatı kabul edilebilir',
|
||||||
|
mp3: 'Yalnızca mp3 formatı kabul edilebilir',
|
||||||
|
ogg: 'Yalnızca ogg formatı kabul edilebilir',
|
||||||
|
wmv: 'Yalnızca wmv formatı kabul edilebilir',
|
||||||
|
mp4: 'Yalnızca mp4 formatı kabul edilebilir',
|
||||||
|
mov: 'Yalnızca mov formatı kabul edilebilir',
|
||||||
|
mkv: 'Yalnızca mkv formatı kabul edilebilir',
|
||||||
|
flv: 'Yalnızca flv biçimi kabul edilebilir'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
it: {
|
||||||
|
required: {
|
||||||
|
token: 'Token is required',
|
||||||
|
field: 'This field is required',
|
||||||
|
// convalide dello sviluppatore
|
||||||
|
Remember_me: 'Remember_me parameter required',
|
||||||
|
// convalide della registrazione
|
||||||
|
name: 'Inserisci nome',
|
||||||
|
first_name: 'Inserisci nome',
|
||||||
|
last_name: 'Inserisci il cognome',
|
||||||
|
national_code: 'Il codice Nationaler è comune',
|
||||||
|
email: 'Enter email',
|
||||||
|
email_personal: "L'email personale è obbligatoria",
|
||||||
|
email_company: "L'email aziendale è obbligatoria per le persone giuridiche",
|
||||||
|
company_name: "Inserisci il nome dell'azienda se sei una persona giuridica",
|
||||||
|
username: 'Inserisci nome utente',
|
||||||
|
phone_number: 'Inserisci numero di telefono',
|
||||||
|
password: 'Inserisci password',
|
||||||
|
birthdate: 'Enter birthdate',
|
||||||
|
// indirizzamento delle convalide
|
||||||
|
country: 'Inserisci paese',
|
||||||
|
province: 'Inserisci provincia',
|
||||||
|
city: 'Inserisci città',
|
||||||
|
address: 'Inserisci indirizzo',
|
||||||
|
postal_code: 'Inserisci codice postale',
|
||||||
|
plaque: 'Inserisci targa',
|
||||||
|
receiver_first_name: 'Inserisci il nome del destinatario',
|
||||||
|
receiver_last_name: 'Inserisci il cognome del destinatario',
|
||||||
|
receiver_mobile: 'Inserisci il numero di cellulare del destinatario',
|
||||||
|
// globale (post - gallery - ...)
|
||||||
|
title: 'Inserisci titolo',
|
||||||
|
caption: 'Inserisci didascalia',
|
||||||
|
description: 'Inserisci descrizione',
|
||||||
|
category: 'Seleziona categoria',
|
||||||
|
image: "L'immagine è obbligatoria",
|
||||||
|
cover: 'Cover is required',
|
||||||
|
file: 'Il file è obbligatorio',
|
||||||
|
message: 'Scrivi messaggio',
|
||||||
|
quantity: 'Inserisci quantità',
|
||||||
|
date: 'Enter date',
|
||||||
|
reason: 'Seleziona motivo',
|
||||||
|
question: 'Scrivi la domanda',
|
||||||
|
answer: 'Scrivi la risposta',
|
||||||
|
price: 'Enter Price',
|
||||||
|
type: 'Select type',
|
||||||
|
discount_code: 'Enter discount code',
|
||||||
|
discount_amount: 'Enter discount amount',
|
||||||
|
discount_expire_date: 'Specify discount code expiration date',
|
||||||
|
user_id: 'Select user',
|
||||||
|
video: 'Video is required'
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
phone_number: 'Formato del numero di telefono non corretto',
|
||||||
|
email: 'Formato email non corretto',
|
||||||
|
number: 'Il valore deve essere un numero',
|
||||||
|
boolean: 'Il valore deve essere booleano',
|
||||||
|
image: 'Photo format is not acceptable',
|
||||||
|
video: 'Video format is not acceptable',
|
||||||
|
national_code: 'Il formato del codice nazionale non è corretto'
|
||||||
|
},
|
||||||
|
min_char: {
|
||||||
|
min2: 'Almeno 2 caratteri',
|
||||||
|
min4: 'Almeno 4 caratteri',
|
||||||
|
min8: 'Almeno 8 caratteri',
|
||||||
|
min10: 'Almeno 10 caratteri',
|
||||||
|
min20: 'Almeno 20 caratteri',
|
||||||
|
min30: 'Almeno 30 caratteri',
|
||||||
|
min40: 'Almeno 40 caratteri',
|
||||||
|
min50: 'Almeno 50 caratteri',
|
||||||
|
min60: 'Almeno 60 caratteri',
|
||||||
|
min100: 'Almeno 100 caratteri',
|
||||||
|
min120: 'Almeno 120 caratteri',
|
||||||
|
min150: 'Almeno 150 caratteri',
|
||||||
|
min200: 'Almeno 200 caratteri',
|
||||||
|
data_size: 'Dimensione minima accettabile: ',
|
||||||
|
image_width_size: 'Larghezza minima: ',
|
||||||
|
image_height_size: 'Altezza minima: '
|
||||||
|
},
|
||||||
|
max_char: {
|
||||||
|
max4: 'Massimo 4 caratteri',
|
||||||
|
max8: 'Massimo 8 caratteri',
|
||||||
|
max10: 'Massimo 10 caratteri',
|
||||||
|
max15: 'Massimo 15 caratteri',
|
||||||
|
max20: 'Massimo 20 caratteri',
|
||||||
|
max30: 'Massimo 30 caratteri',
|
||||||
|
max40: 'Massimo 40 caratteri',
|
||||||
|
max50: 'Massimo 50 caratteri',
|
||||||
|
max60: 'Massimo 60 caratteri',
|
||||||
|
max100: 'Massimo 100 caratteri',
|
||||||
|
max120: 'Massimo 120 caratteri',
|
||||||
|
max150: 'Massimo 150 caratteri',
|
||||||
|
max200: 'Massimo 200 caratteri',
|
||||||
|
data_size: 'Dimensione massima accettabile: ',
|
||||||
|
image_width_size: 'Larghezza massima: ',
|
||||||
|
image_height_size: 'Altezza massima: '
|
||||||
|
},
|
||||||
|
not_found: {
|
||||||
|
user_id: 'Nessun utente con questo profilo',
|
||||||
|
admin_id: 'Nessun amministratore con questo profilo',
|
||||||
|
order_id: 'Nessun ordine con questo profilo',
|
||||||
|
item_id: 'Nessun articolo con questa specifica',
|
||||||
|
password: "La password o l'ID non sono corretti"
|
||||||
|
},
|
||||||
|
duplicated: {
|
||||||
|
username: 'Questo nome utente esiste già',
|
||||||
|
email: 'Questa email esiste già',
|
||||||
|
name: 'Il nome è duplicato',
|
||||||
|
title: 'Il titolo è duplicato',
|
||||||
|
phone_number: 'Phone number already exists'
|
||||||
|
},
|
||||||
|
response: {
|
||||||
|
logged_in: "Hai effettuato l'accesso",
|
||||||
|
not_logged_in: 'Non sei loggato',
|
||||||
|
logged_out: 'Sei disconnesso',
|
||||||
|
unauthenticated: 'unauthenticated',
|
||||||
|
recovery_link: 'Link di ripristino inviato',
|
||||||
|
success_save: 'Salvataggio riuscito',
|
||||||
|
success_remove: 'Rimosso con successo',
|
||||||
|
cart_empty: 'Il carrello è vuoto',
|
||||||
|
already_has_address: 'Ha già indirizzo',
|
||||||
|
activation_code: 'Activation code sent to you',
|
||||||
|
activation_email: 'Activation email sent to you',
|
||||||
|
expired_reset_link: "L'attuale link del passaggio di reimpostazione è scaduto",
|
||||||
|
email_not_confirmed: 'Conferma prima la tua email, il link di attivazione ti è già stato inviato.',
|
||||||
|
expired_activation_link: 'Questo link di attivazione è scaduto',
|
||||||
|
success_activation: 'Il tuo account è stato attivato con successo',
|
||||||
|
passwords_not_match: 'Le password non sono le stesse',
|
||||||
|
problem: 'Si è verificato un problema, riprova.',
|
||||||
|
latinChar: 'Please write in Latin letters',
|
||||||
|
persianChar: 'Please write in Persian letters',
|
||||||
|
whiteSpace: 'There should be no space between letters and words'
|
||||||
|
},
|
||||||
|
file_types: {
|
||||||
|
jpg: 'È accettabile solo il formato jpg',
|
||||||
|
png: 'È accettabile solo il formato png',
|
||||||
|
gif: 'È accettabile solo il formato GIF',
|
||||||
|
pdf: 'È accettabile solo il formato pdf',
|
||||||
|
txt: 'È accettabile solo il formato txt',
|
||||||
|
log: 'È accettabile solo il formato log',
|
||||||
|
mp3: 'È accettabile solo il formato mp3',
|
||||||
|
ogg: 'È accettabile solo il formato ogg',
|
||||||
|
wmv: 'È accettabile solo il formato wmv',
|
||||||
|
mp4: 'È accettabile solo il formato mp4',
|
||||||
|
mov: 'È accettabile solo il formato mov',
|
||||||
|
mkv: 'È accettabile solo il formato mkv',
|
||||||
|
flv: 'È accettabile solo il formato flv'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
supportedImageFormats: ['jpg', 'jpeg', 'png', 'svg', 'svg+xml', 'webp'],
|
||||||
|
supportedVideoFormats: ['mp4', 'wmv']
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const errorHandler = require("./middleware/errorHandler");
|
||||||
|
const db = require("./config/dbConnectoin");
|
||||||
|
const fileUpload = require("express-fileupload");
|
||||||
|
const path = require("path");
|
||||||
|
const swiftly = require("swiftly-tools");
|
||||||
|
const cron = require("cron").CronJob;
|
||||||
|
const { expressSharp, FsAdapter } = require('express-sharp')
|
||||||
|
const { functions } = require("./controllers/Users");
|
||||||
|
const { autoFetch } = require('express-route-detector')
|
||||||
|
var cors = require('cors')
|
||||||
|
require("dotenv").config();
|
||||||
|
|
||||||
|
// Init database
|
||||||
|
db();
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const port = process.env.PORT || 6060;
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
app.use(cors())
|
||||||
|
app.use(fileUpload());
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.urlencoded({ extended: false }));
|
||||||
|
app.use(swiftly.middleware.hsts)
|
||||||
|
app.use(swiftly.middleware.sign("Mr Swift"))
|
||||||
|
|
||||||
|
// The scheduled job
|
||||||
|
const job = new cron("0 0 * * *", function () {
|
||||||
|
functions.deleteUsers();
|
||||||
|
});
|
||||||
|
job.start();
|
||||||
|
|
||||||
|
// Routes
|
||||||
|
app.use(autoFetch(express))
|
||||||
|
app.use('/uploads', expressSharp({
|
||||||
|
imageAdapter: new FsAdapter(path.join(__dirname, 'uploads')),
|
||||||
|
}));
|
||||||
|
|
||||||
|
//Error handler
|
||||||
|
app.use(errorHandler.run);
|
||||||
|
|
||||||
|
//Init site data
|
||||||
|
Site.findOne({ profile: "main" }).then(async (data) => {
|
||||||
|
if (!data) {
|
||||||
|
await Site.create({
|
||||||
|
profile: "main",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(async (err) => {
|
||||||
|
await Site.create({
|
||||||
|
profile: "main",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`Server runing on port: ${port}`);
|
||||||
|
});
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
const createOrder = [
|
||||||
|
asyncHandler(async (req, res) => {
|
||||||
|
const {
|
||||||
|
discountCode,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
const userID = req.user.id;
|
||||||
|
|
||||||
|
const userData = await User.findById(req.user.id)
|
||||||
|
if (userData.cart.length <= 0) {
|
||||||
|
res.status(400)
|
||||||
|
throw new Error("سبد خرید خالی است")
|
||||||
|
}
|
||||||
|
const shippingAddress = userData.state + " - " + userData.city + " - " + userData.address + " - " + userData.postCode + " - " + userData.phoneNumber
|
||||||
|
const orderDate = new Date()
|
||||||
|
const data = {
|
||||||
|
userID,
|
||||||
|
totalAmount: 0,
|
||||||
|
shippingAddress,
|
||||||
|
orderDate,
|
||||||
|
status: "Pending",
|
||||||
|
};
|
||||||
|
|
||||||
|
let myPromise = new Promise(async function (myResolve, myReject) {
|
||||||
|
try {
|
||||||
|
let products = []
|
||||||
|
// Use Promise.all to wait for all asynchronous operations to complete
|
||||||
|
await Promise.all(
|
||||||
|
userData.cart.map(async (product) => {
|
||||||
|
const pd = await Product.findById(product.product);
|
||||||
|
if (pd.specialPrice) {
|
||||||
|
data.totalAmount = pd.specialPrice * product.quantity + data.totalAmount;
|
||||||
|
} else {
|
||||||
|
data.totalAmount = pd.price * product.quantity + data.totalAmount;
|
||||||
|
}
|
||||||
|
products.push({ product: pd.id, quantity: product.quantity, price: pd.price, specialPrice: pd.specialPrice })
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
data.products = products
|
||||||
|
// Resolve the main promise after all asynchronous operations are finished
|
||||||
|
myResolve(data);
|
||||||
|
} catch (error) {
|
||||||
|
// Reject the promise if an error occurs
|
||||||
|
myReject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (discountCode) {
|
||||||
|
const discount = await Discount.findOne({ discountCode });
|
||||||
|
if (!discount) {
|
||||||
|
res.status(404);
|
||||||
|
throw new Error(_sr.fa.not_found.item_id);
|
||||||
|
}
|
||||||
|
if (discount.expirationDate <= Date.now()) {
|
||||||
|
res.status(404);
|
||||||
|
throw new Error("این کد منقضی شده");
|
||||||
|
}
|
||||||
|
if (discount.use >= usageLimit) {
|
||||||
|
res.status(404);
|
||||||
|
throw new Error("این کد منقضی شده");
|
||||||
|
}
|
||||||
|
if (discount.usedBy.length > 0) {
|
||||||
|
let thisUser = true;
|
||||||
|
discount.usedBy.forEach((user) => {
|
||||||
|
if (user === userID) {
|
||||||
|
thisUser = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (thisUser) {
|
||||||
|
res.status(404);
|
||||||
|
throw new Error("این کد منقضی شده");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (discount.applicableProducts.length > 0) {
|
||||||
|
let thisProducts = true;
|
||||||
|
discount.applicableProducts.forEach((product) => {
|
||||||
|
userData.cart.forEach((productX) => {
|
||||||
|
if (product === productX) {
|
||||||
|
thisProducts = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (thisProducts) {
|
||||||
|
res.status(404);
|
||||||
|
throw new Error("این کد منقضی شده");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (discount.type) {
|
||||||
|
case "f":
|
||||||
|
data.priceWithDiscount = data.totalAmount - discount.amount;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "p":
|
||||||
|
const darsad = discount.amount / 100;
|
||||||
|
|
||||||
|
const manfi = data.totalAmount * darsad;
|
||||||
|
|
||||||
|
data.priceWithDiscount = data.totalAmount - manfi;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data.priceWithDiscount = data.totalAmount
|
||||||
|
}
|
||||||
|
|
||||||
|
var order
|
||||||
|
myPromise.then(async () => {
|
||||||
|
order = await Order.create(data);
|
||||||
|
let findOrder = await Order.findById(order._id).populate('products.product', ' title uid').populate('userID', sp.select.userCustom)
|
||||||
|
|
||||||
|
userData.cart.map(async (productData) => {
|
||||||
|
var pusher = productData
|
||||||
|
pusher.status = "Pending"
|
||||||
|
pusher.date = Date.now()
|
||||||
|
pusher.orderDate = Date.now()
|
||||||
|
const product = await Product.findById(productData.product)
|
||||||
|
pusher.price = product?.specialPrice || product.price
|
||||||
|
await Product.findByIdAndUpdate(
|
||||||
|
productData.product, {
|
||||||
|
order: product?.order + 1 || 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await Shop.findByIdAndUpdate(
|
||||||
|
product.shopID,
|
||||||
|
{
|
||||||
|
$push: { pendingProductss: pusher },
|
||||||
|
},
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const emailInfo = await Email.findOne({ status: data.status });
|
||||||
|
const smsInfo = await Sms.findOne({ status: data.status });
|
||||||
|
|
||||||
|
if (emailInfo.send) {
|
||||||
|
// email(userData.email, "Asan Market Order", emailInfo.body, emailInfo.html);
|
||||||
|
}
|
||||||
|
if (smsInfo.send) {
|
||||||
|
await sms(userData.phoneNumber, `سفارش شما با ایدیه ${findOrder?._id} در آسان مارکت ثبت شد و در انتظار پرداخت میباشد`);
|
||||||
|
}
|
||||||
|
|
||||||
|
userData.cart = []
|
||||||
|
userData.orders.push(order)
|
||||||
|
userData.save()
|
||||||
|
res.status(201).json(findOrder);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Asanmarket
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Asanmarket
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# Asanmarket
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Asanmarket
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user