This commit is contained in:
Mr Swift
2024-04-27 20:10:55 +03:30
parent f52f5496c5
commit ee6bd01224
30 changed files with 6503 additions and 0 deletions
+16
View File
@@ -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
+23
View File
@@ -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'
}
}
+2
View File
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
+6
View File
@@ -0,0 +1,6 @@
/node_modules
.png
.jpg
.web
*.png
+19
View File
@@ -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;
+26
View File
@@ -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;
+57
View File
@@ -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)
})
})
}
+9
View File
@@ -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,
};
+55
View File
@@ -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
},
]
};
+60
View File
@@ -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
},
]
};
+11
View File
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./*"],
"@/*": ["./*"],
"~~/*": ["./*"],
"@@/*": ["./*"]
}
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"app":"api-asanmarket",
"port":"5050",
"disks":[
{
"name": "uploads",
"mountTo": "uploads"
}
],
"node": {
"version": "18"
}
}
+62
View File
@@ -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 };
+17
View File
@@ -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 };
+28
View File
@@ -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 };
+28
View File
@@ -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 };
+15
View File
@@ -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);
+59
View File
@@ -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);
+4648
View File
File diff suppressed because it is too large Load Diff
+34
View File
@@ -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"
}
}
+91
View File
@@ -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
}
+21
View File
@@ -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'
}
}
+219
View File
@@ -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,
};
+758
View File
@@ -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']
}
+58
View File
@@ -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}`);
});
+157
View File
@@ -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);
})
})
]
+3
View File
@@ -0,0 +1,3 @@
# Asanmarket
+3
View File
@@ -0,0 +1,3 @@
# Asanmarket
+1
View File
@@ -0,0 +1 @@
# Asanmarket
+3
View File
@@ -0,0 +1,3 @@
# Asanmarket