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