154 lines
5.7 KiB
JavaScript
154 lines
5.7 KiB
JavaScript
|
|
const BigNumber = require('bignumber.js');
|
||
|
|
|
||
|
|
exports.getPackageData = function (data, rest = {}) {
|
||
|
|
return {
|
||
|
|
...rest,
|
||
|
|
name: data.name.trim(),
|
||
|
|
cateId: typeof data.cateId === 'string' ? data.cateId : '',
|
||
|
|
desc: typeof data.desc === 'string' ? data.desc.trim() : '',
|
||
|
|
hasValidDays: typeof data.hasValidDays === 'boolean' ? data.hasValidDays : false,
|
||
|
|
validDays: typeof data.validDays === 'number' ? data.validDays : 0,
|
||
|
|
enableDiscount: typeof data.enableDiscount === 'boolean' ? data.enableDiscount : false,
|
||
|
|
minDiscount: typeof data.minDiscount === 'number' ? data.minDiscount : 10,
|
||
|
|
packageType: data.packageType,
|
||
|
|
packagePrice: data.packagePrice,
|
||
|
|
projectNumber: data.projectNumber,
|
||
|
|
projects: data.projects.map(i => ({
|
||
|
|
_id: i._id,
|
||
|
|
projectName: i.projectName,
|
||
|
|
projectCateId: i.projectCateId,
|
||
|
|
price: i.price,
|
||
|
|
number: i.number,
|
||
|
|
discount: i.discount,
|
||
|
|
required: i.required
|
||
|
|
}))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
exports.verifyPakcage = function (data) {
|
||
|
|
if (typeof data.name !== 'string' || data.name.trim() === '') {
|
||
|
|
return '套餐名称不能为空'
|
||
|
|
}
|
||
|
|
if (data.name.trim().length > 50) {
|
||
|
|
return '套餐名称不能超过50个字符'
|
||
|
|
}
|
||
|
|
if (data.desc && typeof data.desc !== 'string') {
|
||
|
|
return '套餐描述必须是字符串'
|
||
|
|
}
|
||
|
|
if (typeof data.desc === 'string' && data.desc.trim().length > 500) {
|
||
|
|
return '套餐描述不能超过500个字符'
|
||
|
|
}
|
||
|
|
if (typeof data.hasValidDays !== 'boolean') {
|
||
|
|
return '是否有有效期设置不正确'
|
||
|
|
}
|
||
|
|
if (data.hasValidDays && (typeof data.validDays !== 'number' || !(data.validDays > 0)) || data.validDays % 1 !== 0) {
|
||
|
|
return '有效天数无效'
|
||
|
|
}
|
||
|
|
if (typeof data.enableDiscount !== 'boolean') {
|
||
|
|
return '启用折扣设置不正确'
|
||
|
|
}
|
||
|
|
if (data.enableDiscount && (typeof data.minDiscount !== 'number' || !(data.minDiscount > 0 && data.minDiscount <= 10))) {
|
||
|
|
return '最小折扣无效'
|
||
|
|
}
|
||
|
|
if (typeof data.cateId !== 'string' || data.cateId.trim() === '') {
|
||
|
|
return '套餐分类不能为空'
|
||
|
|
}
|
||
|
|
if (data.enableDiscount && !checkDecimal(data.minDiscount, 2)) {
|
||
|
|
return '最小折扣最多支持2为小数'
|
||
|
|
}
|
||
|
|
if (!['fixed', 'free'].includes(data.packageType)) {
|
||
|
|
return '套餐类型不正确'
|
||
|
|
}
|
||
|
|
if (data.packagePrice === 'free' && (typeof data.packagePrice !== 'number' || !(data.packagePrice > 0))) {
|
||
|
|
return '套餐价格无效'
|
||
|
|
}
|
||
|
|
if (data.packagePrice === 'free' && !checkDecimal(data.packagePrice, 2)) {
|
||
|
|
return '套餐价格最多支持2位小数'
|
||
|
|
}
|
||
|
|
const msg = verifyPackageItems(data.projects, data.packageType);
|
||
|
|
if (msg) return msg;
|
||
|
|
if (typeof data.projectNumber !== 'number' || !(data.projectNumber > 0) || !checkDecimal(data.projectNumber, 0)) {
|
||
|
|
return '套餐项目数量设置不正确'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function verifyPackageItems(projects, packageType) {
|
||
|
|
if (!Array.isArray(projects) || projects.length === 0) {
|
||
|
|
return '套餐项目不能为空'
|
||
|
|
}
|
||
|
|
if (packageType === 'fixed' && projects.some(i => !(i._id && typeof i.projectName === 'string' && i.projectName.trim() !== '' && i.price && i.number && i.discount))) return '套餐项目信息不完整'
|
||
|
|
for (let project of projects) {
|
||
|
|
const name = project.projectName.trim();
|
||
|
|
if (typeof project._id !== 'string' || project._id.trim() === '') {
|
||
|
|
return `${name}数据设置不正确`
|
||
|
|
}
|
||
|
|
if (typeof project.price !== 'number' || !(project.price > 0)) {
|
||
|
|
return `${name}价格设置不正确`
|
||
|
|
}
|
||
|
|
// if (checkDecimal(project.price, 2)) {
|
||
|
|
// return `${name}价格最多支持2位小数`
|
||
|
|
// }
|
||
|
|
if (typeof project.number !== 'number' || !(project.number > 0) || !checkDecimal(project.number, 0)) {
|
||
|
|
return `${name} 项目数量设置不正确`
|
||
|
|
}
|
||
|
|
if (packageType === 'fixed') {
|
||
|
|
if (typeof project.discount !== 'number' || !(project.discount > 0 && project.discount <= 10 && checkDecimal(project.discount, 2))) {
|
||
|
|
return `${name} 折扣设置不正确`
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (typeof project.required !== 'boolean') {
|
||
|
|
return `${name} 是否必选设置不正确`
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 计算项目套餐价格
|
||
|
|
*/
|
||
|
|
exports.getPackageListWithPrice = function (packageList) {
|
||
|
|
if (!Array.isArray(packageList)) return [];
|
||
|
|
return packageList.map(p => {
|
||
|
|
const projectData = Array.isArray(p.packageProjects) ? p.packageProjects : [];
|
||
|
|
const _projects = Array.isArray(p.projects) ? p.projects : [];
|
||
|
|
let allProjectPrice = new BigNumber(0);
|
||
|
|
let count = 0;
|
||
|
|
const projects = _projects.map(i => {
|
||
|
|
const project = projectData.find(j => j._id === i._id);
|
||
|
|
let projectFee = 0
|
||
|
|
if (p.packageType === 'fixed') {
|
||
|
|
count += 1
|
||
|
|
const price = project && project.price >= 0 ? Number(project.price) : 0;
|
||
|
|
const discount = i.discount >= 0 ? Number(i.discount) : 10;
|
||
|
|
const number = i.number >= 0 ? Number(i.number) : 1;
|
||
|
|
projectFee = new BigNumber(price).multipliedBy(discount).dividedBy(10).multipliedBy(number).toNumber();
|
||
|
|
allProjectPrice = allProjectPrice.plus(projectFee);
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
...i,
|
||
|
|
projectName: project ? project.projectName : i.projectName,
|
||
|
|
price: project ? project.price : i.price,
|
||
|
|
number: i.number,
|
||
|
|
discount: i.discount,
|
||
|
|
projectFee,
|
||
|
|
lowestDiscount: project ? project.lowestDiscount : '',
|
||
|
|
}
|
||
|
|
})
|
||
|
|
const { packageProjects, ...rest } = p;
|
||
|
|
return {
|
||
|
|
...rest,
|
||
|
|
projects,
|
||
|
|
count,
|
||
|
|
packagePrice: p.packageType === 'fixed' ? allProjectPrice.toNumber() : p.packagePrice,
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function checkDecimal(num, len) {
|
||
|
|
if (typeof num !== 'number' || typeof len !== 'number' || !(len >= 0) || len % 1 !== 0) return false;
|
||
|
|
if (len === 0) return Number.isInteger(num);
|
||
|
|
return parseFloat(num.toFixed(len)) === num
|
||
|
|
}
|
||
|
|
|
||
|
|
|