470 lines
16 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
const dayjs = require("dayjs");
const logger = require("../../utils/logger");
const api = require("../../api");
let db = null;
exports.main = async (content, mongodb) => {
db = mongodb;
switch (content.type) {
case "batchUpdateCustomer":
return await this.batchUpdateCustomer(content);
case "searchCorpCustomer":
return await this.searchCorpCustomer(content);
}
};
exports.searchCorpCustomer = async function (context) {
if (!context.corpId) return { success: false, message: "机构id不能为空" };
try {
const query = { corpId: context.corpId };
const page = parseInt(context.page) > 0 ? parseInt(context.page) : 1;
const pageSize = parseInt(context.pageSize) > 0 ? parseInt(context.pageSize) : 10;
const andList = []; // 并且的查询条件列表
// 客户姓名筛选
if (typeof context.name === "string" && context.name.trim()) {
query.name = { $regex: ".*" + context.name.trim(), $options: "i" };
}
// 手机号筛选
if (typeof context.mobile === "string" && context.mobile.trim()) {
query.mobile = { $regex: ".*" + context.mobile.trim(), $options: "i" };
}
// 性别筛选
if (typeof context.sex === "string" && context.sex.trim()) {
query.sex = { $regex: ".*" + context.sex.trim(), $options: "i" };
}
// 客户阶段筛选
if (Array.isArray(context.customerStage) && context.customerStage.length) {
query.customerStage = { $in: context.customerStage }
}
// 客户来源筛选
if (Array.isArray(context.customerSource) && context.customerSource.length) {
query.customerSource = { $in: context.customerSource }
}
// 标签筛选
if (Array.isArray(context.tagIds) && context.tagIds.length) {
query.tagIds = { $in: context.tagIds }
}
// 添加类型筛选
if (context.addMethod) {
query.addMethod = context.addMethod;
}
// 创建人类型筛选
if (context.creators && context.creators.length) {
query.creator = { $in: context.creators };
}
// 根据外部联系人id筛选
if (context.externalUserId) {
query["externalUserId"] = context.externalUserId;
}
// 团队筛选
if (context.teamId === "NO_TEAM") {
query.teamId = { $in: [[], null, ""] }
} else if (context.teamId === "HAS_TEAM") {
query.teamId = { $nin: [[], null, ""] };
} else if (Array.isArray(context.teamId)) {
query.teamId = { $in: context.teamId };
} else if (context.teamId) {
query.teamId = context.teamId
}
// 筛选年龄区间
const minAge = parseInt(context.minAge);
const maxAge = parseInt(context.maxAge);
if (minAge >= 0 && maxAge >= 0) {
const minAgeStamp = dayjs().subtract(minAge, "year").endOf("day").valueOf();
const maxAgeStamp = dayjs().subtract(maxAge + 1, "year").startOf("day").valueOf();
andList.push({ $or: [{ age: { $gte: minAge, $lte: maxAge } }, { birthdayStamp: { $gt: maxAgeStamp, $lte: minAgeStamp } }] })
} else if (minAge >= 0) {
const minAgeStamp = dayjs().subtract(minAge, "year").endOf("day").valueOf();
andList.push({ $or: [{ age: { $gte: minAge } }, { birthdayStamp: { $lte: minAgeStamp } }] })
} else if (maxAge >= 0) {
const maxAgeStamp = dayjs().subtract(maxAge + 1, "year").startOf("day").valueOf();
andList.push({ $or: [{ age: { $lte: maxAge } }, { birthdayStamp: { $gte: maxAgeStamp } }] })
}
// 责任人筛选
if (context.customerType === "myCustomer") {
// 查询我的客户
query["personResponsibles"] = {
$elemMatch: {
corpUserId: context.userId,
teamId: context.teamId,
},
};
} else if (Array.isArray(context.personResponsibles) && context.personResponsibles.length) {
const personResponsibles = context.personResponsibles.filter(i => i !== "NO"); //过滤无责任人
const noPersonResponsible = context.personResponsibles.includes("NO"); //是否有 无责任人选项
const orList = [];
if (personResponsibles.length) {
orList.push({
$elemMatch: {
corpUserId: { $in: personResponsibles },
teamId: Array.isArray(context.teamId)
? { $in: context.teamId }
: context.teamId,
},
});
}
if (noPersonResponsible) {
orList.push({
$not: {
$elemMatch: {
teamId: Array.isArray(context.teamId)
? { $in: context.teamId }
: context.teamId,
},
},
});
}
if (orList.length === 1) {
query["personResponsibles"] = orList[0];
} else if (orList.length > 1) {
andList.push({
$or: orList.map(i => ({
personResponsibles: i
}))
})
}
}
// 网店报备责任人筛选
if (context.reportRersonResponsibles) {
query["personResponsibles"] = {
$elemMatch: {
corpUserId: { $in: context.reportRersonResponsibles },
},
};
}
// 筛选是否分组
if (context.hasGroup === "YES") {
const groupIds = await getGroupIds(context.corpId, context.teamId);
query["groupIds"] = { $in: groupIds };
} else if (context.hasGroup === "NO") {
const groupIds = await getGroupIds(context.corpId, context.teamId);
query["groupIds"] = { $nin: groupIds };
}
if (Array.isArray(context.groupIds)) {
query.groupIds = { $in: context.groupIds }
}
// 创建时间 筛选
const createTimeQuery = getTimeRange(context.startCreateTime, context.endCreateTime);
if (createTimeQuery) {
query.createTime = createTimeQuery;
}
// 最近到院时间筛选
const arriveTimeQuery = getTimeRange(context.startArriveTime, context.endArriveTime);
if (arriveTimeQuery)
query.lastVisitTime = arriveTimeQuery;
// 最近服务时间筛选
const serviceTimeQuery = getTimeRange(context.startServiceTime, context.endServiceTime);
if (serviceTimeQuery) {
query.serviceTime = serviceTimeQuery;
}
if (context.serviceTime === "NO") {
query.serviceTime = { $or: [{ $exists: false }, { $eq: "" }] };
}
// 入院时间筛选
if (Array.isArray(context.inHospitalDates) && context.inHospitalDates.length === 2) {
const inHospitalTimesQuery = getTimeRange(...context.inHospitalDates);
if (inHospitalTimesQuery) {
query.inHospitalTimes = inHospitalTimesQuery;
}
}
// 根据意向项目id筛选
if (Array.isArray(context.projectIds) && context.projectIds.length) {
query["projects._id"] = { $in: context.projectIds };
}
if (context.reportTeamId) {
query.reportTeamId = context.reportTeamId
};
if (Array.isArray(context.reportUserIds) && context.reportUserIds) {
query.reportUserId = { $in: context.reportUserIds };
}
const allQuery = andList.length ? { $and: [...andList, query] } : query;
// if ($or.length) query["$or"] = $or;
const total = await db.collection("member").countDocuments(allQuery);
let listQuery = [
{ $match: allQuery },
{ $sort: { createTime: -1 } },
{ $skip: pageSize * (page - 1) },
{ $limit: pageSize },
];
// 查询是否有回访计划
if (context.showHasPlan === "YES") {
listQuery.push(
{
$lookup: {
from: "to-do-events",
localField: "_id",
foreignField: "customerId",
as: "todo",
},
},
{
$addFields: {
hasPlan: {
$cond: {
if: {
$and: [
{ $in: ["untreated", "$todo.eventStatus"] },
{
$in: [context.createTeamId, "$todo.executeTeamId"],
},
],
},
then: true,
else: false,
},
},
},
},
{
$project: {
// 第六阶段:选择返回的字段
todo: 0,
},
}
);
}
// 查询消费金额
if (context.showConsumeAmount === "YES") {
listQuery.push({
$lookup: {
from: "consume-record",
localField: "_id",
foreignField: "customerId",
as: "consumeRecord",
},
});
}
const list = await db.collection("member").aggregate(listQuery).toArray();
const pages = Math.ceil(total / pageSize);
if (context.showProjectName === "YES") {
const projectIds = [];
list.forEach((item) => {
item.projectIds = Array.isArray(item.projects)
? item.projects
.map((project) => (project && project._id ? project._id : ""))
.filter(Boolean)
: [];
projectIds.push(...item.projectIds);
});
const res = await api.getCorpApi({
type: "getProjectNames",
corpId: context.corpId,
ids: projectIds,
});
const m = new Map();
const projects = res && Array.isArray(res.data) ? res.data : [];
projects.forEach((item) => {
if (item._id && item.projectName) {
m.set(item._id, item.projectName);
}
});
list.forEach((item) => {
item.projectNames = item.projectIds
.map((id) => m.get(id))
.filter(Boolean);
});
}
return { success: true, total, list, pages };
} catch (error) {
return {
success: false,
message: error.message,
};
}
};
async function getGroupIds(corpId, teamId) {
try {
// 1. 查询条件根据机构ID和团队ID筛选对应的分组数据
const query = { corpId, teamId };
// 2. 执行查询:获取符合条件的分组数据,使用 MongoDB 原生查询语法
const result = await db
.collection("group")
.find(query, { projection: { _id: 1 } })
.toArray();
// 3. 提取分组的ID并返回映射结果集合提取每个分组的ID字段
const groupIds = result.map((item) => item._id);
return groupIds; // 返回分组ID列表
} catch (error) {
// 4. 错误处理:如果查询发生错误,捕获异常并打印错误日志
logger.error("Error getting group IDs:", error);
return []; // 返回空数组,表示查询失败或无数据
}
}
/**
* 批量更新客户信息
* 暂支持 customerSource 客户来源及关联的推荐人
* 暂支持 tagIds 客户标签
* 暂支持 customerStage 客户阶段
* @param {*} context
* @returns
*/
exports.batchUpdateCustomer = async (context) => {
const { corpId, customerIds, modifyField } = context;
// 1. 验证输入参数
if (!corpId) return { success: false, message: "机构id不能为空" };
if (!Array.isArray(customerIds) || customerIds.length === 0)
return { success: false, message: "客户id不能为空" };
if (!["customerSource", "tagIds", "customerStage"].includes(modifyField)) {
return { success: false, message: "修改字段不存在或者修改字段不支持" };
}
try {
// 2. 批量修改客户来源
if (modifyField === "customerSource") {
const {
customerSource,
reference,
referenceCustomerId,
referenceType,
referenceUserId,
} = context;
// 2.1. 验证客户来源相关参数
if (
!Array.isArray(customerSource) ||
[reference, referenceCustomerId, referenceType, referenceUserId].some(
(i) => typeof i !== "string"
)
) {
return { success: false, message: "客户来源参数错误" };
}
// 2.2. 使用MongoDB原生查询批量更新
const updateResult = await db.collection("member").updateMany(
{ corpId, _id: { $in: customerIds } }, // 查询条件
{
$set: {
customerSource,
reference,
referenceCustomerId,
referenceType,
referenceUserId,
},
}
);
if (updateResult.modifiedCount > 0) {
return { success: true, message: "修改成功" };
} else {
return { success: false, message: "没有客户需要更新" };
}
}
// 3. 批量修改客户标签
else if (modifyField === "tagIds") {
const { tagIds, tagType } = context;
// 3.1. 验证标签参数
if (!Array.isArray(tagIds))
return { success: false, message: "标签类型错误" };
if (tagType === "cover") {
// 3.2. 覆盖原有标签
const updateResult = await db
.collection("member")
.updateMany(
{ corpId, _id: { $in: customerIds } },
{ $set: { tagIds } }
);
return updateResult.modifiedCount > 0
? { success: true, message: "修改成功" }
: { success: false, message: "没有客户需要更新" };
} else if (tagType === "append") {
// 3.3. 追加标签
if (tagIds.length === 0) return { success: true, message: "修改成功" };
const customerList = await db
.collection("member")
.find({ corpId, _id: { $in: customerIds } })
// .project({ _id: 1, tagIds: 1 })
.toArray();
if (customerList.length === 0)
return { success: false, message: "客户不存在" };
console.log("customerList", customerList);
// 合并标签并更新
const updatedCustomerList = customerList.map((customer) => {
const existingTagIds = Array.isArray(customer.tagIds)
? customer.tagIds
: [];
const newTagIds = Array.from(new Set([...existingTagIds, ...tagIds]));
return { _id: customer._id, tagIds: newTagIds };
});
console.log("updatedCustomerList", updatedCustomerList);
// 批量更新客户标签
const bulkOperations = updatedCustomerList.map((customer) => ({
updateOne: {
filter: { _id: customer._id },
update: { $set: { tagIds: customer.tagIds || [] } },
},
}));
const bulkWriteResult = await db
.collection("member")
.bulkWrite(bulkOperations);
return bulkWriteResult.modifiedCount > 0
? { success: true, message: "修改成功" }
: { success: false, message: "没有客户需要更新" };
} else {
return { success: false, message: "标签修改类型错误" };
}
}
// 4. 批量修改客户阶段
else if (modifyField === "customerStage") {
const { customerStage } = context;
// 4.1. 验证客户阶段参数
if (typeof customerStage !== "string")
return { success: false, message: "客户阶段参数错误" };
// 4.2. 使用MongoDB原生查询批量更新
const updateResult = await db
.collection("member")
.updateMany(
{ corpId, _id: { $in: customerIds } },
{ $set: { customerStage } }
);
return updateResult.modifiedCount > 0
? { success: true, message: "修改成功" }
: { success: false, message: "没有客户需要更新" };
}
} catch (error) {
// 错误处理:如果发生错误,返回错误信息
logger.error("批量更新客户时发生错误:", error);
return {
success: false,
message: error.message,
};
}
};
function getTimeRange(startTime, endTime) {
const startTimeStamp = startTime && dayjs(startTime).isValid() ? dayjs(startTime).valueOf() : 0;
const endTimeStamp = endTime && dayjs(endTime).isValid() ? dayjs(endTime).valueOf() : 0;
if (startTimeStamp && endTimeStamp) {
return { $gte: startTimeStamp, $lte: endTimeStamp }
}
if (startTimeStamp) {
return { $gte: startTimeStamp }
}
if (endTimeStamp) {
return { $lte: endTimeStamp }
}
return ''
}