2026-07-27 11:28:33 +08:00

470 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 ''
}