1775 lines
48 KiB
JavaScript
1775 lines
48 KiB
JavaScript
const utils = require("../utils");
|
||
const dayjs = require("dayjs");
|
||
const helpers = require("./customer-util");
|
||
const sop = require("../sop");
|
||
const updateCustomer = require("./update");
|
||
const customerQuery = require("./query");
|
||
const common = require("../../common");
|
||
const appFunction = require("../app-function");
|
||
const api = require("../../api");
|
||
let db = null;
|
||
exports.main = async (content, DB) => {
|
||
db = DB;
|
||
switch (content.type) {
|
||
case "autoCreateMember":
|
||
return await autoCreateMember(content);
|
||
case "asyncCustomerTag":
|
||
return await asyncCustomerTag(content);
|
||
case "update":
|
||
return await updateMember(content);
|
||
case "add":
|
||
return await addMember(content);
|
||
case "deleteMember":
|
||
return await deleteMember(content);
|
||
case "getReferredPeople":
|
||
return await getReferredPeople(content);
|
||
case "setAgeToNumber":
|
||
return await setAgeToNumber();
|
||
case "getMember":
|
||
return await getMember(content);
|
||
case "getCustomerInSidebar":
|
||
return await getCustomerInSidebar(content);
|
||
case "batchImportCustomer":
|
||
return await batchImportCustomer(content);
|
||
case "getmemberCountForTeamId":
|
||
return await getmemberCountForTeamId(content);
|
||
case "getmemberAndserviceCountForUserId":
|
||
return await getmemberAndserviceCountForUserId(content);
|
||
case "getMemberInfo":
|
||
return await getMemberInfo(content);
|
||
case "getMemberForTeam":
|
||
return await getMemberForTeam(content);
|
||
case "getCorpCustomer":
|
||
return await getCorpCustomer(content);
|
||
case "getMemberBytags":
|
||
return await getMemberBytags(content);
|
||
case "externalUseridToMember":
|
||
return await externalUseridToMember(content);
|
||
case "editExternalContactRemark":
|
||
return await exports.editExternalContactRemark(content);
|
||
case "updateCustomerTimeField":
|
||
return await exports.updateCustomerTimeField(content);
|
||
case "getCustomerByUnionId":
|
||
return await exports.getCustomerByUnionId(content);
|
||
case "getCustomerNamesById":
|
||
return await exports.getCustomerNamesById(content);
|
||
case "triggerSoptaskByCustomerId":
|
||
return await triggerSoptaskByCustomerId(content);
|
||
case "updateCustomerInHospitalTime":
|
||
case "pushCustomerTeamId":
|
||
case "updateCustomerPersonResponsibles":
|
||
return await updateCustomer.main(content, db);
|
||
case "getCustomersCount":
|
||
case "getInHospitalCustomersCount":
|
||
return await customerQuery.main(content, db);
|
||
case "addConsumeRecord":
|
||
return await addConsumeRecord(content);
|
||
case "updateCustomerReportPeople":
|
||
return await updateCustomerReportPeople(content);
|
||
case "getCustomerReportLog":
|
||
return await getCustomerReportLog(content);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 自动建档
|
||
* @param {string} corpId 企业微信ID
|
||
* @param {string} env 环境ID
|
||
* @param {string} externalUserId 用户userId
|
||
* @param {string} name 用户姓名
|
||
* @param {string} relationship 关系
|
||
* @param {Array} tags 标签
|
||
* @returns
|
||
*/
|
||
|
||
/**
|
||
* 自动建档
|
||
* @param {string} corpId 企业微信ID
|
||
* @param {string} name 用户姓名
|
||
* @param {string} externalUserId 用户userId
|
||
* @param {object} params 其他参数
|
||
* @param {string} userId 用户ID
|
||
* @returns
|
||
*/
|
||
async function autoCreateMember({
|
||
corpId,
|
||
name,
|
||
externalUserId,
|
||
params,
|
||
userId,
|
||
}) {
|
||
const query = { corpId, externalUserId };
|
||
let data = await db.collection("member").find(query).toArray();
|
||
if (data.length > 0)
|
||
return {
|
||
success: true,
|
||
message: "该客户已存在",
|
||
};
|
||
if (!name) {
|
||
let externalUserIdInfo = await api.getWecomApi({
|
||
type: "getNameByexternalUserId",
|
||
externalUserId,
|
||
corpId,
|
||
});
|
||
let info = externalUserIdInfo.data;
|
||
if (info && info.name) name = info.name;
|
||
}
|
||
// 获取当前客户数据
|
||
const teamIds = await getTeamList(userId, corpId);
|
||
if (teamIds.length === 0) {
|
||
return {
|
||
success: false,
|
||
message: "请先创建团队",
|
||
};
|
||
}
|
||
const personResponsibles = teamIds.map((i) => {
|
||
return { corpUserId: userId, teamId: i };
|
||
});
|
||
console.log(" 外部联系人name", name);
|
||
const addQuery = {
|
||
_id: common.generateRandomString(24),
|
||
corpId,
|
||
name,
|
||
externalUserId,
|
||
relationship: "本人",
|
||
createTime: new Date().getTime(),
|
||
creator: "系统自动建档",
|
||
customerStage: "OMINHOSPITALA",
|
||
createType: "auto",
|
||
personResponsibles,
|
||
teamId: teamIds,
|
||
...params,
|
||
};
|
||
await addMember({ params: addQuery });
|
||
return {
|
||
success: true,
|
||
message: "自动建档成功",
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 自动化建档
|
||
* @param {string} corpId - 企业微信ID
|
||
*/
|
||
async function autoCustomerArchives(context, name, qrCodeInfo) {
|
||
const { ExternalUserID, CorpID, UserID } = context;
|
||
// 获取到teamId
|
||
const teamIds = await getTeamList(UserID, CorpID);
|
||
// 获取二维码数据
|
||
// 遍历teamIds建档
|
||
// 判断是否已经建档
|
||
const archivedCount = await db
|
||
.collection("member")
|
||
.find({
|
||
corpId: CorpID,
|
||
externalUserId: ExternalUserID,
|
||
})
|
||
.count();
|
||
console.log("已经建档数", archivedCount);
|
||
if (archivedCount > 0) return;
|
||
const { tagIds, customerSource } = qrCodeInfo;
|
||
const personResponsibles = teamIds.map((i) => {
|
||
return {
|
||
corpUserId: UserID,
|
||
teamId: i,
|
||
};
|
||
});
|
||
const params = {
|
||
_id: common.generateRandomString(24),
|
||
corpId: CorpID,
|
||
teamId: teamIds,
|
||
externalUserId: ExternalUserID,
|
||
relationship: "本人",
|
||
tagIds,
|
||
customerSource,
|
||
name,
|
||
personResponsibles,
|
||
createTime: new Date().getTime(),
|
||
creator: "扫码自动建档",
|
||
customerStage: "OMINHOSPITALA",
|
||
createType: "auto",
|
||
};
|
||
console.log("自动建档", params);
|
||
await db.collection("member").insertOne(params);
|
||
await addMember({});
|
||
}
|
||
|
||
// 根据userId和corpId获取团队列表
|
||
async function getTeamList(userId, corpId) {
|
||
const result = await api.getCorpApi({
|
||
type: "getTeamBymember",
|
||
corpUserId: userId,
|
||
corpId,
|
||
});
|
||
if (result && Array.isArray(result.data) && result.data.length > 0)
|
||
return result.data.map((item) => item.teamId);
|
||
else return [];
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param {string} corpId - 企业微信ID
|
||
* @param {string} env - 环境ID
|
||
* @param {string} externalUserId - 用户userId
|
||
* @param {string} name - 用户姓名
|
||
* @param {Array} tags - 标签
|
||
* @returns
|
||
*/
|
||
async function asyncCustomerTag({
|
||
corpId,
|
||
externalUserId,
|
||
tags,
|
||
name = "",
|
||
userId,
|
||
}) {
|
||
console.log("外部联系人企业微信标签", tags);
|
||
// 获取
|
||
let result = await api.getCorpApi({
|
||
type: "getCorpTags",
|
||
corpId,
|
||
});
|
||
console.log("获取到机构标签getCorpTags", result);
|
||
let corpAllTag = result.list || [];
|
||
// 筛选出机构中所有企业微信的标签
|
||
let corpWecomTagIds = [];
|
||
corpAllTag.forEach((item) => {
|
||
if (item.createType === "corpAsync") {
|
||
item.tag.forEach((tag) => {
|
||
corpWecomTagIds.push(tag.id);
|
||
});
|
||
}
|
||
});
|
||
console.log("筛选出机构中所有企业微信的标签", corpWecomTagIds);
|
||
let data = await db
|
||
.collection("member")
|
||
.find({ corpId, externalUserId })
|
||
.toArray();
|
||
if (data.length === 0) {
|
||
let params = {
|
||
tagIds: tags,
|
||
};
|
||
// 给客户自动建档
|
||
await autoCreateMember({ corpId, name, externalUserId, userId, params });
|
||
}
|
||
console.log("自动建档的员工", data);
|
||
// 合并标签
|
||
for (let i = 0; i < data.length; i++) {
|
||
let tag = data[i].tagIds || [];
|
||
let createType = data[i].createType;
|
||
// 筛选出客户标签中的企业微信标签
|
||
let memberWeComTagIds = tag.filter((item) =>
|
||
corpWecomTagIds.includes(item)
|
||
);
|
||
console.log("筛选出客户标签中的企业微信标签", memberWeComTagIds);
|
||
let newTagIds = tags;
|
||
// corpTagIds 比 newTagIds 多的id 是需要删除的
|
||
let delTagIds = memberWeComTagIds.filter(
|
||
(item) => !newTagIds.includes(item)
|
||
);
|
||
// corpTagIds 比 newTagIds 少的id 是需要新增的
|
||
let addTagIds = newTagIds.filter(
|
||
(item) => !memberWeComTagIds.includes(item)
|
||
);
|
||
// 删除标签
|
||
tag = tag.filter((item) => !delTagIds.includes(item));
|
||
// 新增标签
|
||
tag = Array.from(new Set([...tag, ...addTagIds]));
|
||
console.log("客户标签tagIds", tag);
|
||
let params = {
|
||
tagIds: tag,
|
||
};
|
||
if (createType === "auto") params["name"] = name;
|
||
console.log("更新标签参数", params);
|
||
await db
|
||
.collection("member")
|
||
.updateOne({ _id: data[i]._id }, { $set: params });
|
||
}
|
||
return {
|
||
success: true,
|
||
message: "更新标签成功",
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 合并自动建档
|
||
* @param {*} param0
|
||
* @returns
|
||
*/
|
||
async function asyncAutoCustomerArchives({
|
||
corpId,
|
||
externalUserId,
|
||
id,
|
||
createType,
|
||
}) {
|
||
if (!externalUserId || createType === "auto") return;
|
||
let autoCustomer = await db
|
||
.collection("member")
|
||
.findOne({ corpId, externalUserId, createType: "auto" });
|
||
console.log("获取到自动建档档案", autoCustomer);
|
||
if (autoCustomer) {
|
||
// 合并这些字段
|
||
let currentCustomer = await db.collection("member").findOne({ _id: id });
|
||
let { teamId = [], tagIds = [], personResponsibles = [] } = autoCustomer;
|
||
let {
|
||
tagIds: currentTagIds = [],
|
||
personResponsibles: currentPersonResponsibles = [],
|
||
customerSource: currentCustomerSource = [],
|
||
teamId: currentTeamId = [],
|
||
} = currentCustomer;
|
||
let newTeamId = Array.from(new Set([...teamId, ...currentTeamId])); // 合并团队
|
||
let newTag = Array.from(new Set([...tagIds, ...currentTagIds])); // 合并标签
|
||
let newPersonResponsible = personResponsibles || [];
|
||
currentPersonResponsibles.forEach((item) => {
|
||
if (
|
||
!personResponsibles.find(
|
||
(i) => i.teamId === item.teamId && i.corpUserId === item.corpUserId
|
||
)
|
||
) {
|
||
newPersonResponsible.push(item);
|
||
}
|
||
});
|
||
await db.collection("member").deleteOne({ _id: autoCustomer._id });
|
||
let params = {
|
||
tagIds: newTag,
|
||
personResponsibles: newPersonResponsible,
|
||
customerSource: currentCustomerSource,
|
||
updateTime: new Date().getTime(),
|
||
teamId: newTeamId,
|
||
createType: "manual",
|
||
};
|
||
await db.collection("member").updateOne({ _id: id }, { $set: params });
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param {string} id - 客户id
|
||
* @param {object} params - 更新参数
|
||
* @param {string} env - 环境ID
|
||
* @param {string} userId - 用户ID
|
||
* @returns
|
||
*/
|
||
async function updateMember({
|
||
id,
|
||
params,
|
||
userId,
|
||
corpId,
|
||
createTeamId,
|
||
createTeamName,
|
||
operationType,
|
||
}) {
|
||
const member = await db.collection("member").findOne({ _id: id });
|
||
if (params.corpId === "undefined" || !params.corpId) {
|
||
delete params.corpId;
|
||
}
|
||
params["updateTime"] = new Date().getTime();
|
||
if ("age" in params && params["age"] !== undefined) {
|
||
params["age"] = parseInt(params["age"]) > 0 ? parseInt(params["age"]) : "";
|
||
}
|
||
if (params.idCard) {
|
||
const { gender, birthDate, age } = utils.calculateIdCardInfo(params.idCard);
|
||
params.sex = gender;
|
||
params.birthday = birthDate;
|
||
params.age = age;
|
||
const repeatIdCardCount = await db.collection("member").countDocuments({
|
||
idCard: params.idCard,
|
||
_id: { $ne: id },
|
||
});
|
||
if (repeatIdCardCount > 0) {
|
||
return {
|
||
success: false,
|
||
message: "已存在相同身份证号档案!",
|
||
};
|
||
}
|
||
}
|
||
params.createType = "manual";
|
||
if (member.createType === "auto") params.creator = userId || "";
|
||
// 自动更新最新的出生日期时间戳
|
||
if (member && (params.idCard || params.birthday)) {
|
||
const mergeData = { ...member, ...params };
|
||
const birthdayStamp = helpers.getBirthdayStamp(mergeData);
|
||
if (birthdayStamp) params["birthdayStamp"] = birthdayStamp;
|
||
if (!mergeData.birthday && !mergeData.idCard && "birthdayStamp" in member) {
|
||
params["birthdayStamp"] = undefined;
|
||
}
|
||
}
|
||
await db.collection("member").updateOne({ _id: id }, { $set: params });
|
||
// 合并自动建档
|
||
const asyncAutoCustomerArchivesTask = asyncAutoCustomerArchives({
|
||
corpId,
|
||
externalUserId: params.externalUserId,
|
||
id,
|
||
createType: params.createType,
|
||
});
|
||
// 修改了名字, 同步到企业微信备注名
|
||
if (!params.externalUserId && params.unbindExternalUserId)
|
||
params.externalUserId = params.unbindExternalUserId;
|
||
let reMarkTask = null;
|
||
if (params.externalUserId || params.name) {
|
||
reMarkTask = exports.editExternalContactRemark({
|
||
corpId,
|
||
externalUserId: params.externalUserId,
|
||
memberId: id,
|
||
});
|
||
}
|
||
// 触发SOP任务
|
||
const query = {
|
||
...params,
|
||
externalUserId: member.externalUserId,
|
||
personResponsibles: member.personResponsibles,
|
||
};
|
||
if (
|
||
params.externalUserId &&
|
||
dayjs().startOf("day").valueOf() < member.createTime
|
||
) {
|
||
query.externalUserId = params.externalUserId;
|
||
query.createTime = member.createTime;
|
||
}
|
||
const sopTask = triggerSoptask({
|
||
corpId,
|
||
params: query,
|
||
customerId: id,
|
||
});
|
||
// 添加服务记录
|
||
const createServiceRecordTask = await createServiceRecordTaskFnc({
|
||
corpId,
|
||
id,
|
||
userId,
|
||
member,
|
||
createTeamId,
|
||
createTeamName,
|
||
operationType,
|
||
params,
|
||
});
|
||
await Promise.all([
|
||
asyncAutoCustomerArchivesTask,
|
||
reMarkTask,
|
||
sopTask,
|
||
...createServiceRecordTask,
|
||
]);
|
||
return {
|
||
success: true,
|
||
message: "更新成功",
|
||
};
|
||
}
|
||
// 创建服务记录
|
||
async function createServiceRecordTaskFnc({
|
||
corpId,
|
||
id,
|
||
userId = "",
|
||
member,
|
||
createTeamId,
|
||
createTeamName,
|
||
operationType,
|
||
params,
|
||
}) {
|
||
let customerName = params.name || member.name;
|
||
// 添加服务记录
|
||
let query = {
|
||
eventType: "customerUpdate",
|
||
customerId: id,
|
||
executorUserId: userId,
|
||
executeTeamId: createTeamId,
|
||
createTeamName,
|
||
creatorUserId: userId,
|
||
corpId,
|
||
customerName: customerName,
|
||
createTime: dayjs().valueOf(),
|
||
executionTime: dayjs().valueOf(),
|
||
customerUserId: member.externalUserId,
|
||
taskContent: `更新客户档案信息`,
|
||
};
|
||
if (member.createType === "auto") {
|
||
query.eventType = "remindFiling";
|
||
}
|
||
if (!userId) return [];
|
||
let addServiceRecordTaskList = [];
|
||
if (params.teamId && operationType === "adminEditTeam") {
|
||
let addTeamIds = params.teamId.filter(
|
||
(item) => !member.teamId.includes(item)
|
||
);
|
||
let removeTeamIds = member.teamId.filter(
|
||
(item) => !params.teamId.includes(item)
|
||
);
|
||
if (addTeamIds.length > 0) {
|
||
const teamNames = await getTeamNamesByTeamIds({
|
||
corpId,
|
||
teamIds: addTeamIds,
|
||
});
|
||
query.eventType = "adminAllocateTeams";
|
||
query.taskContent = `管理员把${customerName}分配给“${teamNames.join(
|
||
"、"
|
||
)}“团队`;
|
||
query.transferToTeamIds = addTeamIds;
|
||
addServiceRecordTaskList.push(appFunction.addServiceRecord(query));
|
||
}
|
||
if (removeTeamIds.length > 0) {
|
||
const teamNames = await getTeamNamesByTeamIds({
|
||
corpId,
|
||
teamIds: removeTeamIds,
|
||
});
|
||
query.eventType = "adminRemoveTeams";
|
||
query.removeTeamIds = removeTeamIds;
|
||
query.taskContent = `管理员解除${customerName}与”${teamNames.join(
|
||
"、"
|
||
)}“团队的关联`;
|
||
addServiceRecordTaskList.push(appFunction.addServiceRecord(query));
|
||
}
|
||
} else {
|
||
addServiceRecordTaskList = [appFunction.addServiceRecord(query)];
|
||
}
|
||
return addServiceRecordTaskList;
|
||
}
|
||
|
||
async function getTeamNamesByTeamIds({ corpId, teamIds }) {
|
||
const teams = await db
|
||
.collection("team")
|
||
.find({ corpId, teamId: { $in: teamIds } })
|
||
.toArray();
|
||
return teams.map((item) => item.name);
|
||
}
|
||
|
||
/**
|
||
* 新增成员
|
||
* @param {object} params - 成员信息
|
||
* @param {string} createTeamId - 创建团队ID
|
||
* @param {string} createTeamName - 创建团队名称
|
||
* @returns {object} 新增结果
|
||
*/
|
||
async function addMember({ params, createTeamId, createTeamName }) {
|
||
const { corpId, name, teamId, idCard } = params;
|
||
if (!corpId || corpId === "undefined") {
|
||
return {
|
||
success: false,
|
||
message: "机构Id未传",
|
||
};
|
||
}
|
||
if (!name) {
|
||
return {
|
||
success: false,
|
||
message: "姓名不能为空",
|
||
};
|
||
}
|
||
if (idCard) {
|
||
const { gender, birthDate, age } = utils.calculateIdCardInfo(idCard);
|
||
params.sex = gender;
|
||
params.birthday = birthDate;
|
||
params.age = age;
|
||
}
|
||
const limitation = await corpCustomtorLimitation(corpId);
|
||
if (!limitation) {
|
||
return {
|
||
success: false,
|
||
message: "客户数已达上限",
|
||
};
|
||
}
|
||
if (params.idCard) {
|
||
const repeat = await isIdCardRepeat(params.idCard, corpId);
|
||
if (repeat)
|
||
return { success: false, message: "您的档案已存在,请勿重复建档!" };
|
||
}
|
||
params["createTime"] = new Date().getTime();
|
||
params["customerStage"] = params["customerStage"] || "OMINHOSPITALA";
|
||
if (teamId && typeof teamId === "string") {
|
||
params["teamId"] = [teamId];
|
||
}
|
||
if ("age" in params) {
|
||
params["age"] = parseInt(params["age"]) > 0 ? parseInt(params["age"]) : "";
|
||
}
|
||
params.inHospitalTimes = [];
|
||
if (typeof params.teamId === "string") params.teamId = [params.teamId];
|
||
const birthdayStamp = helpers.getBirthdayStamp(params);
|
||
if (birthdayStamp) params["birthdayStamp"] = birthdayStamp;
|
||
params["_id"] = common.generateRandomString(24);
|
||
const res = await db.collection("member").insertOne(params);
|
||
// 合并自动建档
|
||
const asyncAutoCustomerArchivesTask = asyncAutoCustomerArchives({
|
||
corpId,
|
||
externalUserId: params.externalUserId,
|
||
id: res.insertedId,
|
||
createType: params.createType,
|
||
});
|
||
// 修改了名字, 同步到企业微信备注名
|
||
const editRemarkTask = exports.editExternalContactRemark({
|
||
corpId,
|
||
externalUserId: params.externalUserId,
|
||
});
|
||
// 触发SOP任务
|
||
const sopTask = triggerSoptask({
|
||
corpId,
|
||
params,
|
||
customerId: res.insertedId,
|
||
});
|
||
// 添加服务记录
|
||
let query = {
|
||
eventType: "remindFiling",
|
||
customerId: res.insertedId,
|
||
executorUserId: params.creator,
|
||
executeTeamId: createTeamId,
|
||
createTeamName,
|
||
creatorUserId: params.creator,
|
||
corpId,
|
||
customerName: params.name,
|
||
createTime: dayjs().valueOf(),
|
||
taskContent: `&&&${params.creator || ""}&&&新增客户${params.name}`,
|
||
executionTime: dayjs().valueOf(),
|
||
customerUserId: params.externalUserId,
|
||
};
|
||
// 采集方式 addMethod 手动录入、扫码加好友自动建档、推送建档链接、网电报备
|
||
if (params.createType === "auto") {
|
||
query.addMethod = "扫码加好友自动建档";
|
||
} else if (params.addMethod === "eStoreReport") {
|
||
query.addMethod = "网电报备";
|
||
} else if (params.addMethod === "pushLink") {
|
||
query.addMethod = "推送建档链接";
|
||
} else {
|
||
query.addMethod = "手动录入";
|
||
}
|
||
query.taskContent = query.taskContent + `,采集方式:${query.addMethod}`;
|
||
const addServiceRecordTask = params.creator
|
||
? appFunction.addServiceRecord(query)
|
||
: "";
|
||
await Promise.all([
|
||
asyncAutoCustomerArchivesTask,
|
||
editRemarkTask,
|
||
sopTask,
|
||
addServiceRecordTask,
|
||
]);
|
||
return {
|
||
success: true,
|
||
message: "添加成功",
|
||
data: {
|
||
id: res.insertedId,
|
||
},
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 触发SOP任务
|
||
* @param {object} params - 参数
|
||
* @returns {object} 触发结果
|
||
*/
|
||
async function triggerSoptask({ corpId, params, customerId }) {
|
||
const { personResponsibles } = params;
|
||
if (!personResponsibles || !corpId) {
|
||
return {
|
||
success: false,
|
||
message: "触发SOP任务失败",
|
||
};
|
||
}
|
||
const query = {
|
||
corpId,
|
||
customerId,
|
||
archive: params,
|
||
};
|
||
console.log("触发SOP任务参数", query);
|
||
let res = await sop.main(
|
||
{
|
||
type: "triggerSopTask",
|
||
...query,
|
||
},
|
||
db
|
||
);
|
||
console.log("触发SOP任务");
|
||
}
|
||
|
||
/**
|
||
* 根据客户ID触发SOP任务
|
||
* @param {object} params - 参数
|
||
* @returns {object} 触发结果
|
||
*/
|
||
async function triggerSoptaskByCustomerId({ corpId, customerId }) {
|
||
const {
|
||
data: [member],
|
||
} = await db.collection("member").find({ _id: customerId }).toArray();
|
||
const query = {
|
||
corpId,
|
||
customerId,
|
||
archive: member,
|
||
};
|
||
console.log("触发SOP任务参数", query);
|
||
let res = await sop.main(
|
||
{
|
||
type: "triggerSopTask",
|
||
...query,
|
||
},
|
||
db
|
||
);
|
||
console.log("触发SOP任务", res);
|
||
}
|
||
|
||
/**
|
||
* 删除成员
|
||
* @param {string} id - 成员id
|
||
* @param {string} corpId - 企业微信ID
|
||
* @returns {object} 删除结果
|
||
*/
|
||
async function deleteMember({ id, corpId }) {
|
||
try {
|
||
await exports.editExternalContactRemark({
|
||
memberId: id,
|
||
corpId,
|
||
deleteMemberId: id,
|
||
});
|
||
const res = await db.collection("member").deleteOne({ _id: id });
|
||
// 删除成员时, 删除SOP任务
|
||
await sop.main({ type: "deleteSopTask", corpId, customerId: id }, db);
|
||
return {
|
||
success: true,
|
||
message: "删除成功",
|
||
data: res,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 机构客户数限制
|
||
* @param {string} corpId - 企业微信ID
|
||
* @returns {boolean} 是否超出限制
|
||
*/
|
||
async function corpCustomtorLimitation(corpId) {
|
||
const memberCount = await db.collection("member").find({ corpId }).count();
|
||
const { data } = await api.getCorpApi({ type: "getCorpInfo", corpId });
|
||
const corp = data && data[0] ? data[0] : {};
|
||
const { package } = corp;
|
||
if (!package) return false;
|
||
const { customerCount, giveCustomerCount } = package;
|
||
return memberCount < customerCount + giveCustomerCount;
|
||
}
|
||
|
||
/**
|
||
* 判断身份证是否重复
|
||
* @param {string} idCard - 身份证号
|
||
* @param {string} corpId - 企业微信ID
|
||
* @returns {boolean} 是否重复
|
||
*/
|
||
async function isIdCardRepeat(idCard, corpId) {
|
||
try {
|
||
const res = await db.collection("member").find({ corpId, idCard }).count();
|
||
return res > 0;
|
||
} catch (e) {
|
||
return Promise.reject(e.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取推荐人信息
|
||
* @param {object} ctx - 上下文
|
||
* @returns {object} 推荐人信息
|
||
*/
|
||
async function getReferredPeople(ctx) {
|
||
try {
|
||
const { id: referenceCustomerId, corpId } = ctx;
|
||
if (referenceCustomerId && corpId) {
|
||
const page =
|
||
typeof ctx.page === "number" && ctx.page % 1 === 0 && ctx.page > 0
|
||
? ctx.page
|
||
: 1;
|
||
const pageSize =
|
||
typeof ctx.pageSize === "number" &&
|
||
ctx.pageSize % 1 === 0 &&
|
||
ctx.pageSize > 0
|
||
? ctx.pageSize
|
||
: 20;
|
||
const res = db
|
||
.collection("member")
|
||
.find({ referenceCustomerId, corpId, referenceType: "客户" })
|
||
.skip((page - 1) * pageSize)
|
||
.limit(pageSize)
|
||
.project({ name: true, teamId: true, sex: true, mobile: true });
|
||
const data = await res.toArray();
|
||
const total = await db
|
||
.collection("member")
|
||
.find({ referenceCustomerId, corpId, referenceType: "客户" })
|
||
.count();
|
||
return {
|
||
success: true,
|
||
list: data,
|
||
pages: Math.ceil(total / pageSize),
|
||
message: "查询成功",
|
||
};
|
||
}
|
||
return { success: false, message: "参数错误" };
|
||
} catch (e) {
|
||
return { success: false, message: e.message };
|
||
}
|
||
}
|
||
|
||
// 将年龄字段转换为数字
|
||
async function setAgeToNumber() {
|
||
const batchSize = 100; // 每次处理的文档数量
|
||
let totalUpdated = 0;
|
||
|
||
try {
|
||
while (true) {
|
||
console.log(`Processing batch...`);
|
||
// 查询一批符合条件的文档
|
||
const queryResult = await db
|
||
.collection("member")
|
||
.find({
|
||
age: { $regex: "^[0-9]+$", $options: "i" },
|
||
})
|
||
.limit(batchSize)
|
||
.project({ _id: true, age: true })
|
||
.toArray();
|
||
if (queryResult.length === 0) {
|
||
break; // 没有更多文档需要处理
|
||
}
|
||
|
||
const bulkOps = queryResult
|
||
.map((doc) => {
|
||
const age = parseInt(doc.age, 10);
|
||
if (!isNaN(age)) {
|
||
return {
|
||
updateOne: {
|
||
filter: { _id: doc._id },
|
||
update: { $set: { age: age } },
|
||
},
|
||
};
|
||
}
|
||
})
|
||
.filter(Boolean);
|
||
|
||
if (bulkOps.length > 0) {
|
||
const result = await db.collection("member").bulkWrite(bulkOps);
|
||
totalUpdated += result.modifiedCount;
|
||
}
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
message: `${totalUpdated} documents updated.`,
|
||
};
|
||
} catch (err) {
|
||
return {
|
||
success: false,
|
||
error: err,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 获取成员信息
|
||
async function getMember(context) {
|
||
let { unionid, corpId, corpUserId, params = {}, externalUserIds } = context;
|
||
if (!corpId || corpId === "undefined") {
|
||
return {
|
||
success: false,
|
||
message: "机构Id未传",
|
||
};
|
||
}
|
||
try {
|
||
if (corpUserId) params.teamId = await getTeamList(corpUserId, corpId);
|
||
if (unionid) params.unionid = unionid;
|
||
if (externalUserIds) params.externalUserId = { $in: externalUserIds };
|
||
if (typeof params.name === "string" && params.name.trim()) {
|
||
params.name = { $regex: ".*" + params.name.trim() + ".*", $options: "i" };
|
||
}
|
||
const fetchData = async (page, pageSize, db) => {
|
||
let data = await db
|
||
.collection("member")
|
||
.find({
|
||
corpId,
|
||
...params,
|
||
})
|
||
.skip((page - 1) * pageSize)
|
||
.limit(pageSize)
|
||
.sort({ createTime: -1 })
|
||
.toArray();
|
||
return data;
|
||
};
|
||
const list = await utils.getAllData(fetchData, db);
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: list,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 获取侧边栏客户数据
|
||
async function getCustomerInSidebar(context) {
|
||
let { corpId, teamIds, externalUserId } = context;
|
||
if (!corpId || corpId === "undefined") {
|
||
return {
|
||
success: false,
|
||
message: "机构Id未传",
|
||
};
|
||
}
|
||
if (!externalUserId) return { success: false, message: "外部联系人id未传" };
|
||
try {
|
||
const res = await db
|
||
.collection("member")
|
||
.find({
|
||
corpId,
|
||
externalUserId,
|
||
})
|
||
.sort({ createTime: -1 })
|
||
.limit(100)
|
||
.project({
|
||
externalContactInfo: false,
|
||
})
|
||
.toArray();
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: res,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 根据团队ID获取客户总数
|
||
async function getmemberCountForTeamId(context) {
|
||
const { time, params } = context;
|
||
if (time === "THISMONTH") {
|
||
const { startOfThisMouthTimestamp, endOfThisMouthTimestamp } =
|
||
getThisMouth();
|
||
params["createTime"] = {
|
||
$gte: startOfThisMouthTimestamp,
|
||
$lte: endOfThisMouthTimestamp,
|
||
};
|
||
} else if (time === "LASTMONTH") {
|
||
const { lastMonthStartDateTimestamp, lastMonthEndDateTimestamp } =
|
||
getlastMonthStartTimeAndEndTime();
|
||
params["createTime"] = {
|
||
$gte: lastMonthStartDateTimestamp,
|
||
$lte: lastMonthEndDateTimestamp,
|
||
};
|
||
}
|
||
try {
|
||
const res = await db.collection("member").find(params).count();
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: res,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 根据userId 获取客户总数
|
||
async function getmemberAndserviceCountForUserId(context) {
|
||
const { params, teamId } = context;
|
||
const { corpId, userId, startTime, endTime } = params;
|
||
|
||
try {
|
||
const memberQuery = {
|
||
corpId,
|
||
};
|
||
if (teamId) {
|
||
memberQuery.teamId = teamId;
|
||
memberQuery.personResponsibles = {
|
||
$elemMatch: {
|
||
corpUserId: userId,
|
||
teamId: teamId,
|
||
},
|
||
};
|
||
} else {
|
||
memberQuery.personResponsibles = {
|
||
$elemMatch: {
|
||
corpUserId: userId,
|
||
},
|
||
};
|
||
}
|
||
|
||
if (startTime && dayjs(startTime).isValid()) {
|
||
const startTimestamp = dayjs(startTime).startOf("day").valueOf();
|
||
memberQuery.createTime = memberQuery.createTime || {};
|
||
memberQuery.createTime.$gte = startTimestamp;
|
||
}
|
||
if (endTime && dayjs(endTime).isValid()) {
|
||
const endTimestamp = dayjs(endTime).endOf("day").valueOf();
|
||
memberQuery.createTime = memberQuery.createTime || {};
|
||
memberQuery.createTime.$lte = endTimestamp;
|
||
}
|
||
const memberTotal = await db.collection("member").find(memberQuery).count();
|
||
const serviceQuery = {
|
||
corpId,
|
||
executorUserId: userId,
|
||
eventType: { $ne: "serviceRate" },
|
||
};
|
||
|
||
if (startTime && dayjs(startTime).isValid()) {
|
||
const startTimestamp = dayjs(startTime).startOf("day").valueOf();
|
||
serviceQuery.executionTime = serviceQuery.executionTime || {};
|
||
serviceQuery.executionTime.$gte = startTimestamp;
|
||
}
|
||
if (endTime && dayjs(endTime).isValid()) {
|
||
const endTimestamp = dayjs(endTime).endOf("day").valueOf();
|
||
serviceQuery.executionTime = serviceQuery.executionTime || {};
|
||
serviceQuery.executionTime.$lte = endTimestamp;
|
||
}
|
||
if (teamId) {
|
||
serviceQuery.executeTeamId = teamId;
|
||
}
|
||
|
||
const serviceTotal = await db
|
||
.collection("service-record")
|
||
.find(serviceQuery)
|
||
.count();
|
||
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: {
|
||
memberTotal,
|
||
serviceTotal,
|
||
},
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error.message,
|
||
};
|
||
}
|
||
}
|
||
async function getmemberAndserviceCountForUserId(context) {
|
||
const { params, teamId } = context;
|
||
const { corpId, userId, startTime, endTime } = params;
|
||
|
||
try {
|
||
const memberQuery = {
|
||
corpId,
|
||
};
|
||
if (teamId) {
|
||
memberQuery.teamId = teamId;
|
||
memberQuery.personResponsibles = {
|
||
$elemMatch: {
|
||
corpUserId: userId,
|
||
teamId: teamId,
|
||
},
|
||
};
|
||
} else {
|
||
memberQuery.personResponsibles = {
|
||
$elemMatch: {
|
||
corpUserId: userId,
|
||
},
|
||
};
|
||
}
|
||
|
||
if (startTime && dayjs(startTime).isValid()) {
|
||
const startTimestamp = dayjs(startTime).startOf("day").valueOf();
|
||
memberQuery.createTime = memberQuery.createTime || {};
|
||
memberQuery.createTime.$gte = startTimestamp;
|
||
}
|
||
if (endTime && dayjs(endTime).isValid()) {
|
||
const endTimestamp = dayjs(endTime).endOf("day").valueOf();
|
||
memberQuery.createTime = memberQuery.createTime || {};
|
||
memberQuery.createTime.$lte = endTimestamp;
|
||
}
|
||
const memberTotal = await db.collection("member").find(memberQuery).count();
|
||
const serviceQuery = {
|
||
corpId,
|
||
executorUserId: userId,
|
||
eventType: { $ne: "serviceRate" },
|
||
};
|
||
|
||
if (startTime && dayjs(startTime).isValid()) {
|
||
const startTimestamp = dayjs(startTime).startOf("day").valueOf();
|
||
serviceQuery.executionTime = serviceQuery.executionTime || {};
|
||
serviceQuery.executionTime.$gte = startTimestamp;
|
||
}
|
||
if (endTime && dayjs(endTime).isValid()) {
|
||
const endTimestamp = dayjs(endTime).endOf("day").valueOf();
|
||
serviceQuery.executionTime = serviceQuery.executionTime || {};
|
||
serviceQuery.executionTime.$lte = endTimestamp;
|
||
}
|
||
if (teamId) {
|
||
serviceQuery.executeTeamId = teamId;
|
||
}
|
||
|
||
const serviceTotal = await db
|
||
.collection("service-record")
|
||
.find(serviceQuery)
|
||
.count();
|
||
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: {
|
||
memberTotal,
|
||
serviceTotal,
|
||
},
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error.message,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 获取上个月的开始和结束时间戳
|
||
function getlastMonthStartTimeAndEndTime() {
|
||
const currentDate = new Date();
|
||
const lastMonthYear = currentDate.getFullYear();
|
||
const lastMonth = currentDate.getMonth() - 1;
|
||
const lastMonthLastDate = new Date(lastMonthYear, lastMonth + 1, 0);
|
||
const lastMonthStartDate = new Date(lastMonthYear, lastMonth, 1, 0, 0, 0);
|
||
const lastMonthStartDateTimestamp = lastMonthStartDate.getTime();
|
||
const lastMonthEndDate = new Date(
|
||
lastMonthYear,
|
||
lastMonth,
|
||
lastMonthLastDate.getDate(),
|
||
23,
|
||
59,
|
||
59
|
||
);
|
||
const lastMonthEndDateTimestamp = lastMonthEndDate.getTime();
|
||
return {
|
||
lastMonthStartDateTimestamp,
|
||
lastMonthEndDateTimestamp,
|
||
};
|
||
}
|
||
|
||
// 获取本月的开始时间戳
|
||
function getThisMouth() {
|
||
const currentDate = new Date();
|
||
currentDate.setDate(1);
|
||
currentDate.setHours(0, 0, 0, 0);
|
||
const startOfThisMouthTimestamp = currentDate.getTime();
|
||
return {
|
||
startOfThisMouthTimestamp,
|
||
endOfThisMouthTimestamp: new Date().getTime(),
|
||
};
|
||
}
|
||
|
||
// 根据标签ID获取成员列表
|
||
async function getMemberBytags(context) {
|
||
const { corpId, tagIds, userId } = context;
|
||
let params = { corpId, tagIds: { $in: tagIds } };
|
||
if (userId) params["teamId"] = await getTeamList(userId, corpId);
|
||
try {
|
||
const res = await db.collection("member").find(params).toArray();
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: res,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: "获取失败",
|
||
};
|
||
}
|
||
}
|
||
|
||
// 获取企业客户
|
||
async function getCorpCustomer(context) {
|
||
try {
|
||
let {
|
||
page,
|
||
pageSize,
|
||
type,
|
||
startCreateTime,
|
||
endCreateTime,
|
||
corpUserId,
|
||
showExternalCustomer,
|
||
permanent_code,
|
||
userIds,
|
||
teamId,
|
||
accessToken,
|
||
...params
|
||
} = context;
|
||
const { corpId } = params;
|
||
|
||
// 校验企业ID是否为空
|
||
if (!corpId) return { success: false, message: "机构ID不能为空" };
|
||
|
||
// 根据name进行模糊查询
|
||
if (typeof params.name === "string" && params.name.trim()) {
|
||
params.name = new RegExp(".*" + params.name.trim(), "i");
|
||
}
|
||
|
||
// 根据mobile进行模糊查询
|
||
if (typeof params.mobile === "string" && params.mobile.trim()) {
|
||
const pattern = params.mobile.trim().split("").join(".*");
|
||
params.mobile = new RegExp(pattern, "i");
|
||
}
|
||
|
||
// 如果有teamId进行团队筛选
|
||
if (teamId) {
|
||
if (Array.isArray(teamId)) {
|
||
params["teamId"] = { $in: teamId };
|
||
} else {
|
||
params["teamId"] = teamId;
|
||
}
|
||
}
|
||
|
||
if (showExternalCustomer) {
|
||
params["externalUserId"] = { $exists: true };
|
||
params["personResponsibles"] = {
|
||
$elemMatch: { corpUserId: { $in: userIds } },
|
||
};
|
||
}
|
||
|
||
// 如果teamId是'无',设置为无效值
|
||
if (teamId === "无") {
|
||
params.teamId = { $or: [{ $eq: [] }, { $exists: false }, { $eq: "" }] };
|
||
}
|
||
|
||
// 如果有tagIds,进行标签筛选
|
||
if (Array.isArray(params.tagIds) && params.tagIds.length) {
|
||
params.tagIds = { $all: params.tagIds }; // 匹配所有指定tagId
|
||
}
|
||
|
||
// 根据时间范围过滤数据
|
||
if (startCreateTime && endCreateTime) {
|
||
const startTime = dayjs(startCreateTime).startOf("day").valueOf();
|
||
const endTime = dayjs(endCreateTime).endOf("day").valueOf();
|
||
params["createTime"] = { $gte: startTime, $lte: endTime };
|
||
}
|
||
|
||
// 聚合管道
|
||
const pipeline = [
|
||
{ $match: params }, // 过滤条件
|
||
{ $sort: { createTime: -1 } }, // 按createTime降序排序
|
||
{ $skip: (page - 1) * pageSize }, // 分页跳过的记录数
|
||
{ $limit: pageSize }, // 设置分页大小
|
||
{
|
||
$lookup: {
|
||
from: "member-management-plan", // 关联的集合
|
||
localField: "_id", // 当前集合字段
|
||
foreignField: "customerId", // 关联集合字段
|
||
as: "plans", // 返回的字段名
|
||
},
|
||
},
|
||
{
|
||
$project: showExternalCustomer
|
||
? { _id: 1, name: 1 }
|
||
: { _id: 1, name: 1, plans: 1 }, // 返回需要的字段
|
||
},
|
||
];
|
||
|
||
// 获取总数的聚合管道
|
||
const totalPipeline = [
|
||
{ $match: params },
|
||
{ $count: "total" }, // 获取符合条件的总数
|
||
];
|
||
|
||
// 执行总数查询
|
||
const totalResult = await db
|
||
.collection("member")
|
||
.aggregate(totalPipeline)
|
||
.toArray();
|
||
const total = totalResult.length ? totalResult[0].total : 0;
|
||
const pages = Math.ceil(total / pageSize);
|
||
|
||
// 执行数据查询
|
||
const memberList = await db
|
||
.collection("member")
|
||
.aggregate(pipeline)
|
||
.toArray();
|
||
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: memberList,
|
||
total: total,
|
||
pages: pages,
|
||
size: pageSize,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error.toString(),
|
||
};
|
||
}
|
||
}
|
||
|
||
// 根据团队ID获取成员列表
|
||
async function getMemberForTeam(context) {
|
||
try {
|
||
const { page, pageSize, corpId, params: data, teamId } = context;
|
||
const { startCreateTime, endCreateTime, managementPlanStatus, ...params } =
|
||
data || {};
|
||
if (typeof params.name === "string" && params.name.trim()) {
|
||
params.name = { $regex: ".*" + params.name.trim() + ".*", $options: "i" };
|
||
}
|
||
if (!teamId || (Array.isArray(teamId) && teamId.length == 0)) {
|
||
return {
|
||
success: false,
|
||
message: "团队ID未传",
|
||
};
|
||
}
|
||
params["corpId"] = corpId;
|
||
params["teamId"] = teamId;
|
||
if (Array.isArray(params.tagIds) && params.tagIds.length) {
|
||
params.tagIds = { $and: params.tagIds.map((id) => ({ $in: [id] })) };
|
||
}
|
||
if (startCreateTime && endCreateTime) {
|
||
params["createTime"] = {
|
||
$and: [
|
||
{ $gte: dayjs(startCreateTime).valueOf() },
|
||
{ $lte: dayjs(endCreateTime).valueOf() },
|
||
],
|
||
};
|
||
}
|
||
if (params.startServiceTime || params.endServiceTime) {
|
||
params["serviceTime"] = {
|
||
$and: [
|
||
{ $gte: params.startServiceTime },
|
||
{ $lte: params.endServiceTime },
|
||
],
|
||
};
|
||
}
|
||
if (params["groupIds"] === "no-id") {
|
||
const groupIds = await getGroupIds(teamId);
|
||
params["groupIds"] = { $nin: groupIds };
|
||
}
|
||
let planParams = {};
|
||
if (managementPlanStatus) {
|
||
planParams["plan.planExecutStaus"] = managementPlanStatus;
|
||
}
|
||
const total = await db.collection("member").find(params).count();
|
||
const pages = Math.ceil(total / pageSize);
|
||
const res = await db
|
||
.collection("member")
|
||
.aggregate([
|
||
{ $match: params },
|
||
{ $sort: { createTime: -1 } },
|
||
{ $skip: (page - 1) * pageSize },
|
||
{ $limit: pageSize },
|
||
{
|
||
$lookup: {
|
||
from: "member-management-plan",
|
||
localField: "_id",
|
||
foreignField: "customerId",
|
||
as: "plans",
|
||
},
|
||
},
|
||
])
|
||
.toArray();
|
||
const list = res.map((item) => {
|
||
item.plans.reverse();
|
||
const plan = item.plans.find((plan) => plan.executeTeamId === teamId);
|
||
delete item.plans;
|
||
return {
|
||
...item,
|
||
plan: plan || {},
|
||
};
|
||
});
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: list,
|
||
total: total,
|
||
pages: pages,
|
||
size: pageSize,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 获取团队的groupIds
|
||
async function getGroupIds(teamId) {
|
||
const data = await db.collection("group").find({ teamId }).toArray();
|
||
const ids = data.map((item) => item._id);
|
||
return ids;
|
||
}
|
||
|
||
// 获取成员信息
|
||
async function getMemberInfo(context) {
|
||
try {
|
||
const { params } = context;
|
||
const res = await db
|
||
.collection("member")
|
||
.aggregate([
|
||
{ $match: params },
|
||
{
|
||
$lookup: {
|
||
from: "member",
|
||
let: { referenceCustomerId: "$_id" },
|
||
pipeline: [
|
||
{
|
||
$match: {
|
||
$expr: {
|
||
$and: [
|
||
{
|
||
$eq: ["$referenceCustomerId", "$$referenceCustomerId"],
|
||
},
|
||
{ $eq: ["$referenceType", "客户"] },
|
||
],
|
||
},
|
||
},
|
||
},
|
||
],
|
||
as: "referenceCount",
|
||
},
|
||
},
|
||
{ $addFields: { referenceCount: { $size: "$referenceCount" } } },
|
||
])
|
||
.toArray();
|
||
return {
|
||
success: true,
|
||
message: "获取成功",
|
||
data: res,
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 批量导入客户
|
||
async function batchImportCustomer(context) {
|
||
const { params } = context;
|
||
let baseReatParams = Object.entries(params).reduce((prev, [key, value]) => {
|
||
if (value) {
|
||
prev[key] = value;
|
||
}
|
||
return prev;
|
||
}, {});
|
||
const { idCard, customerNumber } = baseReatParams;
|
||
if (!idCard && !customerNumber)
|
||
return { success: false, message: "身份证号和客户编号不能同时为空" };
|
||
let getMemberParams = {};
|
||
if (idCard) {
|
||
getMemberParams["idCard"] = idCard;
|
||
} else if (!idCard && customerNumber) {
|
||
getMemberParams["customerNumber"] = customerNumber;
|
||
}
|
||
let newCustomerId = "";
|
||
let operationType = "add";
|
||
try {
|
||
const customer = await db.collection("member").findOne(getMemberParams);
|
||
if (customer) {
|
||
baseReatParams["updateTime"] = new Date().getTime();
|
||
operationType = "update";
|
||
delete baseReatParams["creator"];
|
||
await db
|
||
.collection("member")
|
||
.updateOne({ _id: customer._id }, { $set: baseReatParams });
|
||
newCustomerId = customer._id;
|
||
} else {
|
||
baseReatParams["createTime"] = new Date().getTime();
|
||
baseReatParams["_id"] = common.generateRandomString(24);
|
||
const res = await db.collection("member").insertOne(baseReatParams);
|
||
newCustomerId = res.insertedId;
|
||
}
|
||
return {
|
||
success: true,
|
||
data: newCustomerId,
|
||
operationType,
|
||
customer,
|
||
message: "导入成功",
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据externalUserId更新unionid
|
||
* @param {object} context - 上下文
|
||
* @returns {object} 更新结果
|
||
*/
|
||
async function externalUseridToMember(context) {
|
||
const { externalUserId, unionid, corpId, realUnionid } = context;
|
||
if (!externalUserId || !unionid || !corpId) {
|
||
return { success: false, message: "参数错误" };
|
||
}
|
||
try {
|
||
const data = await db
|
||
.collection("member")
|
||
.find({
|
||
externalUserId,
|
||
corpId,
|
||
unionid: { $ne: unionid },
|
||
})
|
||
.toArray();
|
||
if (data.length === 0) return { success: true, message: "无需更新" };
|
||
const ids = data.map((item) => item._id);
|
||
await db
|
||
.collection("member")
|
||
.updateMany({ _id: { $in: ids } }, { $set: { unionid, realUnionid } });
|
||
return {
|
||
success: true,
|
||
message: "更新成功",
|
||
};
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error.message,
|
||
};
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 编辑外部联系人备注
|
||
* @param {object} context - 上下文
|
||
* @returns {object} 编辑结果
|
||
*/
|
||
exports.editExternalContactRemark = async (context) => {
|
||
if (!context.memberId && !context.externalUserId) {
|
||
return { success: false, message: "参数错误" };
|
||
}
|
||
if (context.memberId && !context.externalUserId) {
|
||
const data = await db
|
||
.collection("member")
|
||
.find({ _id: context.memberId })
|
||
.toArray();
|
||
context.externalUserId = data[0].externalUserId;
|
||
}
|
||
if (!context.externalUserId) {
|
||
return { success: false, message: "外部联系人Id未传" };
|
||
}
|
||
const query = {
|
||
corpId: context.corpId,
|
||
externalUserId: context.externalUserId,
|
||
};
|
||
if (context.deleteMemberId) {
|
||
query["_id"] = { $ne: context.deleteMemberId };
|
||
}
|
||
const memberList = await db.collection("member").find(query).toArray();
|
||
const list = memberList.map((item) => ({
|
||
name: item.name,
|
||
relationship: item.relationship,
|
||
}));
|
||
const res = await api.getWecomApi({
|
||
type: "asyncExternalContactRemark",
|
||
externalUserId: context.externalUserId,
|
||
corpId: context.corpId,
|
||
list,
|
||
});
|
||
return res;
|
||
};
|
||
|
||
/**
|
||
* 更新客户的时间字段
|
||
* @param {object} context - 上下文
|
||
* @returns {object} 更新结果
|
||
*/
|
||
exports.updateCustomerTimeField = async (context) => {
|
||
const { field, _id, corpId, time } = context;
|
||
try {
|
||
if (
|
||
typeof field !== "string" ||
|
||
!corpId ||
|
||
!_id ||
|
||
!time ||
|
||
!dayjs(time).isValid()
|
||
) {
|
||
return {
|
||
success: false,
|
||
message: "参数错误",
|
||
};
|
||
}
|
||
const customer = await db
|
||
.collection("member")
|
||
.find({ _id, corpId })
|
||
.project({ [field]: 1 })
|
||
.toArray();
|
||
if (
|
||
customer.length > 0 &&
|
||
(!customer[0][field] || dayjs(customer[0][field]).isBefore(dayjs(time)))
|
||
) {
|
||
await db
|
||
.collection("member")
|
||
.updateOne(
|
||
{ _id, corpId },
|
||
{ $set: { [field]: dayjs(time).valueOf() } }
|
||
);
|
||
return {
|
||
success: true,
|
||
message: "更新成功",
|
||
};
|
||
}
|
||
return { success: false, message: "客户不存在或者无需更新" };
|
||
} catch (error) {
|
||
return {
|
||
success: false,
|
||
message: error.message,
|
||
};
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 根据unionid获取客户
|
||
* @param {object} ctx - 上下文
|
||
* @returns {object} 客户信息
|
||
*/
|
||
exports.getCustomerByUnionId = async (ctx) => {
|
||
const { unionid, realUnionid, corpId } = ctx;
|
||
try {
|
||
const customer = await db
|
||
.collection("member")
|
||
.find({ corpId, unionid: { $in: [unionid, realUnionid] } })
|
||
.project({ _id: 1, name: 1 })
|
||
.limit(1)
|
||
.toArray();
|
||
return { success: Boolean(customer.length), data: customer[0] };
|
||
} catch (e) {
|
||
return { success: false, message: e.message };
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 根据客户ID获取客户名称
|
||
* @param {object} ctx - 上下文
|
||
* @returns {object} 客户名称列表
|
||
*/
|
||
exports.getCustomerNamesById = async (ctx) => {
|
||
const { ids, corpId } = ctx;
|
||
if (!corpId || !Array.isArray(ids) || ids.length === 0) {
|
||
return { success: false, message: "参数错误" };
|
||
}
|
||
try {
|
||
const list = await db
|
||
.collection("member")
|
||
.find({ corpId, _id: { $in: ids } })
|
||
.project({ _id: 1, name: 1 })
|
||
.toArray();
|
||
return { success: true, data: list };
|
||
} catch (e) {
|
||
return { success: false, message: e.message };
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 新增客户消费记录
|
||
* @param {object} item - 消费记录信息
|
||
* @returns {object} 新增结果
|
||
*/
|
||
async function addConsumeRecord(item) {
|
||
const { consumeAmount, corpId, customerId } = item;
|
||
const latestConsumeTime = dayjs().valueOf();
|
||
const query = {
|
||
_id: common.generateRandomString(24),
|
||
consumeAmount,
|
||
corpId,
|
||
customerId,
|
||
createTime: latestConsumeTime,
|
||
};
|
||
await db.collection("consume-record").insertOne(query);
|
||
return {
|
||
success: true,
|
||
message: "更新成功",
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 更新客户报备人员
|
||
* @param {object} ctx - 上下文
|
||
* @returns {object} 更新结果
|
||
*/
|
||
async function updateCustomerReportPeople(ctx) {
|
||
const {
|
||
customerId,
|
||
reportUserId,
|
||
corpId,
|
||
updateUserId,
|
||
reportTimeStamp,
|
||
personResponsibles,
|
||
teamId,
|
||
reportTeamId,
|
||
} = ctx;
|
||
if (
|
||
!corpId ||
|
||
!customerId ||
|
||
!reportUserId ||
|
||
!updateUserId ||
|
||
!reportTimeStamp ||
|
||
!personResponsibles ||
|
||
!teamId ||
|
||
!reportTeamId ||
|
||
!dayjs(reportTimeStamp).isValid()
|
||
) {
|
||
return { success: false, message: "参数错误" };
|
||
}
|
||
try {
|
||
const customer = await db
|
||
.collection("member")
|
||
.find({ _id: customerId, corpId })
|
||
.project({
|
||
reportUserId: 1,
|
||
createTime: 1,
|
||
reportTimeStamp: 1,
|
||
reportTeamId: 1,
|
||
})
|
||
.toArray();
|
||
if (customer.length === 0) return { success: false, message: "客户不存在" };
|
||
const res = await db.collection("member").updateOne(
|
||
{ _id: customerId },
|
||
{
|
||
$set: {
|
||
reportUserId,
|
||
reportTimeStamp,
|
||
personResponsibles,
|
||
reportTeamId,
|
||
teamId,
|
||
},
|
||
}
|
||
);
|
||
if (res.modifiedCount === 0) return { success: false, message: "更新失败" };
|
||
await db.collection("customer-report-log").insertOne({
|
||
_id: common.generateRandomString(24),
|
||
customerId,
|
||
corpId,
|
||
reportUserId,
|
||
updateUserId,
|
||
reportTimeStamp,
|
||
preReportUserId: customer[0].reportUserId,
|
||
preReportTimeStamp: customer[0].reportTimeStamp || customer[0].createTime,
|
||
preReportTeamId: customer[0].reportTeamId || "",
|
||
createTime: Date.now(),
|
||
});
|
||
return { success: true, message: "更新成功" };
|
||
} catch (e) {
|
||
return { success: false, message: e.message };
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取客户报备日志
|
||
* @param {object} ctx - 上下文
|
||
* @returns {object} 报备日志
|
||
*/
|
||
async function getCustomerReportLog(ctx) {
|
||
const { customerId, corpId, page = 1, pageSize = 10 } = ctx;
|
||
if (!corpId || !customerId) return { success: false, message: "参数错误" };
|
||
try {
|
||
const total = await db
|
||
.collection("customer-report-log")
|
||
.find({ customerId, corpId })
|
||
.count();
|
||
const list = await db
|
||
.collection("customer-report-log")
|
||
.find({ customerId, corpId })
|
||
.sort({ createTime: -1 })
|
||
.skip((page - 1) * pageSize)
|
||
.limit(pageSize)
|
||
.toArray();
|
||
return { success: true, list, total, message: "查询成功" };
|
||
} catch (error) {
|
||
return { success: false, message: error.message };
|
||
}
|
||
}
|