2340 lines
80 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
let db = "";
const { ObjectId } = require("mongodb");
const dayjs = require("dayjs");
const { decryptOrderList } = require("../consult-order/format");
const {
formatUploadRxData,
formatOnlineMedicinePurchaseData,
formatReviewData,
formatWinePurchaseData,
encryptDiagnosticRecordFields,
decryptDiagnosticRecordFields,
decryptDiagnosticRecordList,
buildHybridSearchQuery,
} = require("./format");
const zytHis = require("../zyt-his");
const consultOrder = require("../consult-order");
const tencentIM = require("../tencent-im");
const beijingCa = require("../beijing-ca");
const BigNumber = require("bignumber.js");
const timeApi = require("../hlw-time-duration");
const types = require("./types");
const { getConfig } = require("../utils/config");
const PrescriptionTypeMap = {
onlineMedicinePurchase: 'onlineMedicinePurchase',
onlineConsult: 'storeMedicinePurchase',
wineConsult: 'medicalWinePurchase'
}
/**
* 性能优化建议
*
* 1. 数据库索引建议
* - diagnostic-record 集合
* db.getCollection("diagnostic-record").createIndex({ "status": 1, "createTime": -1 })
* db.getCollection("diagnostic-record").createIndex({ "orderId": 1 })
* db.getCollection("diagnostic-record").createIndex({ "doctorCode": 1, "status": 1 })
* db.getCollection("diagnostic-record").createIndex({ "patientId": 1, "status": 1, "orderSource": 1 })
*
* - consult-order 集合
* db.getCollection("consult-order").createIndex({ "orderId": 1 })
* db.getCollection("consult-order").createIndex({ "orderStatus": 1 })
*
* 2. 查询优化
* - getAuditDiagnosisList 函数已优化为先分页后关联查询避免大数据量 $lookup
* - 使用 Promise.all 并行执行不相关的查询操作
* - 避免在查询条件中使用正则表达式考虑使用全文检索
*
* 3. 数据冗余建议可选
* - diagnostic-record 中冗余 consult-order 的关键字段如患者姓名手机号等
* - 减少跨集合查询的需求
*/
// 判断当前是否是 zytDev 环境
function isZytDevEnv() {
console.log("当前环境变量 CONFIG_NODE_ENV:", process.env.CONFIG_NODE_ENV);
return (
process.env.CONFIG_NODE_ENV === "zytDev" ||
process.env.CONFIG_NODE_ENV === "development"
);
}
// 根据环境决定是否调用 beijingCa
async function conditionalCallBeijingCa(params, dbParam) {
if (isZytDevEnv()) {
console.log("在 zytDev 环境下,跳过调用 beijingCa");
return {
success: true,
userId: params.code || params.userId || "mock_user_id",
message: "在 zytDev 环境下模拟返回",
};
}
return await beijingCa(params, dbParam);
}
const status = {
init: "INIT", //待审核
pass: "PASS", //审核通过
unpass: "UNPASS", //审核未通过
expired: "EXPIRED", //订单过期 无法
passInvalid: "PASS_INVALID", //通过的处方作废 (目前就订单退费会导致处方作废)
unpassInvalid: "UNPASS_INVALID", //未通过的处方作废 (目前就订单退费会导致处方作废)
invalid: "INVALID", //处方作废 (目前就订单退费会导致处方作废)
};
module.exports = async (item, mongodb) => {
db = mongodb;
switch (item.type) {
case "addConsultDiagnosis":
return await addConsultDiagnosis(item, db);
case "getOrderDiagnosis":
return await getOrderDiagnosis(item, db);
case "getDiagnosisById":
return await getDiagnosisById(item, db);
case "getStoreDiagnosisRecord":
return await getStoreDiagnosisRecord(item, db);
case "getAuditDiagnosisList":
return await getAuditDiagnosisList(item, db);
case "getAuditedDiagnosisList":
return await getAuditedDiagnosisList(item, db);
case "getPatientDiagnosisRecord":
return await getPatientDiagnosisRecord(item, db);
case "getPatientPassDiagnosisRecord":
return await getPatientPassDiagnosisRecord(item, db);
case "auditDiagnosis":
return await auditDiagnosis(item, db);
case "uploadDiagnosis":
return await uploadDiagnosis(item, db);
case "orderHasDiagnosis":
return await orderHasDiagnosis(item, db);
case "getLatestSubmitTime":
return await getLatestSubmitTime(item, db);
case "reUploadDiagnosticRecord":
return await reUploadDiagnosticRecord(item, db);
case "discardDiagnosticRecord":
return await discardDiagnosticRecord(item, db);
case "getAllDiagnosisRecord":
return await getAllDiagnosisRecord(item, db);
case "getDoctorRxStats":
return await getDoctorRxStats(item, db);
case "getPharmacistRxStats":
return await getPharmacistRxStats(item, db);
case "checkRxUploadStatus":
return await checkRxUploadStatus(item, db);
case "getAccountRxList":
return await getAccountRxList(item, db);
case "getRxDetail":
return await getRxDetail(item, db);
case "getAccountHistoryDrugs":
return await getAccountHistoryDrugs(item, db);
case "getPatientHistoryDrugs":
return await getPatientHistoryDrugs(item, db);
case "getRxMedicineOrderStatus":
return await getRxMedicineOrderStatus(item, db);
case "runOnlineRxExpireSchedule":
return await runOnlineRxExpireSchedule(db);
case "getPatientHomeRxCount":
return await getPatientHomeRxCount(item, db);
case "getReUploadRxList":
return await getReUploadRxList(item, db);
case "handleReUploadRx":
return await handleReUploadRx(item, db);
case "getPatientWineBuyCount":
return await getPatientWineBuyCount(item, db);
case "getYbReviewResult":
return await getYbReviewResult(item, db);
}
};
let scheduleTaskIsRunning = false;
async function addConsultDiagnosis(item) {
let { params = {} } = item;
const corpId = typeof item.corpId === "string" ? item.corpId.trim() : '';
const { orderId, doctorCode } = params;
if (
typeof orderId !== "string" ||
orderId.trim() === "" ||
typeof doctorCode !== "string" ||
doctorCode.trim() === ""
) {
return { success: false, message: "参数错误" };
}
const timeData = { type: 'addConsultDiagnosis', startTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), orderId }
try {
const order = await db.collection("consult-order").findOne(
{ orderId },
{
projection: {
createTime: 1,
orderStatus: 1,
registerId: 1,
medorg_order_no: 1,
accountId: 1,
prescriptionStartTime: 1,
consultType: 1,
areaCode: 1,
pickUpType: 1,
sex: 1,
age: 1
},
}
);
timeData.orderQueryTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (!order) {
return { success: false, message: "订单不存在" };
}
if (order.orderStatus !== "processing") {
return { success: false, message: "当前订单状态不支持开方" };
}
if (!(order.createTime > dayjs().startOf("day").valueOf())) {
return { success: false, message: "当前订单不在有效期内" };
}
timeApi({ type: "addDoctorRxDuration", orderId }, db);
// 提交诊断前, 先判单CA 自动签名是否失效
const res = await conditionalCallBeijingCa({
type: "autoSignVerifyCA",
code: doctorCode,
});
timeData.caSignVerifyTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
const doctorCAUserId = res.userId;
if (!res.success) {
return { success: false, message: "CA自动签名已失效, 请开启自动签" };
}
// 判断是否医生发的消息是否大于2条
const chatCount = await db.collection("im-chat-msg").countDocuments({
From_Account: doctorCode,
To_Account: orderId,
});
timeData.chatCountQueryTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (chatCount < 3) {
return {
success: false,
message: "请先向患者发送2条提问消息后再开方",
};
}
const record = await db
.collection("diagnostic-record")
.findOne(
{ orderId, doctorCode },
{ projection: { _id: 1, status: 1, pharmacistNo: 1 } }
);
timeData.recordQueryTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (record && record.status === status.init) {
return { success: false, message: "该订单已存在诊断信息,请勿重复添加" };
}
if (record && record.status === status.pass) {
return { success: false, message: "该订单已审核通过,请勿重复添加" };
}
if (order.consultType === "onlineMedicinePurchase") {
const { success, message, drugs } = await getMedicinesWithHisChargeInfo(params.drugs, order.areaCode);
if (!success) {
return { success, message }
}
params.drugs = drugs;
}
if (order.consultType === "wineConsult") {
const { success, message, wines } = await getWinesWithHisChargeInfo(params.wines);
if (!success) {
return { success, message }
}
params.wines = wines;
params.pickUpType = order.pickUpType;
}
if (record && record.status === status.unpass) {
return await rewriteConsultDiagnosis(
params,
record._id,
corpId,
record.pharmacistNo,
timeData,
order
);
}
// 获取推荐药师 随机获取药师
const {
success,
message,
data: pharmacist,
} = await getRecommendPharmacist({ type: order.consultType === 'wineConsult' ? 'chinese' : 'west' });
timeData.pharmacistQueryTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (!success) {
return { success: false, message };
}
const common = require('../../common')
const data = {
...params,
createTime: Date.now(),
status: status.init,
pharmacistNo: pharmacist.pharmacistNo,
pharmacist: pharmacist.pharmacistName,
doctorCAUserId,
sex: order.sex,
age: order.age,
prescriptionType: PrescriptionTypeMap[order.consultType],
accountId: order.accountId,
medOrgOrderNo: order.registerId || order.medorg_order_no,
areaCode: order.areaCode,
};
if (order.consultType === 'wineConsult') {
data.medOrgOrderNo = common.generateUniqueStr('R')
}
// 由后端统一设置处方时间:
// - 开始时间从 consult-order 读取(接单时已由后端写入)
// - 结束时间为首次提交医嘱的服务器时间
const hlwConfig = await db.collection('hlw-config').findOne({ corpId });
// 首次开方间隔时间(和接诊时间的时间间隔 单位秒)
const firstSubmitRxIntervel = hlwConfig && Number.isInteger(hlwConfig.firstSubmitRxIntervel) ? hlwConfig.firstSubmitRxIntervel : 0;
// 医生提交处方时间间隔
const submitRxInterval = hlwConfig && Number.isInteger(hlwConfig.submitRxInterval) ? hlwConfig.submitRxInterval : 0;
if (typeof order.prescriptionStartTime !== "undefined") {
data.prescriptionStartTime = order.prescriptionStartTime;
}
data.prescriptionEndTime = Date.now();
if (firstSubmitRxIntervel > 0 && (data.prescriptionEndTime - data.prescriptionStartTime) <= (firstSubmitRxIntervel * 1000)) {
return { success: false, message: `接诊后${firstSubmitRxIntervel}秒内不允许提交处方, 请和患者充分沟通后再开方` }
}
if (!data.medOrgOrderNo) {
data.medOrgOrderNo = order.registerId || order.medorg_order_no;
}
if (!data.accountId && order.accountId) {
data.accountId = order.accountId;
}
if (submitRxInterval > 0) {
const lastSubmitRecord = await db.collection('doctor-last-submit-time').findOne({ doctorCode: data.doctorCode });
const submitTime = lastSubmitRecord && lastSubmitRecord.submitTime > 0 ? lastSubmitRecord.submitTime : 0;
const diff = Math.ceil((Date.now() - submitTime) / 1000);
const interval = Math.ceil(submitRxInterval - diff);
if (interval > 0) {
return { success: false, message: `提交处方太频繁,请${interval}秒后再试` }
}
if (lastSubmitRecord) {
await db.collection('doctor-last-submit-time').updateOne({ doctorCode: data.doctorCode }, { $set: { submitTime: Date.now() } });
} else {
await db.collection('doctor-last-submit-time').insertOne({ doctorCode: data.doctorCode, submitTime: Date.now() });
}
}
if (['onlineMedicinePurchase', 'medicalWinePurchase'].includes(data.prescriptionType)) {
const { medicinePurchaseRxDuration } = await getConfig(corpId);
if (Number.isInteger(medicinePurchaseRxDuration) && medicinePurchaseRxDuration >= 10) {
data.expireTime = dayjs().add(medicinePurchaseRxDuration, 'minute').valueOf();
} else {
return { success: false, message: "配药处方持续时长配置不正确, 请检查配置(最小10分钟)" };
}
}
// 加密敏感字段
const encryptedData = encryptDiagnosticRecordFields(data);
const { insertedId } = await db
.collection("diagnostic-record")
.insertOne(encryptedData);
timeData.insertRecordTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
timeData.rxId = insertedId;
// 发起咨询后, 咨询订单状态变为已完成
await updateOrderStatusAndSendNotification({
orderId,
corpId,
doctorCode,
notification: `处方已开具,审方中.....请稍等`,
syncOtherMachine: 1,
orderStatus: "completed",
msgType: "MEDICALADVICE",
}, timeData);
timeData.duration = dayjs().diff(timeData.startTime, 's');
if (timeData.duration > 3) {
db.collection("perf-observation").insertOne(timeData);
}
return {
success: true,
message: "新增成功",
data: insertedId,
doctorCAUserId,
};
} catch (err) {
return {
success: false,
message: err.message || "新增失败",
};
}
}
// 未通过的处方 重新提交 原药师在线的话
async function rewriteConsultDiagnosis(item, _id, corpId, pharmacistNo, timeData, order) {
const {
complaint,
presentIllness,
dispose,
diagnosisList,
drugs,
orderId,
doctorCode,
} = item;
try {
timeData.type = 'rewriteConsultDiagnosis';
const data = {
complaint,
presentIllness,
dispose,
diagnosisList,
drugs,
wines: item.wines,
updateTime: Date.now(),
status: status.init,
};
const doctorType = order.consultType === 'wineConsult' ? 'chinese' : 'west'
const {
success,
message,
data: pharmacist,
} = await getRecommendPharmacist({ pharmacistNo, type: doctorType });
timeData.pharmacistQueryTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (!success) {
return { success: false, message };
}
// 如果药师不在线, 则重新获取药师 doctorNo doctorName
if (pharmacist && pharmacist.doctorNo !== pharmacistNo) {
data.pharmacistNo = pharmacist.doctorNo;
data.pharmacist = pharmacist.doctorName;
}
// 加密敏感字段(如果有)
const encryptedData = encryptDiagnosticRecordFields(data);
const { modifiedCount } = await db
.collection("diagnostic-record")
.updateOne({ _id }, { $set: encryptedData });
await updateOrderStatusAndSendNotification({
orderId,
corpId,
doctorCode,
notification: "医生重新提交诊断, 等待审方中",
syncOtherMachine: 2,
orderStatus: "completed",
msgType: "REPEATMEDICALADVICE",
}, timeData);
timeData.rewriteStatus = modifiedCount === 1 ? 'success' : 'fail';
timeData.duration = dayjs().diff(timeData.startTime, 's');
if (timeData.duration > 3) {
db.collection("perf-observation").insertOne(timeData);
}
if (modifiedCount === 1) {
return { success: true, message: "更新成功" };
}
return { success: false, message: "更新失败" };
} catch (e) {
return { success: false, message: e.message || "更新失败" };
}
}
async function getDiagnosisById(ctx, db) {
try {
const _id = ObjectId.isValid(ctx.id) ? new ObjectId(ctx.id) : null;
if (!_id) {
return { success: false, message: "参数错误" };
}
const data = await db.collection("diagnostic-record").findOne({ _id });
if (!data) {
return { success: false, message: "查询失败" };
}
// 解密敏感字段
const decryptedData = decryptDiagnosticRecordFields(data);
return { success: true, message: "查询成功", data: decryptedData };
} catch (e) {
return { success: false, message: e?.message }
}
}
async function getOrderDiagnosis(item, db) {
const { orderId, doctorNo: doctorCode, status } = item;
if (typeof orderId !== "string" || orderId.trim() === "") {
return { success: false, message: "参数错误" };
}
try {
// 兼容仅按 orderId 查询的场景(如从购药订单反查处方)
const query = { orderId };
if (typeof doctorCode === "string" && doctorCode.trim() !== "") {
query.doctorCode = doctorCode.trim();
}
if (typeof status === "string" && status.trim() !== "") {
query.status = status;
}
const data = await db.collection("diagnostic-record").findOne(query);
// 解密敏感字段
const decryptedData = decryptDiagnosticRecordFields(data);
return { success: true, message: "查询成功", data: decryptedData };
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getStoreDiagnosisRecord(item, db) {
if (typeof item.storeId !== "string" || item.storeId.trim() === "") {
return { success: false, message: "参数错误" };
}
const page = item.page > 0 && Number.isInteger(item.page) ? item.page : 1;
const pageSize =
item.pageSize > 0 && Number.isInteger(item.pageSize) ? item.pageSize : 20;
const date =
item.date && dayjs(item.date).isValid() ? dayjs(item.date) : dayjs();
const createTime = {
$gte: date.startOf("day").valueOf(),
$lte: date.endOf("day").valueOf(),
};
const query = {
drugStoreNo: item.storeId,
orderSource: "MATEPAD",
status: status.pass,
createTime,
};
if (typeof item.keyword == "string" && item.keyword.trim() !== "") {
// 使用混合搜索支持明文和密文数据
const nameCondition = buildHybridSearchQuery("name", item.keyword, false);
const orConditions = [
{ doctorName: { $regex: item.keyword.trim(), $options: "i" } },
];
// 如果构建了name搜索条件添加到$or中
if (nameCondition && nameCondition.$or) {
orConditions.push(...nameCondition.$or);
} else if (nameCondition) {
orConditions.push(nameCondition);
}
query.$or = orConditions;
}
try {
const total = await db
.collection("diagnostic-record")
.countDocuments(query);
const list = await db
.collection("diagnostic-record")
.find(query)
.sort({ auditTime: -1 })
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
// 查询今日的处方 对已上传但未获取 his处方上传状态的处方进行查询
const start = dayjs().startOf("day").valueOf();
const toSignList = list
.filter(
(i) =>
i.patientId &&
i.medOrgOrderNo &&
i.status === status.pass &&
i.uploadStatus === "uploaded" &&
!i.hisUploadStatus &&
i.createTime > start
)
.map((i) => ({
_id: i._id,
patientId: i.patientId,
medOrgOrderNo: i.medOrgOrderNo,
}));
if (toSignList.length > 0) {
const task = toSignList.map((data) =>
zytHis({
type: "getHisPrescriptionUploadStatus",
orderno: data.medOrgOrderNo,
patientId: data.patientId,
_id: data._id,
})
);
const res = await Promise.all(task);
const result = res.reduce(
(acc, item) => {
if (item.hisUploadStatus === "uploaded") {
acc.uploaded.push(item._id);
} else if (item.hisUploadStatus === "error") {
acc.uploadError.push(item._id);
} else if (item.hisUploadStatus === "notUploaded") {
acc.notUploaded.push(item._id);
}
if (item.hisUploadStatus && item.hisUploadStatus !== "notUploaded") {
acc.map[item.orderno] = item.hisUploadStatus;
}
return acc;
},
{ uploaded: [], uploadError: [], notUploaded: [], map: {} }
);
if (result.uploaded.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.uploaded } },
{ $set: { hisUploadStatus: "uploaded" } }
);
}
if (result.uploadError.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.uploadError } },
{ $set: { hisUploadStatus: "error" } }
);
}
if (result.notUploaded.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.notUploaded }, needReUpload: { $exists: false } },
{ $set: { needReUpload: true } }
);
}
list.forEach((i) => {
if (result.map[i.orderId]) {
i.hisUploadStatus = result.map[i.orderId];
}
});
}
// 解密敏感字段
const decryptedList = decryptDiagnosticRecordList(list);
const wineList = decryptedList.filter(i => i.prescriptionType === 'medicalWinePurchase');
if (wineList.length) {
const wines = await db.collection('chinese-medicine-order').find({ rpNo: { $in: wineList.map(i => i._id.toString()) } }).toArray();
for (let item of wineList) {
if (item.pickUpType === 'selfTake') {
item.wineStatus = 'completed';
continue;
}
const wine = wines.find(i => i.rpNo === item._id.toString());
if (wine) {
item.wineStatus = wine.status;
continue;
}
if (item.expireTime > Date.now()) {
item.wineStatus = 'unpay';
} else {
item.wineStatus = 'expired';
}
}
}
return {
success: true,
message: "查询成功",
list: decryptedList,
total,
paegs: Math.ceil(total / pageSize),
};
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getAuditDiagnosisList(item, db) {
const page = item.page > 0 && Number.isInteger(item.page) ? item.page : 1;
const pageSize =
item.pageSize > 0 && Number.isInteger(item.pageSize) ? item.pageSize : 1;
const query = {
status: status.init,
pharmacistNo:
typeof item.pharmacistNo === "string" ? item.pharmacistNo : "",
};
// 使用混合搜索支持明文和密文数据
const nameCondition = buildHybridSearchQuery("name", item.name, false);
if (nameCondition) {
Object.assign(query, nameCondition);
}
const mobileCondition = buildHybridSearchQuery("mobile", item.mobile, false);
if (mobileCondition) {
Object.assign(query, mobileCondition);
}
if (Array.isArray(item.doctorCodes) && item.doctorCodes.length > 0) {
query.doctorCode = { $in: item.doctorCodes };
}
try {
// 并行执行总数查询和最新时间查询
const [total, res] = await Promise.all([
db.collection("diagnostic-record").countDocuments(query),
db.collection("diagnostic-record").findOne(
{},
{
sort: { createTime: -1 },
projection: { createTime: 1, _id: 0 },
}
),
]);
// 先查询分页的 diagnostic-record 数据
const diagnosticRecords = await db
.collection("diagnostic-record")
.find(query)
.sort({ prescriptionStartTime: 1 })
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
if (diagnosticRecords.length === 0) {
return {
success: true,
message: "查询成功",
list: [],
total,
latestTime: res && res.createTime ? res.createTime : 0,
};
}
// 提取所有 orderId
const orderIds = diagnosticRecords.map((record) => record.orderId);
// 批量查询对应的 consult-order 数据
const orders = await db
.collection("consult-order")
.find({ orderId: { $in: orderIds } })
.toArray();
const decryptedOrders = orders.length > 0 ? decryptOrderList(orders) : orders;
// 创建 orderId 到 order 的映射
const orderMap = decryptedOrders.reduce((map, order) => {
map[order.orderId] = order;
return map;
}, {});
// 合并数据
const list = diagnosticRecords.map((record) => ({
...record,
order: orderMap[record.orderId] || {},
}));
// 解密敏感字段
const decryptedList = decryptDiagnosticRecordList(list);
return {
success: true,
message: "查询成功",
list: decryptedList,
total,
latestTime: res && res.createTime ? res.createTime : 0,
};
} catch (e) {
return { success: false, message: e.message || "查询失败", latestTime: 0 };
}
}
async function getPatientDiagnosisRecord(item, db) {
if (!item.patientId) {
return { success: false, message: "参数错误" };
}
const page = item.page > 0 && Number.isInteger(item.page) ? item.page : 1;
const orderSource = ["ALIPAY_MINI", "MATEPAD"].includes(item.orderSource)
? item.orderSource
: "ALIPAY_MINI";
const pageSize =
item.pageSize > 0 && Number.isInteger(item.pageSize) ? item.pageSize : 20;
const query = { patientId: item.patientId, status: status.pass, orderSource };
if (typeof item.accountId === 'string' && item.accountId.trim()) {
query.accountId = item.accountId.trim()
};
const allQuery = query
try {
const total = await db
.collection("diagnostic-record")
.countDocuments(allQuery);
const list = await db
.collection("diagnostic-record")
.find(allQuery, { sort: { auditTime: -1 } })
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
// 查询今日的处方 对已上传但未获取 his处方上传状态的处方进行查询
const start = dayjs().startOf("day").valueOf();
const toSignList = list
.filter(
(i) =>
i.patientId &&
i.medOrgOrderNo &&
i.status === status.pass &&
i.uploadStatus === "uploaded" &&
!i.hisUploadStatus &&
i.createTime > start
)
.map((i) => ({
_id: i._id,
patientId: i.patientId,
medOrgOrderNo: i.medOrgOrderNo,
}));
if (toSignList.length > 0) {
const task = toSignList.map((data) =>
zytHis({
type: "getHisPrescriptionUploadStatus",
orderno: data.medOrgOrderNo,
patientId: data.patientId,
_id: data._id,
})
);
const res = await Promise.all(task);
const result = res.reduce(
(acc, item) => {
if (item.hisUploadStatus === "uploaded") {
acc.uploaded.push(item._id);
} else if (item.hisUploadStatus === "error") {
acc.uploadError.push(item._id);
} else if (item.hisUploadStatus === "notUploaded") {
acc.notUploaded.push(item._id);
}
if (item.hisUploadStatus && item.hisUploadStatus !== "notUploaded") {
acc.map[item.orderno] = item.hisUploadStatus;
}
return acc;
},
{ uploaded: [], uploadError: [], notUploaded: [], map: {} }
);
if (result.uploaded.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.uploaded } },
{ $set: { hisUploadStatus: "uploaded" } }
);
}
if (result.uploadError.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.uploadError } },
{ $set: { hisUploadStatus: "error" } }
);
}
if (result.notUploaded.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.notUploaded }, needReUpload: { $exists: false } },
{ $set: { needReUpload: true } }
);
}
list.forEach((i) => {
if (result.map[i.orderId]) {
i.hisUploadStatus = result.map[i.orderId];
}
});
}
// 解密敏感字段
const decryptedList = decryptDiagnosticRecordList(list);
return {
success: true,
message: "查询成功",
list: decryptedList,
total,
paegs: Math.ceil(total / pageSize),
};
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getPatientPassDiagnosisRecord(ctx, db) {
const { startDate, endDate, patientId } = ctx;
if (typeof patientId !== "string" || patientId.trim() === "") {
return { success: false, message: "参数错误" };
}
const startTime =
startDate && dayjs(startDate).isValid()
? dayjs(startDate).startOf("day").valueOf()
: "";
const endTime =
endDate && dayjs(endDate).isValid()
? dayjs(endDate).endOf("day").valueOf()
: "";
try {
const query = { patientId, status: status.pass };
if (startTime && endTime) {
query.createTime = { $gte: startTime, $lte: endTime };
}
const res = await db
.collection("diagnostic-record")
.find(query)
.sort({ createTime: -1 })
.toArray();
// 解密敏感字段
const decryptedRes = decryptDiagnosticRecordList(res);
return { success: true, message: "查询成功", data: decryptedRes };
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getAuditedDiagnosisList(item, db) {
const page = item.page > 0 && Number.isInteger(item.page) ? item.page : 1;
const pageSize =
item.pageSize > 0 && Number.isInteger(item.pageSize) ? item.pageSize : 1;
const query = {
status: {
$in: [
status.pass,
status.unpass,
status.expired,
status.invalid,
status.passInvalid,
status.unpassInvalid,
],
},
pharmacistNo:
typeof item.pharmacistNo === "string" ? item.pharmacistNo : "",
};
// 使用混合搜索支持明文和密文数据
const nameCondition = buildHybridSearchQuery("name", item.name, false);
if (nameCondition) {
Object.assign(query, nameCondition);
}
const mobileCondition = buildHybridSearchQuery("mobile", item.mobile, false);
if (mobileCondition) {
Object.assign(query, mobileCondition);
}
if (Array.isArray(item.doctorCodes) && item.doctorCodes.length > 0) {
query.doctorCode = { $in: item.doctorCodes };
}
try {
const total = await db
.collection("diagnostic-record")
.countDocuments(query);
// 先查询分页的 diagnostic-record 数据,按审核时间排序
const diagnosticRecords = await db
.collection("diagnostic-record")
.find(query)
.sort({ auditTime: -1 })
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
if (diagnosticRecords.length === 0) {
return {
success: true,
message: "查询成功",
list: [],
total,
};
}
// 提取所有 orderId
const orderIds = diagnosticRecords.map((record) => record.orderId);
// 批量查询对应的 consult-order 数据
const orders = await db
.collection("consult-order")
.find({ orderId: { $in: orderIds } })
.toArray();
const decryptedData = orders ? decryptOrderList(orders) : orders;
// 创建 orderId 到 order 的映射
const orderMap = decryptedData.reduce((map, order) => {
map[order.orderId] = order;
return map;
}, {});
// 合并数据
const list = diagnosticRecords.map((record) => ({
...record,
order: orderMap[record.orderId] || {},
}));
// 解密敏感字段
const decryptedList = decryptDiagnosticRecordList(list);
return {
success: true,
message: "查询成功",
list: decryptedList,
total,
};
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function auditDiagnosis(item, db) {
const { pharmacistNo, pharmacist } = item;
const timeData = { type: 'auditDiagnosis', startTime: dayjs().format('YYYY-MM-DD HH:mm:ss') };
const res = await conditionalCallBeijingCa({
type: "autoSignVerifyCA",
code: pharmacistNo,
}, db);
timeData.caSignVerifyTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
if (!res.success) {
return { success: false, message: "CA自动签名已失效, 请开启自动签" };
}
const pharmacistCAUserId = res.userId;
if (![status.pass, status.unpass].includes(item.status)) {
return { success: false, message: "状态错误" };
}
if (!pharmacistNo || !pharmacist) {
return { success: false, message: "审方药师信息不能为空" };
}
const ids = Array.isArray(item.ids) ? item.ids.filter(i => typeof i === 'string' && i.trim() !== '') : [];
if (ids.length === 0) {
return { success: false, message: "id错误" };
}
const reasons = Array.isArray(item.reasons)
? item.reasons.filter((i) => typeof i === "string" && i.trim() !== "")
: [];
if (item.status === status.unpass && reasons.length === 0) {
return { success: false, message: "请填写拒绝原因" };
}
try {
// 1. 根据待审核id 查询待处理的处方记录
const _rxList = await db.collection("diagnostic-record").find(
{ _id: { $in: ids.map((id) => new ObjectId(id)) }, status: status.init, pharmacistNo },
// { projection: { orderId: 1, _id: 1, name: 1, sex: 1, age: 1, drugs: 1, prescriptionType: 1, diagnosisList: 1 } }
).toArray();
// 患者姓名 证件号 手机号解密
const rxList = _rxList.map(i => decryptDiagnosticRecordFields(i));
// 2. 根据处方记录的orderId 查询对应的咨询记录
const consultOrderList = await db.collection("consult-order").find(
{ orderId: { $in: rxList.map((i) => i.orderId) } },
{ projection: { _id: 1, orderId: 1, orderStatus: 1, medorg_order_no: 1 } }
).toArray();
//3. 根据咨询记录的状态 将待处理的处方列表分为三组 passList, unPassList , expireList, failList
const failList = [];
const passList = [];
const unPassList = [];
const expireList = [];
const targetList = item.status === status.pass ? passList : unPassList;
for (let id of ids) {
const rx = rxList.find(i => i._id.toString() === id);
if (!rx) {
failList.push({ id, message: "处方不存在" });
continue;
}
const data = { rx, status: item.status };
const order = consultOrderList.find(i => i.orderId === rx.orderId && rx.orderId);
data.order = order;
if (order && ["pending", "processing", "completed"].includes(order.orderStatus)) {
targetList.push(data);
} else if (order) {
data.status = status.expired;
expireList.push(data)
} else {
failList.push({ id, message: "咨询订单不存在" });
}
}
const statsCount = {
allCount: targetList.length + expireList.length, // 总待处理条数
handleCount: 0, // 审核通过或者审核不通过的处理条数
expireCount: 0 // 已过期处理成功条数
}
// 4. 根据分组 分别处理
if (passList.length) {
let successRxList = [];
const uploadResult = await Promise.all(passList.map(i => uploadRx2His(i.rx, i.order)));
uploadResult.forEach(i => {
if (i.success) {
const rx = passList.find(j => j.rx._id.toString() === i.id.toString());
successRxList.push(rx);
} else {
failList.push({ id: i.id, message: i.message });
}
})
const { modifiedCount } = await db.collection("diagnostic-record").updateMany(
{ _id: { $in: successRxList.map(i => i.rx._id) } },
{
$set: {
uploadStatus: "uploaded",
status: status.pass,
auditTime: Date.now(),
}
}
)
statsCount.handleCount += modifiedCount;
// 处方签名
successRxList.forEach(({ rx }) => sign(rx, pharmacistCAUserId))
// 发送审核通过消息
successRxList.forEach(({ rx }) => attempToSendPassMessage(rx, item.corpId))
}
if (unPassList.length) {
const { modifiedCount } = await db.collection("diagnostic-record").updateMany(
{ _id: { $in: unPassList.map(i => i.rx._id) }, status: status.init },
{
$set: {
status: item.status,
auditTime: Date.now(),
reasons
}
}
)
statsCount.handleCount += modifiedCount;
await db.collection("consult-order").updateMany(
{ orderId: { $in: unPassList.map(i => i.rx.orderId) } },
{ $set: { orderStatus: "processing" } }
)
unPassList.forEach(({ rx }) => attempToSendUnPassMessage(rx, item.corpId, pharmacist, reasons))
// 记录一下 药师拒绝的操作
db.collection("pharmacist-reject-record").insertMany(
unPassList.map((item) => ({
recordId: item.rx._id.toString(),
type: "pharmacistReject",
pharmacistNo,
pharmacist,
reasons,
createTime: Date.now(),
}))
)
}
if (expireList.length) {
const { modifiedCount } = await db.collection("diagnostic-record").updateMany(
{ _id: { $in: expireList.map(i => i.rx._id) }, status: status.init },
{ $set: { status: status.expired }, updateTime: Date.now() }
)
statsCount.expireCount += modifiedCount;
}
return {
success: statsCount.handleCount > 0,
message: `已审核${item.status === status.pass ? "通过" : "不通过"}${statsCount.handleCount}条数据${statsCount.expireCount > 0 ? `, 已过期${statsCount.expireCount}条数据` : ''}`,
failList
}
} catch (e) {
return { success: false, message: e.message || "审核失败" };
}
}
async function uploadRx2His(rx, order) {
const hisUploadFn = {
storeMedicinePurchase: 'hlwuploadprescription',
onlineMedicinePurchase: 'uploadMedicinePurchaseRx',
medicalWinePurchase: 'uploadWinePurchaseRx',
}
const formatFn = {
storeMedicinePurchase: formatUploadRxData,
onlineMedicinePurchase: formatOnlineMedicinePurchaseData,
medicalWinePurchase: formatWinePurchaseData,
}
try {
const uploadData = formatFn[rx.prescriptionType](rx, order);
const type = hisUploadFn[rx.prescriptionType];
const { success, message } = await zytHis({
type,
data: uploadData
})
return { success, message, id: rx._id }
} catch (e) {
return { success: false, message: `[审核处方上传错误]: ${e.message}`, id: rx._id }
}
}
async function attempToSendPassMessage(rx, corpId) {
for (let i = 0; i < 10; i++) {
try {
const { success, message } = await tencentIM({
type: "sendSystemNotification",
corpId,
formAccount: rx.doctorCode,
toAccount: rx.orderId,
SyncOtherMachine: 1,
msgBody: [
{
MsgType: "TIMCustomElem",
MsgContent: {
Data: "AUDIPASS",
Ext: JSON.stringify({
id: rx._id,
orderId: rx.orderId,
name: rx.name,
expireTime: rx.expireTime ? dayjs(rx.expireTime).format("YYYY-MM-DD HH:mm") : '',
time: dayjs(rx.createTime).format("YYYY-MM-DD HH:mm"),
sex: rx.sex,
age: rx.age,
prescriptionType: rx.prescriptionType,
pickUpType: rx.pickUpType,
disease: rx.diagnosisList.map(d => d.name).join(", "),
drugs: rx.drugs.map(d => ({
drugName: d.drugName,
spec: d.specification,
quantity: d.quantity,
unit: d.unit,
usageName: d.usageName,
frequencyName: d.frequencyName,
days: d.days,
dosage: d.dosage,
dosage_unit: d.dosage_unit
})),
wines: Array.isArray(rx.wines) ? rx.wines.map(w => ({
name: w.name,
quantity: w.quantity,
details: w.details,
efficacy: w.efficacy,
})) : []
})
},
},
],
})
if (success) {
break;
}
console.log(`[发送处方审核通过消息失败(第${i + 1}次)]: ${message}`);
await new Promise(resolve => setTimeout(resolve, 500 + 100 * i));
} catch (e) {
console.log(`[发送处方审核通过消息错误(第${i + 1}次)]: ${e.message}`);
}
}
}
async function attempToSendUnPassMessage(rx, corpId, pharmacist, reasons) {
for (let i = 0; i < 10; i++) {
try {
const { success, message } = await tencentIM({
type: "sendSystemNotification",
corpId,
formAccount: rx.orderId,
toAccount: rx.doctorCode,
SyncOtherMachine: 2,
msgBody: [
{
MsgType: "TIMCustomElem",
MsgContent: {
Data: "AUDIFAIL",
Desc: "notification",
Ext: `药师${pharmacist}审方不通过,驳回原因:${reasons.join(",")}`,
},
},
],
})
if (success) {
break;
}
console.log(`[发送处方审核通过消息失败(第${i + 1}次)]: ${message}`);
await new Promise(resolve => setTimeout(resolve, 500 + 100 * i));
} catch (e) {
console.log(`[发送处方审核通过消息错误(第${i + 1}次)]: ${e.message}`);
}
}
}
// 对医生和药师进行签名
async function sign(item, pharmacistCAUserId) {
const { doctorCAUserId, pharmacist } = item;
console.log("进入签名");
const oriData = getOriData(item);
const doctorRes = await conditionalCallBeijingCa(
{
type: "autoSign",
userId: doctorCAUserId,
oriData,
},
db
);
const pharmacistRes = await conditionalCallBeijingCa(
{
type: "autoSign",
userId: pharmacistCAUserId,
oriData: `${oriData} 药师${pharmacist}审方通过`,
},
db
);
console.log("医生签名结果", doctorRes);
console.log("药师签名结果", pharmacistRes);
}
function getOriData(data) {
const doctorName = data.doctorName;
const patientName = data.name;
const diagnosis = data.diagnosisList.map((d) => d.name).join(", ");
const drugs = data.drugs
.map(
(d) =>
`${d.drugName} (${d.dosage}${d.dosage_unit}, ${d.frequencyName}, ${d.days}天)`
)
.join(", ");
return `医生${doctorName}向患者${patientName}开具的诊断是${diagnosis},开具的药物是${drugs}`;
}
async function uploadDiagnosis(ids) {
if (!Array.isArray(ids) || ids.length == 0)
return {
success: false,
message: "参数错误",
};
try {
const res = await db
.collection("diagnostic-record")
.find({ _id: { $in: ids }, status: status.pass })
.limit(ids.length)
.toArray();
const list = res.map((item) => ({
payload: formatUploadRxData(item),
_id: item._id,
}));
const res1 = await Promise.all(
list.map((item) =>
zytHis({
type: "hlwuploadprescription",
payload: item.payload,
_id: item._id,
})
)
);
const successIds = res1.filter((i) => i.success).map((i) => i._id);
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: successIds } },
{ $set: { uploadStatus: "uploaded" } }
);
const successCount = successIds.length;
return {
success: true,
message: `成功上传${successCount}条数据`,
};
} catch (err) {
console.log(err, err.message);
return {
success: false,
message: err.message || "上传失败",
};
}
}
/**
*
* orderStatus completed(已完成) processing(处理中) pending(待处理) cancelled(已取消) finished(已结束)
* syncOtherMachine 若不希望将消息同步至 From_Account SyncOtherMachine 填写2若希望将消息同步至 From_Account SyncOtherMachine 填写1
* MsgType TIMTextElem文本消息 TIMLocationElem位置消息 TIMFaceElem表情消息 TIMCustomElem自定义消息 TIMSoundElem语音消息 TIMImageElem图像消息 TIMFileElem文件消息 TIMVideoFileElem视频消息
* MsgContent.Text 文本消息内容
* MsgContent.Data 自定义消息类型 MEDICALADVICE(医嘱)
* MsgContent.Desc notification
*
*/
async function updateOrderStatusAndSendNotification(item, timeData) {
const {
orderId,
doctorCode,
corpId,
notification,
syncOtherMachine,
orderStatus,
msgType,
} = item;
await consultOrder(
{
type: "updateConsultOrderStatus",
orderId,
orderStatus,
corpId,
},
db
);
if (timeData) {
timeData.updateOrderStatusTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
}
await tencentIM({
type: "sendSystemNotification",
corpId,
formAccount: orderId,
toAccount: doctorCode,
SyncOtherMachine: syncOtherMachine,
msgBody: [
{
MsgType: "TIMCustomElem",
MsgContent: {
Data: msgType,
Desc: "notification",
Ext: notification,
},
},
],
});
if (timeData) {
timeData.sendNotificationTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
}
}
async function getLatestSubmitTime(ctx) {
try {
const pharmacistNo = typeof ctx.pharmacistNo === "string" ? ctx.pharmacistNo : "";
if (!pharmacistNo) {
return {
success: true,
message: "获取成功",
data: 0,
};
}
const res = await db.collection("diagnostic-record").findOne(
{ pharmacistNo },
{
sort: { createTime: -1 }, // Sort by createTime in descending order
projection: { createTime: 1, _id: 0 }, // Only return the createTime field, exclude _id
}
);
const reUploadCount = await db.collection('diagnostic-record').countDocuments({
prescriptionType: 'storeMedicinePurchase',
pharmacistNo,
needReUpload: true,
createTime: { $gt: dayjs().startOf('day').valueOf() }
});
return {
success: true,
message: "获取成功",
data: res ? res.createTime : 0,
reUploadCount
};
} catch (e) {
return { success: false, message: e.message || "获取失败", data: 0 };
}
}
async function orderHasDiagnosis(item) {
if (typeof item.patientId !== "string" || typeof item.orderId !== "string") {
return {
success: false,
message: "参数错误",
};
}
try {
const count = await db.collection("diagnostic-record").countDocuments({
patientId: item.patientId,
orderId: item.orderId,
});
return { success: true, message: "查询成功", exist: count > 0 };
} catch (e) {
return { success: true, message: "查询成功", exist: false };
}
}
async function reUploadDiagnosticRecord({ _id }) {
try {
const data = await db
.collection("diagnostic-record")
.findOne({ _id: new ObjectId(_id) });
if (!data) return { success: false, message: "处方不存在" };
if (data.prescriptionType !== "storeMedicinePurchase") {
return { success: false, message: "暂只支持门店处方重新上传" };
}
if (data && data.uploadStatus === "uploaded")
return { success: false, message: "处方已上传" };
const { uploaded } = await zytHis({
type: "hlwPrescriptionOrderStatus",
orderno: data.orderId,
patientId: data.patientId,
});
if (uploaded) {
await db
.collection("diagnostic-record")
.updateOne(
{ _id: new ObjectId(_id) },
{ $set: { uploadStatus: "uploaded", hisUploadStatus: "uploaded" } }
);
return { success: true, message: "处方上传成功" };
}
const payload = formatUploadRxData(data);
const { success, message } = await zytHis({
type: "hlwuploadprescription",
payload,
_id: data._id,
});
if (success) {
await db
.collection("diagnostic-record")
.updateOne(
{ _id: new ObjectId(_id) },
{ $set: { uploadStatus: "uploaded" } }
);
return { success: true, message: "处方上传成功" };
}
return { success: false, message: message || "重新上传失败" };
} catch (e) {
return { success: false, message: e.message || "重新上传失败" };
}
}
// 废弃处方
async function discardDiagnosticRecord(ctx) {
const { orderId } = ctx;
if (typeof orderId !== "string" || orderId.trim() === "")
return { success: false, message: "参数错误" };
try {
const item = await db.collection("diagnostic-record").findOne(
{
orderId,
status: {
$nin: [status.passInvalid, status.invalid, status.unpassInvalid],
},
},
{ projection: { status: 1, _id: 1 } }
);
if (item) {
const targetStatus =
item.status === status.pass
? status.passInvalid
: item.status === status.unpass
? status.unpassInvalid
: status.invalid;
await db.collection("diagnostic-record").updateOne(
{ _id: item._id },
{
$set: {
status: targetStatus,
},
}
);
return { success: true, message: "废弃成功" };
}
return { success: false, message: "处方不存在" };
} catch (e) {
return { success: false, message: e.message || "废弃失败" };
}
}
async function getAllDiagnosisRecord(ctx) {
const { page, pageSize } = ctx;
const pageNum = page > 0 && Number.isInteger(page) ? page : 1;
const size = pageSize > 0 && Number.isInteger(pageSize) ? pageSize : 20;
const insuranceCodes = Array.isArray(ctx.insuranceCodes) ? ctx.insuranceCodes.filter(i => typeof i === 'string' && i.trim()) : [];
try {
const query = {};
// 使用混合搜索支持明文和密文数据
const nameCondition = buildHybridSearchQuery("name", ctx.name, false);
if (nameCondition) {
Object.assign(query, nameCondition);
}
if (Array.isArray(ctx.doctorCodes) && ctx.doctorCodes.length > 0) {
query.doctorCode = { $in: ctx.doctorCodes };
}
if (Array.isArray(ctx.pharmacistNos) && ctx.pharmacistNos.length > 0) {
query.pharmacistNo = { $in: ctx.pharmacistNos };
}
const { startDate, endDate } = ctx;
if (startDate && dayjs(startDate).isValid()) {
query.createTime = { $gte: dayjs(startDate).startOf("day").valueOf() };
}
if (endDate && dayjs(endDate).isValid()) {
query.createTime = {
...(query.createTime || {}),
$lte: dayjs(endDate).endOf("day").valueOf(),
};
}
const { auditStartDate, auditEndDate } = ctx;
if (auditStartDate && dayjs(auditStartDate).isValid()) {
query.auditTime = {
$gte: dayjs(auditStartDate).startOf("day").valueOf(),
};
}
if (auditEndDate && dayjs(auditEndDate).isValid()) {
query.auditTime = {
...(query.auditTime || {}),
$lte: dayjs(auditEndDate).endOf("day").valueOf(),
};
}
if (Array.isArray(ctx.status)) {
query.status = { $in: ctx.status };
}
if (ctx.preType === 'chinese') {
query.prescriptionType = 'medicalWinePurchase';
} else if (ctx.preType === 'west') {
query.prescriptionType = { $ne: 'medicalWinePurchase' };
}
if (insuranceCodes.length) {
query.drugs = { $elemMatch: { insurance_code: { $in: insuranceCodes } } }
}
const total = await db
.collection("diagnostic-record")
.countDocuments(query);
const list = await db.collection("diagnostic-record").aggregate([
{ $match: query },
{ $sort: { createTime: -1 } },
{ $skip: (pageNum - 1) * size },
{ $limit: size },
{
$lookup: {
from: "consult-order",
localField: "orderId",
foreignField: "orderId",
as: "orderInfo"
}
},
{
$addFields: {
sex: { $arrayElemAt: ["$orderInfo.sex", 0] },
age: { $arrayElemAt: ["$orderInfo.age", 0] }
}
},
{
$project: {
orderInfo: 0
}
}
]).toArray()
// 解密敏感字段
const decryptedList = decryptDiagnosticRecordList(list);
const pages = Math.ceil(total / size);
// 兼容旧用法(直接返回 list/total同时为 PC 端提供 data 包装
return {
success: true,
message: "查询成功",
list: decryptedList,
total,
pages,
page: pageNum,
pageSize: size,
data: {
list: decryptedList,
total,
pages,
page: pageNum,
pageSize: size,
},
};
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getRecommendPharmacist({ pharmacistNo = "", type = 'west' }) {
try {
const query = {
job: "pharmacist",
onlineStatus: "online",
serviceStatus: "enabled",
}
if (type === 'chinese') {
query.openChinesePres = true;
} else {
query.openWestPres = true
}
const nos = await db
.collection("hlw-doctor")
.find(
query,
{ projection: { doctorNo: 1, doctorName: 1 } }
)
.toArray();
const pharmacistNos = nos.map((item) => item.doctorNo);
const matchPharmacist = nos.find(
(item) => pharmacistNo && item.doctorNo === pharmacistNo
);
if (matchPharmacist) {
return {
success: true,
message: "获取推荐药师成功",
data: matchPharmacist,
};
}
if (nos.length === 0) {
return { success: false, message: "当前没有药师在线,请稍后处理" };
}
const res = await getTodayPharmacistCount({ pharmacistNos }, db);
if (!res.success) {
return res;
}
const {
data: [countMap],
} = res;
const auditCount =
countMap && Array.isArray(countMap.auditCount) ? countMap.auditCount : [];
const auditedCount =
countMap && Array.isArray(countMap.auditedCount)
? countMap.auditedCount
: [];
const list = nos
.map((item) => {
const audit = auditCount.find((i) => i._id === item.doctorNo);
const audited = auditedCount.find((i) => i._id === item.doctorNo);
const auditNum = audit ? audit.count : 0;
const auditedNum = audited ? audited.count : 0;
return {
pharmacistNo: item.doctorNo,
doctorNo: item.doctorNo,
pharmacistName: item.doctorName,
doctorName: item.doctorName,
weight: new BigNumber(auditNum)
.plus(new BigNumber(auditedNum).dividedBy(1000000)) //权重计算 已经审核过的权重占比小一点
.toNumber(),
};
})
.sort((a, b) => a.weight - b.weight); // 按照权重升序排序
const [{ weight }] = list;
const lightList = list.filter((i) => i.weight === weight); // 取出权重最小的药师
const randomIndex = Math.floor(Math.random() * lightList.length); // 随机选取一个药师
const pharmacist = lightList[randomIndex];
return { success: true, message: "获取推荐药师成功", data: pharmacist };
} catch (e) {
return {
success: false,
message: e.message || "获取推荐药师失败",
};
}
}
async function getTodayPharmacistCount(ctx) {
const pharmacistNos = Array.isArray(ctx.pharmacistNos)
? ctx.pharmacistNos.filter((i) => typeof i === "string")
: [ctx.pharmacistNos];
try {
const res = await db
.collection("diagnostic-record")
.aggregate([
{
$match: {
pharmacistNo: { $in: pharmacistNos },
createTime: {
$gt: dayjs().startOf("day").valueOf(),
$lte: dayjs().endOf("day").valueOf(),
},
},
},
{
$facet: {
auditCount: [
{ $match: { status: status.init } },
{ $group: { _id: "$pharmacistNo", count: { $sum: 1 } } },
],
auditedCount: [
{ $match: { status: { $in: [status.pass, status.unpass] } } },
{ $group: { _id: "$pharmacistNo", count: { $sum: 1 } } },
],
},
},
])
.toArray();
return { success: true, message: "查询成功", data: res };
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getDoctorRxStats(ctx) {
const { doctorCodes, startDate, endDate } = ctx;
const query = {};
if (Array.isArray(doctorCodes)) {
query.doctorCode = { $in: doctorCodes };
}
if (startDate && dayjs(startDate).isValid()) {
query.createTime = { $gte: dayjs(startDate).startOf("day").valueOf() };
}
if (endDate && dayjs(endDate).isValid()) {
query.createTime = {
...(query.createTime || {}),
$lte: dayjs(endDate).endOf("day").valueOf(),
};
}
if (typeof ctx.orderSource === "string" && ctx.orderSource.trim() !== "") {
query.orderSource = ctx.orderSource;
}
console.log("查询医生处方统计", query);
try {
const res = await db
.collection("diagnostic-record")
.aggregate(
[
{ $match: query },
{
$group: {
_id: "$doctorCode",
doctorName: { $first: "$doctorName" },
count: { $sum: 1 },
passCount: {
$sum: { $cond: [{ $eq: ["$status", status.pass] }, 1, 0] },
},
passInvalidCount: {
$sum: {
$cond: [{ $eq: ["$status", status.passInvalid] }, 1, 0],
},
},
},
},
],
{ allowDiskUse: true }
)
.toArray();
return { success: true, message: "查询成功", data: res };
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getPharmacistRxStats(ctx) {
const { pharmacistNos, startDate, endDate } = ctx;
const query = {};
if (Array.isArray(pharmacistNos)) {
query.pharmacistNo = { $in: pharmacistNos };
}
if (startDate && dayjs(startDate).isValid()) {
query.createTime = { $gte: dayjs(startDate).startOf("day").valueOf() };
}
if (endDate && dayjs(endDate).isValid()) {
query.createTime = {
...(query.createTime || {}),
$lte: dayjs(endDate).endOf("day").valueOf(),
};
}
try {
const res = await db
.collection("diagnostic-record")
.aggregate([
{ $match: query },
{
$group: {
_id: "$pharmacistNo",
doctorName: { $first: "$pharmacist" },
count: { $sum: 1 },
auditCount: {
$sum: {
$cond: [
{
$in: [
"$status",
[status.pass, status.invalid, status.passInvalid],
],
},
1,
0,
],
},
},
expiredCount: {
$sum: { $cond: [{ $eq: ["$status", status.expired] }, 1, 0] },
},
},
},
])
.toArray();
const rejectRes = await db
.collection("pharmacist-reject-record")
.aggregate([
{ $match: query },
{
$group: {
_id: "$pharmacistNo",
doctorName: { $first: "$pharmacist" },
rejectCount: { $sum: 1 },
},
},
])
.toArray();
return { success: true, message: "查询成功", data: res, rejectRes };
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function checkRxUploadStatus(ctx) {
const { orderId, registerId, patientId } = ctx;
if (typeof orderId !== "string" || orderId.trim() === "") {
return { success: false, message: "订单号不能为空" };
}
if (typeof registerId !== "string" || registerId.trim() === "") {
return { success: false, message: "挂号号不能为空" };
}
if (typeof patientId !== "string" || patientId.trim() === "") {
return { success: false, message: "患者id不能为空" };
}
try {
const rx = await db.collection("diagnostic-record").findOne({
orderId,
patientId
});
if (!rx) {
return { success: false, message: "处方不存在" };
}
const { status } = await zytHis({
type: "hlwPrescriptionOrderStatus",
orderno: rx.medOrgOrderNo,
patientId,
});
if (status === "0") {
return {
success: true,
message: "正在获取订单信息请等待1分钟后再发起退费申请!",
};
} else if (["1", "2", "3"].includes(status)) {
return { success: true, message: "处方已上传或者已经作废" };
}
return { success: false, message: "处方上传状态未知,请稍后再试" };
} catch (e) {
return { success: false, message: e.message || "查询失败" };
}
}
async function getAccountRxList(ctx) {
try {
if (typeof ctx.accountId !== 'string' || ctx.accountId.trim() === '') {
return { success: false, message: "账号id不能为空" };
}
const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1;
const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10;
const query = { orderSource: "ALIPAY_MINI", accountId: ctx.accountId.trim(), status: status.pass };
const [list, total] = await Promise.all([
db.collection("diagnostic-record").find(query, { projection: types.output.accountRxList }).sort({ createTime: -1 }).skip((page - 1) * pageSize).limit(pageSize).toArray(),
db.collection("diagnostic-record").countDocuments(query),
]);
await getHisPrescriptionUploadStatus(list);
// 获取处方单号
const rpNos = list.filter(i => i.prescriptionType === 'onlineMedicinePurchase').map(i => i._id.toString());
const orderList = await db.collection("medicine-purchase-order").find({ rpNo: { $in: rpNos } }, { projection: types.output.medicinePurchaseOrder }).toArray();
return { success: true, message: "查询成功", orderList, list: decryptDiagnosticRecordList(list), total, pages: Math.ceil(total / pageSize), now: Date.now() };
} catch (e) {
return { success: false, message: `获取处方记录失败:${e?.message || '未知错误 '}` };
}
}
async function getRxDetail(ctx) {
try {
if (typeof ctx.id !== 'string' || ctx.id.trim() === '') {
return { success: false, message: "处方id不能为空" };
}
const query = {};
query._id = new ObjectId(ctx.id.trim());
if (typeof ctx.accountId === 'string' && ctx.accountId.trim() !== '') {
query.accountId = ctx.accountId.trim();
}
const record = await db.collection("diagnostic-record").findOne(query);
if (!record) {
return { success: false, message: "处方不存在" };
}
if (record.prescriptionType === 'onlineMedicinePurchase') {
const order = await db.collection("medicine-purchase-order").findOne({ rpNo: record._id.toString() }, { projection: types.output.medicinePurchaseOrder });
if (order) {
record.purchaseOrder = order;
}
}
return { success: true, message: "查询成功", data: decryptDiagnosticRecordFields(record), now: Date.now() };
} catch (e) {
return { success: false, message: `获取处方详情失败:${e?.message || '未知错误 '}` };
}
}
async function getHisPrescriptionUploadStatus(list) {
try {
const toSignList = list.filter(i => i.prescriptionType === 'storeMedicinePurchase' && i.medOrgOrderNo && i.hisUploadStatus === 'uploaded' && !i.hisUploadStatus && i.createTime > dayjs().startOf("day").valueOf()).map(i => ({
_id: i._id,
patientId: i.patientId,
medOrgOrderNo: i.medOrgOrderNo,
}));
if (toSignList.length > 0) {
const task = toSignList.map((data) =>
zytHis({
type: "getHisPrescriptionUploadStatus",
orderno: data.medOrgOrderNo,
patientId: data.patientId,
_id: data._id,
})
);
const res = await Promise.all(task);
const result = res.reduce(
(acc, item) => {
if (item.hisUploadStatus === "uploaded") {
acc.uploaded.push(item._id);
} else if (item.hisUploadStatus === "error") {
acc.uploadError.push(item._id);
} else if (item.hisUploadStatus === "notUploaded") {
acc.notUploaded.push(item._id);
}
if (item.hisUploadStatus && item.hisUploadStatus !== "notUploaded") {
acc.map[item.orderno] = item.hisUploadStatus;
}
return acc;
},
{ uploaded: [], uploadError: [], notUploaded: [], map: {} }
);
if (result.uploaded.length > 0) {
db.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.uploaded } },
{ $set: { hisUploadStatus: "uploaded" } }
);
}
if (result.uploadError.length > 0) {
db.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.uploadError } },
{ $set: { hisUploadStatus: "error" } }
);
}
if (result.notUploaded.length > 0) {
await db
.collection("diagnostic-record")
.updateMany(
{ _id: { $in: result.notUploaded }, needReUpload: { $exists: false } },
{ $set: { needReUpload: true } }
);
}
list.forEach((i) => {
if (result.map[i.orderId]) {
i.hisUploadStatus = result.map[i.orderId];
}
});
}
} catch (e) {
console.log('查询his上传信息错误: ', e.message)
}
}
async function getAccountHistoryDrugs(ctx) {
try {
const patientId = typeof ctx.patientId === 'string' && ctx.patientId.trim() !== '' ? ctx.patientId.trim() : '';
const accountId = typeof ctx.accountId === 'string' && ctx.accountId.trim() !== '' ? ctx.accountId.trim() : '';
if (accountId.value == '') {
return { success: false, message: "账号id不能为空" };
}
const query = { accountId, status: status.pass };
if (patientId) {
query.patientId = patientId;
}
const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1;
const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10;
const [list, total] = await Promise.all([
db.collection("diagnostic-record").find(query, { projection: types.output.accountHistoryDrugs }).sort({ createTime: -1 }).skip((page - 1) * pageSize).limit(pageSize).toArray(),
db.collection("diagnostic-record").countDocuments(query),
]);
return { success: true, message: "查询成功", data: list, total, pages: Math.ceil(total / pageSize) };
} catch (e) {
return { success: false, message: `获取账号历史药品错误:${e?.message || '未知错误 '}` };
}
}
async function getPatientHistoryDrugs(ctx) {
try {
const patientId = typeof ctx.patientId === 'string' && ctx.patientId.trim() !== '' ? ctx.patientId.trim() : '';
if (patientId.value == '') {
return { success: false, message: "患者id不能为空" };
}
const query = { patientId, status: status.pass, prescriptionType: { $ne: 'medicalWinePurchase' } };
const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1;
const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10;
const [list, total] = await Promise.all([
db.collection("diagnostic-record").find(query, { projection: types.output.accountHistoryDrugs }).sort({ createTime: -1 }).skip((page - 1) * pageSize).limit(pageSize).toArray(),
db.collection("diagnostic-record").countDocuments(query),
]);
return { success: true, message: "查询成功", data: list, total, pages: Math.ceil(total / pageSize) };
} catch (e) {
return { success: false, message: `获取患者历史药品错误:${e?.message || '未知错误 '}` };
}
}
/**
* 获取药品的his收费信息(药品列表中添加his收费信息)
* @param {*} medicines 药品列表
* @param {*} areaCode 医保区域代码
* @returns
*/
async function getMedicinesWithHisChargeInfo(medicines, areaCode) {
try {
if (!Array.isArray(medicines) || medicines.length === 0) {
return { success: false, message: "药品列表不能为空" };
}
if (typeof areaCode !== 'string' || areaCode.trim() === '') {
return { success: false, message: "区域代码不能为空" };
}
const insuranceCodes = medicines.map(i => i.insurance_code);
const { success, message, data } = await zytHis({ type: 'getHisDrugInfo', insuranceCodes, areaCode });
if (!success) {
return { success, message };
}
const hisDrugs = data && Array.isArray(data) ? data : [];
const drugs = [];
for (const med of medicines) {
const hisDrug = hisDrugs.find(j => med.insurance_code && med.insurance_code === j.gjbm);
if (!hisDrug) {
return { success: false, messsage: `药品【${med.drugName}】医保编码在his中不存在` };
}
const quantity = Number.isInteger(med.quantity) && med.quantity > 0 ? med.quantity : 0;
if (quantity === 0) {
return { success: false, messsage: `药品【${med.drugName}】数量不是正整数` };
}
const pack_retprice = Number(hisDrug.pack_retprice) == hisDrug.pack_retprice && hisDrug.pack_retprice > 0 && hisDrug.pack_retprice !== '' ? Number(hisDrug.pack_retprice) : 0;
if (pack_retprice === 0 || !Number.isInteger(pack_retprice * 100)) {
return { success: false, messsage: `药品【${med.drugName}】价格无效(${pack_retprice})` };
}
const totalPrice = new BigNumber(pack_retprice).multipliedBy(quantity).toNumber();
drugs.push({
...med,
hisChargeInfo: {
drugGroupNo: hisDrug.group_no,
drugId: hisDrug.charge_code,
drugSerial: hisDrug.serial,
drugPrice: hisDrug.pack_retprice,
drugSumamt: totalPrice
}
})
}
return { success: true, drugs };
} catch (e) {
return { success: false, message: `获取his药品信息错误: ${e.message}` }
}
}
async function getWinesWithHisChargeInfo(data) {
if (!Array.isArray(data) || data.length === 0) {
return { success: false, message: "浸酒信息错误" };
}
const wineIds = data.map(i => new ObjectId(i._id));
const docs = await db.collection('chinese-medicine').find({ _id: { $in: wineIds } }).toArray();
const result = [];
for (let i of data) {
const wine = docs.find(item => i._id === item._id.toString());
if (!wine) {
return { success: false, message: `未查询到浸酒【${i.name}】信息` };
}
const quantity = Number.isInteger(i.quantity) && i.quantity > 0 ? i.quantity : 0;
if (quantity === 0) {
return { success: false, message: `浸酒【${i.name}】数量错误` };
}
result.push({
_id: wine._id.toString(),
name: wine.name,
details: wine.details,
efficacy: wine.efficacy,
hisId: wine.hisId,
unit: wine.unit,
quantity: i.quantity,
})
}
return { success: true, message: '获取浸酒价格信息成功', wines: result }
}
async function getRxMedicineOrderStatus(ctx, db) {
try {
const id = typeof ctx.id === 'string' && ctx.id.trim() !== '' ? ctx.id.trim() : '';
const accountId = typeof ctx.accountId === 'string' && ctx.accountId.trim() !== '' ? ctx.accountId.trim() : '';
if (!id || !accountId) {
return { success: false, message: "处方id或账号id不能为空" };
}
const rx = await db.collection('diagnostic-record').findOne({ _id: new ObjectId(id), accountId, prescriptionType: 'onlineMedicinePurchase' }, { projection: { expireTime: 1 } });
if (!rx) {
return { success: false, message: "处方不存在" };
}
const expired = Date.now() > rx.expireTime;
const order = await db.collection('medicine-purchase-order').findOne({ rpNo: id, accountId }, { projection: { status: 1 } });
return { success: true, message: "查询成功", data: { id: rx._id, expired, orderStatus: order ? order.status : 'none' } };
} catch (e) {
return { success: false, message: `获取账号购药处方记录失败: ${e.message}` }
}
}
async function getYbReviewResult(ctx) {
let { params = {} } = ctx;
try {
const drugs = Array.isArray(params.drugs) ? params.drugs : [];
const insuranceCodes = drugs.map(i => i.insurance_code).filter(Boolean);
if (insuranceCodes.length === 0) {
return { success: false, message: "药品列表不能为空" };
}
const { data: hisDrugs } = await zytHis({ type: 'getHisDrugInfo', insuranceCodes, ignoreAreaCode: true });
const hisDrugList = Array.isArray(hisDrugs) ? hisDrugs : [];
const validDrugs = []
for (let i of params.drugs) {
const hisDrug = hisDrugList.find(j => i.insurance_code && i.insurance_code === j.gjbm);
if (!hisDrug) {
continue;
}
validDrugs.push({
...i,
hisChargeInfo: {
drugGroupNo: hisDrug.group_no,
drugId: hisDrug.charge_code,
drugSerial: hisDrug.serial,
drugPrice: hisDrug.pack_retprice,
drugSumamt: new BigNumber(hisDrug.pack_retprice).multipliedBy(i.quantity).toNumber()
}
})
}
if (validDrugs.length === 0) {
return { success: true, message: '未能有效查询: 药品信息未找到 ', advices: [] }
}
params.drugs = validDrugs;
const payload = formatReviewData(params)
const { success, advices, message } = await zytHis({
type: 'ybReviewPrescription',
data: payload
})
return { success, message, advices }
} catch (e) {
return { success: false, message: `获取处方审核结果失败: ${e.message}` }
}
}
async function runOnlineRxExpireSchedule(db) {
if (scheduleTaskIsRunning) return;
scheduleTaskIsRunning = true;
try {
const rxList = await db.collection('diagnostic-record').find(
{
$or: [
{ // 在线购药处方过期
prescriptionType: 'onlineMedicinePurchase',// { $in: ['onlineMedicinePurchase', 'medicalWinePurchase'] },
status: 'PASS',
expireTime: { $lt: Date.now() },
medOrgOrderNo: { $exists: true },
hisChargeStatus: { $exists: false },
createTime: { $gt: dayjs().startOf('day').valueOf() }
},
{ // 快递的浸酒处方过期
prescriptionType: 'medicalWinePurchase',
status: 'PASS',
pickUpType: 'delivery',
expireTime: { $lt: Date.now() },
medOrgOrderNo: { $exists: true },
hisChargeStatus: { $exists: false },
createTime: { $gt: dayjs().startOf('day').valueOf() }
},
]
},
{ projection: { _id: 1, medOrgOrderNo: 1, patientId: 1 } }
).toArray();
for (let rx of rxList) {
const { data } = await zytHis({ type: 'getHisMedicinePurchase', patientId: rx.patientId, orderNo: rx.medOrgOrderNo });
if (data && data.pay_mark === '5') {
const { success } = await zytHis({ type: 'cancelMedicinePurchase', patientId: rx.patientId, orderNo: rx.medOrgOrderNo });
if (success) {
await db.collection('diagnostic-record').updateOne({ _id: rx._id }, { $set: { hisChargeStatus: 'x' } });
}
} else if (data && data.pay_mark) {
await db.collection('diagnostic-record').updateOne({ _id: rx._id }, { $set: { hisChargeStatus: data.pay_mark } });
}
}
} catch (e) {
console.log(`[处方过期定时任务]: 执行失败: ${e?.message}`)
return { success: false, message: `执行定时任务出现错误: ${e.message}` }
}
scheduleTaskIsRunning = false;
}
async function getPatientHomeRxCount(ctx) {
try {
const accountId = typeof ctx.accountId === 'string' && ctx.accountId.trim() !== '' ? ctx.accountId.trim() : '';
if (!accountId) {
return { success: false, message: "账号id不能为空" };
}
// 使用聚合查询实现待支付处方数量统计
const result = await db.collection("diagnostic-record").aggregate([
{
// 第一步:匹配符合条件的处方
$match: {
accountId: accountId,
status: status.pass,
prescriptionType: "onlineMedicinePurchase",
expireTime: { $gt: Date.now() }
}
},
{
// 第二步:联表查询对应的购药订单
$lookup: {
from: "medicine-purchase-order",
let: {
rpNo: { $toString: "$_id" },
accountId: "$accountId"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ["$disabled", false] },
{ $eq: ["$rpNo", "$$rpNo"] },
{ $eq: ["$accountId", "$$accountId"] }
]
}
}
},
{
$project: {
_id: 1,
status: 1,
disabled: 1
}
}
],
as: "purchaseOrder"
}
},
{
// 第三步筛选待支付处方购药订单不存在或status为unpay
$match: {
$or: [
{ purchaseOrder: { $size: 0 } }, // 购药订单不存在
{
$expr: {
$eq: [{ $arrayElemAt: ["$purchaseOrder.status", 0] }, "unpay"]
}
} // 购药订单状态为unpay取数组第一个元素的status
]
}
},
{
// 第四步:统计数量
$count: "count"
}
]).toArray();
const unpay = result.length > 0 && result[0].count ? result[0].count : 0;
const unpayDeliveryFee = await db.collection('medicine-purchase-order').countDocuments({ accountId, shippingFee: { $gt: 0 }, status: 'ybPaid' });
return { success: true, message: "查询成功", data: { unpay, unpayDeliveryFee } };
} catch (e) {
return { success: false, message: `获取患者首页处方数量失败: ${e.message}` }
}
}
async function getReUploadRxList(ctx) {
try {
const pharmacistNo = typeof ctx.pharmacistNo === 'string' && ctx.pharmacistNo.trim() !== '' ? ctx.pharmacistNo.trim() : '';
if (!pharmacistNo) {
return { success: false, message: "药师编号不能为空" };
}
const query = {
prescriptionType: 'storeMedicinePurchase',
pharmacistNo,
needReUpload: true,
// createTime: {
// $gt: dayjs().startOf('day').valueOf()
// }
}
const list = await db.collection('diagnostic-record').find(query, { projection: { _id: 1, auditTime: 1, name: 1 } }).toArray();
const total = await db.collection('diagnostic-record').countDocuments(query);
return { success: true, message: "查询成功", data: list.map(i => decryptDiagnosticRecordFields(i)), total };
} catch (e) {
return { success: false, message: `获取需要重新上传的处方列表失败: ${e.message}` }
}
}
async function handleReUploadRx(ctx) {
try {
const pharmacistNo = typeof ctx.pharmacistNo === 'string' && ctx.pharmacistNo.trim() !== '' ? ctx.pharmacistNo.trim() : '';
const ids = Array.isArray(ctx.ids) ? ctx.ids.filter(i => typeof i == 'string' && ObjectId.isValid(i)) : [];
if (!pharmacistNo || ids.length === 0) {
return { success: false, message: "药师编号或处方id不能为空" };
}
const { matchedCount } = await db.collection('diagnostic-record').updateMany({ _id: { $in: ids.map(i => new ObjectId(i)) }, prescriptionType: 'storeMedicinePurchase', pharmacistNo, needReUpload: true }, { $set: { needReUpload: false } });
if (matchedCount) {
return { success: true, message: "操作成功" };
}
return { success: false, message: "操作失败" };
} catch (e) {
return { success: true, message: e.message }
}
}
async function getPatientWineBuyCount(ctx, db) {
try {
const wineId = typeof ctx.wineId === 'string' && ctx.wineId.trim() !== '' ? ctx.wineId.trim() : '';
const patientId = typeof ctx.patientId === 'string' && ctx.patientId.trim() !== '' ? ctx.patientId.trim() : '';
if (!wineId || !patientId) {
return { success: false, message: "酒类id或患者id号不能为空" };
}
const query = {
prescriptionType: 'medicalWinePurchase',
"wines._id": wineId,
patientId,
}
const count = await db.collection('diagnostic-record').countDocuments(query);
return { success: true, message: "查询成功", data: count };
} catch (e) {
return { success: false, message: `查询患者购买酒类次数失败: ${e.message}` }
}
}