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

2340 lines
80 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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

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