const common = require("../../common"); const zytHis = require("../zyt-his"); const dayjs = require("dayjs"); const { getConfig } = require("../utils/config"); const tencentIM = require("../tencent-im"); const trigger = require("./trigger"); const { ObjectId } = require("mongodb"); const timeApi = require("../hlw-time-duration"); const { encryptOrderFields, decryptOrderFields, decryptOrderList } = require("./format"); const hisPayStatus = { 0: "已支付", 1: "已退费", 5: "未支付", x: "已作废", }; const refundStatus = { INIT: "未处理", PASS: "已通过", REJECT: "已拒绝", }; const RefundOrderScene = { DOCTORAGREEREFUND: "患者已退费", OFFLINEREFUND: "患者线下已退费", }; // 咨询订单退费场景 const ConsultTypeByFeeType = { YB: "onlineConsult", ZF: "onlineConsult", }; let db = ""; module.exports = async (item, mongodb) => { db = mongodb; switch (item.type) { case "addConsultOrder": return await addConsultOrder(item); case "addDrugStoreConsultOrder": return await addDrugStoreConsultOrder(item); case "getPatientOrder": return await getPatientOrder(item); case "getPatientOrderList": return await getPatientOrderList(item); case "getDrugStoreOrderList": return await getDrugStoreOrderList(item); case "deleteConsultOrder": return await deleteConsultOrder(item); case "updateConsultOrder": return await updateConsultOrder(item); case "getConsultOrder": return await getConsultOrder(item); case "updateConsultOrderStatus": return await updateConsultOrderStatus(item); case "refundConsultOrder": return await refundConsultOrder(item); case "acceptConsultOrder": return await acceptConsultOrder(item); case "completeConsultOrder": return await completeConsultOrder(item); case "finishConsultOrder": return await finishConsultOrder(item); case "startConsultOrder": return await startConsultOrder(item); case "refreshOrderPayStatus": return await refreshOrderPayStatus(item); case "cancelConsultOrder": return await cancelConsultOrder(item); case "doctorHasPendingOrder": return await doctorHasPendingOrder(item); case "refundFeeAndOrder": return await refundFeeAndOrder(item); case "serviceFinishConsultOrder": return await serviceFinishConsultOrder(item); case "getHisStoreRegList": return await getHisStoreRegList(item); case "validHlwOrderConfig": return await validHlwOrderConfig(item); case "customerRefundOrder": return await customerRefundOrder(item); case "getOrderPatientList": return await getOrderPatientList(item); case "getHlwOrderList": return await getHlwOrderList(item); case "applyRefundOrder": return await applyRefundOrder(item); case "getRefundOrderList": return await getRefundOrderList(item); case "handleRefundOrder": return await handleRefundOrder(item); case "autoHandleExpireOrder": return await autoHandleExpireOrder(item); default: return { success: false, message: "请求失败!", }; } }; let scheduleTaskIsRunning = false; // 咨询订单库 数据库是 consult-order async function addConsultOrder(item) { let { params, corpId } = item; if (!['YB', 'ZF'].includes(params.feeType)) { return { success: false, message: "费用类型不支持" }; } params.feeType = params.feeType; params.orderId = common.generateUniqueStr('WZ'); params.createTime = Date.now(); params.orderStatus = "pending"; params.payStatus = "success"; params.corpId = corpId; params.orderSource = "ALIPAY_MINI"; // 支付宝小程序 params.doctorCode = params.doctorCode.trim(); return await addOnlineConsultOrder(params); } async function addOnlineConsultOrder(params) { try { params.registerId = common.generateUniqueStr('GH'); const res1 = await getConfig(params.corpId); if (!res1) { return { success: false, message: "未查询到配置信息" }; } const { autoAcceptOrder, consultationDuration } = res1 || {}; if (typeof autoAcceptOrder !== 'boolean' || !(Number.isInteger(consultationDuration) && consultationDuration > 0)) { return { success: false, message: "咨询配置错误" }; } if (autoAcceptOrder) { params.orderStatus = "processing"; params.expireTime = dayjs().add(consultationDuration, "minute").valueOf(); } params.drugStoreId = 'HN000001'; if (!params.drugStoreId) { return { success: false, message: "药房信息缺失" }; } const storeApi = require("../drug-store"); const { success, list, message } = await storeApi( { type: "getDrugStoreList", storeId: typeof params.drugStoreId === "string" ? params.drugStoreId : "", pageSize: 1, }, db ); if (!success) { return { success, message }; } const store = Array.isArray(list) ? list[0] : null; const chargeItem = store && Array.isArray(store.chargeItems) ? store.chargeItems[0] : null; if (!store) { return { success: false, message: "为查询到药房信息" }; } if (!chargeItem || !chargeItem.code) { return { success: false, message: "当前药房未配置互联网诊查费" }; } params.chargeCode = chargeItem.code; params.chargeFee = chargeItem.fee; params.drugStoreName = store.name; params.drugStoreNo = store.login_no; const doctorCode = params.doctorCode.trim(); // 指定医生 if (doctorCode) { const doctor = await db.collection("hlw-doctor").findOne( { doctorNo: doctorCode, job: "doctor" }, { projection: { doctorNo: 1, doctorName: 1, title: 1, deptName: 1, deptCode: 1, onlineStatus: 1, }, } ); if (!doctor) { return { success: false, message: "未查询到医生" }; } if (doctor.onlineStatus !== "online") { return { success: false, message: "医生未在线, 请重新选择医生" }; } params.doctorName = doctor.doctorName || ""; params.doctorTitle = doctor.title || ""; params.deptName = doctor.deptName || ""; params.unitCode = doctor.deptCode || ""; params.doctorCode = doctor.doctorNo; } else { // 随机选取一位医生 (单量少的权重大) const doctorApi = require("../hlw-doctor"); const data = await doctorApi({ type: "getOptimalRecommendDoctor", doctorType: 'west' }, db); if (data.success && data.data) { params.doctorName = data.data.doctorName || ""; params.doctorCode = data.data.doctorNo; params.doctorTitle = data.data.title || ""; params.deptName = data.data.deptName || ""; params.unitCode = data.data.deptCode || ""; } else { return { success: false, message: data.message }; } } params.medorg_order_no = common.generateUniqueStr('HLW', 12); // 加密敏感字段 const encryptedParams = encryptOrderFields(params); const { insertedId } = await db .collection("consult-order") .insertOne(encryptedParams); if (insertedId) { return { success: true, message: "新增成功", data: { orderId: params.orderId, registerId: params.registerId, medorg_order_no: params.medorg_order_no, doctorCode: params.doctorCode, doctorName: params.doctorName, doctorTitle: params.doctorTitle, deptName: params.deptName, deptCode: params.unitCode, }, } } return { success: false, message: "新增失败", }; } catch (e) { return { success: false, message: `新增在线复诊订单失败: ${e.message}` } } } async function addOnlineMedicinePurchaseOrder(params) { try { // 线上购药订单 先咨询 后连同药费一起收取 params.drugStoreId = undefined; params.payStatus = "success"; params.medorg_order_no = common.generateUniqueStr('HLW', 12); if (typeof params.doctorCode === "string" && params.doctorCode.trim() !== "") { const doctor = await db.collection("hlw-doctor").findOne( { doctorNo: params.doctorCode.trim(), job: "doctor" }, { projection: { doctorNo: 1, doctorName: 1, title: 1, deptName: 1, deptCode: 1, onlineStatus: 1, }, } ); if (!doctor) { return { success: false, message: "未查询到医生" }; } if (doctor.onlineStatus !== "online") { return { success: false, message: "医生未在线, 请重新选择医生" }; } params.doctorName = doctor.doctorName || ""; params.doctorTitle = doctor.title || ""; params.deptName = doctor.deptName || ""; params.unitCode = doctor.deptCode || ""; params.doctorCode = doctor.doctorNo; } else { // 随机选取一位医生 (单量少的权重大) const doctorApi = require("../hlw-doctor"); const data = await doctorApi({ type: "getOptimalRecommendDoctor", doctorType: 'west' }, db); if (data.success && data.data) { params.doctorName = data.data.doctorName || ""; params.doctorCode = data.data.doctorNo; params.doctorTitle = data.data.title || ""; params.deptName = data.data.deptName || ""; params.unitCode = data.data.deptCode || ""; } else { return { success: false, message: data.message }; } } const encryptedParams = encryptOrderFields(params); const { insertedId } = await db .collection("consult-order") .insertOne(encryptedParams); return { success: true, message: "新增线上购药订单成功", data: { orderId: params.orderId, doctorCode: params.doctorCode, doctorName: params.doctorName, doctorTitle: params.doctorTitle, deptName: params.deptName, deptCode: params.unitCode, }, }; } catch (e) { return { success: false, message: `新增线上购药订单失败: ${e.message}` } } } async function addDrugStoreConsultOrder(ctx) { const { params } = ctx; const { registerId, consultType = 'onlineConsult' } = params || {}; if (!registerId) { return { success: false, message: "参数错误", }; } if (!['onlineConsult', 'wineConsult'].includes(consultType)) { return { success: false, message: '咨询类型错误' } } try { const total = await db.collection("consult-order").countDocuments({ registerId, }); if (total > 0) { return { success: false, message: "当前挂号已存在订单", }; } const { status, settlement } = await zytHis({ type: "getPayStatus", patientId: params.patientId, registerId, medorgOrderNo: registerId, }); if (status !== "0") { return { success: false, message: hisPayStatus[status] ? `当前挂号${hisPayStatus[status]}` : "查询当前挂号支付状态失败", }; } const orderId = common.generateUniqueStr('WZ'); params.settlement = settlement; params.createTime = Date.now(); params.orderId = orderId; params.orderStatus = "pending"; params.payStatus = "success"; params.medorg_order_no = registerId; params.orderSource = "MATEPAD"; // 门店pad params.consultType = consultType; if (ctx.corpId) { params.corpId = ctx.corpId; } const doctor = await db.collection("hlw-doctor").findOne( { doctorNo: typeof params.doctorCode === "string" ? params.doctorCode : "", job: "doctor", }, { projection: { _id: 0, onlineStatus: 1, offlineTime: 1, doctorName: 1, title: 1, deptName: 1, deptCode: 1 } } ); if (!doctor) { return { success: false, message: "未查询到挂号医生" }; } if (doctor.onlineStatus !== "online") { const offlineTime = typeof doctor.offlineTime === 'number' ? doctor.offlineTime : 0; const tenMinutesLater = offlineTime + 10 * 60 * 1000; if (!offlineTime || Date.now() > tenMinutesLater) { return { success: false, message: "医生已下线。请联系门店工作人员退号,如需继续就诊请重新挂号。" }; } } if (params.consultType === 'wineConsult') { const wineUtil = require('./wine-consult'); params.wines = await wineUtil.getConsultWines(params.wines, db); } // 加密敏感字段 const encryptedParams = encryptOrderFields(params); const { insertedId } = await db .collection("consult-order") .insertOne(encryptedParams); return { success: true, message: "新增成功", data: { orderId, registerId: params.registerId, insertedId, medorg_order_no: params.registerId, }, }; } catch (e) { return { success: false, message: e.message || "新增失败", }; } } async function cancelConsultOrder(item) { const { orderId, corpId } = item; if ( typeof orderId !== "string" || orderId.trim() === "" || typeof corpId !== "string" || corpId.trim() === "" ) { return { success: false, message: "参数错误" }; } try { const order = await db .collection("consult-order") .findOne( { orderId, corpId }, { projection: { patientId: 1, payStatus: 1, registerId: 1 } } ); if (!order) { return { success: false, message: "订单不存在" }; } if (order.payStatus !== "pending") { return { success: false, message: "当前订单不可取消" }; } const { patientId, registerId } = order; const res1 = await zytHis({ type: "getPayStatus", patientId, registerId, }); if (!res1 || !res1.success) { return { success: false, message: res1.message || "查询订单支付状态失败", }; } if (res1.status === "0") { const res2 = await zytHis({ type: "hlwRefund", patientId, registerId, }); if (!res2 || !res2.success) { return { success: false, message: res2.message || "取消订单失败" }; } } // 获取订单 const res = await db.collection("consult-order").updateOne( { orderId, corpId }, { $set: { orderStatus: "cancelled", payStatus: "cancelled", payResult: "用户取消订单", updateTime: Date.now(), }, } ); return { success: true, message: "取消成功", data: res, }; } catch (error) { return { success: false, message: error.message || "取消失败", }; } } async function getPatientOrder(item) { const { orderId } = item; if (!orderId) { return { success: false, message: "参数错误", }; } try { const [data] = await db .collection("consult-order") .aggregate([ { $match: { orderId: orderId } }, { $lookup: { from: "diagnostic-record", // 连接到 diagnostic-record 集合 localField: "orderId", // consult-order 集合中的 orderId 字段 foreignField: "orderId", // diagnostic-record 集合中的 orderId 字段 as: "diagnostic", // 返回的联接结果存储在 diagnostic 字段中 }, }, { $addFields: { diagnostic: { $filter: { input: "$diagnostic", as: "diagnosticRecord", cond: { $eq: ["$$diagnosticRecord.status", "PASS"] }, }, }, }, }, { $addFields: { hasPassDiagnostic: { $gt: [{ $size: "$diagnostic" }, 0] }, }, }, { $project: { diagnostic: 0, // 排除 diagnostic 字段 }, }, { $limit: 1, }, ]) .toArray(); if ( data && data.payExpireTime < Date.now() && data.payStatus === "pending" ) { data.payStatus = "expired"; data.payResult = "超时未支付"; } if ( data && ["processing", "pending", "completed"].includes(data.orderStatus) && data.expireTime < Date.now() ) { data.orderStatus = "cancelled"; } // 解密敏感字段 const decryptedData = data ? decryptOrderFields(data) : data; return { success: true, data: decryptedData, message: "查询成功", }; } catch (err) { return { success: false, message: err.message || "查询失败", }; } } async function getDrugStoreOrderList(ctx) { const { storeId, name } = ctx; if (typeof storeId !== "string" || storeId.trim() === "") { return { success: false, message: "店铺id不能为空" }; } const page = parseInt(ctx.page) > 0 ? parseInt(ctx.page) : 1; const pageSize = parseInt(ctx.pageSize) > 0 ? parseInt(ctx.pageSize) : 20; const date = ctx.date && dayjs(ctx.date).isValid() ? dayjs(ctx.date) : dayjs(); const createTime = { $gte: date.startOf("day").valueOf(), $lte: date.endOf("day").valueOf(), }; try { const query = { drugStoreNo: storeId.trim(), createTime, orderSource: "MATEPAD", }; if (typeof name == "string" && name.trim() !== "") { query.$or = [ { name: { $regex: name.trim(), $options: "i" } }, { doctorName: { $regex: name.trim(), $options: "i" } }, ]; } const list = await db .collection("consult-order") .aggregate([ { $match: query }, { $sort: { createTime: -1 } }, { $skip: (page - 1) * pageSize }, { $limit: pageSize }, { $lookup: { from: "diagnostic-record", // 连接到 diagnostic-record 集合 localField: "orderId", // consult-order 集合中的 orderId 字段 foreignField: "orderId", // diagnostic-record 集合中的 orderId 字段 as: "diagnostic", // 返回的联接结果存储在 diagnostic 字段中 }, }, { $addFields: { diagnostic: { $filter: { input: "$diagnostic", as: "diagnosticRecord", cond: { $eq: ["$$diagnosticRecord.status", "PASS"] }, }, }, }, }, { $addFields: { hasPassDiagnostic: { $gt: [{ $size: "$diagnostic" }, 0] }, }, }, ]) .toArray(); const total = await db.collection("consult-order").countDocuments(query); const todayCount = await db.collection("consult-order").countDocuments({ drugStoreNo: storeId.trim(), createTime: { $gte: dayjs().startOf("day").valueOf(), $lte: dayjs().endOf("day").valueOf(), }, orderSource: "MATEPAD", }); // 解密列表中的敏感字段 const decryptedList = decryptOrderList(list); return { success: true, list: decryptedList, total, page, pageSize, todayCount, pages: Math.ceil(total / pageSize), message: "查询成功", }; } catch (e) { return { success: false, message: e.message || "查询失败", }; } } async function acceptConsultOrder(item) { const { orderId, corpId, doctorCode } = item; try { const item = await db.collection("consult-order").findOne( { orderId }, { projection: { expireTime: 1, createTime: 1, doctorCode: 1, orderStatus: 1, doctorName: 1, }, } ); if (!item) { return { success: false, message: "订单不存在" }; } if ( dayjs().startOf("day").valueOf() > item.expireTime || dayjs().startOf("day").valueOf() > item.createTime ) { return { success: false, message: "订单已过期,请刷新" }; } if (item.orderStatus !== "pending") { return { success: false, message: "订单已失效,请刷新" }; } const { consultationDuration } = await getConfig(corpId); const expireTime = dayjs().add(consultationDuration, "minute").valueOf(); await updateConsultOrderStatus({ orderId, orderStatus: "processing", expireTime, doctorCode: item.doctorCode, corpId, }); timeApi( { type: "addDoctorOrderDuration", doctorCode: item.doctorCode, doctorName: item.doctorName, orderId, createTime: item.createTime, }, db ); // 后端自动生成并保存处方开始时间(毫秒),由服务器记录接单时间点 let serverPrescriptionStartTime = null; try { serverPrescriptionStartTime = Date.now(); await db.collection("consult-order").updateOne( { orderId }, { $set: { prescriptionStartTime: serverPrescriptionStartTime, updateTime: Date.now(), }, } ); } catch (e) { console.error( "保存 prescriptionStartTime 到 consult-order 失败", e && e.message ); // 保持 serverPrescriptionStartTime 的值(可能为 null 如果 Date.now() 未赋值),以便返回给调用者以作判断 } // 接受问诊 发送系统消息 await tencentIM({ type: "sendSystemNotification", formAccount: orderId, toAccount: doctorCode, SyncOtherMachine: 1, corpId, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "ACCEPTCONSULT", Ext: "您已接诊了患者发起的图文问诊服务,请及时回复处理。感谢您的辛勤付出!", }, }, ], }); // 删除定时任务 await trigger({ type: "deleteDelayedTask", triggerTaskId: orderId, corpId, }); // 从新建一个定时任务 await trigger({ type: "createDelayedTask", triggerTaskId: orderId, endTime: expireTime, corpId, }); return { success: true, message: "接诊成功", expireTime, serverPrescriptionStartTime, }; } catch (err) { return { success: false, message: "接诊失败", }; } } // 结束问诊 async function finishConsultOrder(item) { // 判断是否有正在审核的单子 const count = await db.collection("diagnostic-record").countDocuments({ orderId: item.orderId, status: "INIT", }); if (count > 0) { return { success: false, message: "存在正在审核的诊断单,不能结束咨询", }; } return await serviceFinishConsultOrder(item); } async function serviceFinishConsultOrder(item) { let { orderId, doctorCode, corpId } = item; try { // 获取订单 if (!doctorCode || !corpId) { const order = await db.collection("consult-order").findOne({ orderId }); doctorCode = order.doctorCode; corpId = order.corpId; if ( order.orderStatus === "finished" || order.orderStatus === "cancelled" ) { return { success: false, message: "订单已结束", }; } } // 更新订单状态 await closeConsultOrder({ orderId, corpId, doctorCode }); await setDiagnosticExpired({ orderId }); return { success: true, message: "完成成功", }; } catch (error) { return { success: false, message: "完成失败", }; } } async function closeConsultOrder({ orderId, doctorCode, corpId }) { // 删除定时任务 await trigger({ type: "deleteDelayedTask", triggerTaskId: orderId, }); await tencentIM({ type: "sendSystemNotification", formAccount: doctorCode, toAccount: orderId, SyncOtherMachine: 1, corpId, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "FINISHED", Ext: "本次问诊已结束,不能继续发消息。", }, }, ], }); await updateConsultOrderStatus({ orderId, orderStatus: "finished", doctorCode, corpId, }); } // 完成订单 async function completeConsultOrder(item) { let { orderId, doctorCode, sendText, corpId } = item; try { // 获取订单 if (doctorCode) { const order = await db.collection("consult-order").findOne({ orderId }); doctorCode = order.doctorCode; } // 更新订单状态 await updateConsultOrderStatus({ orderId, orderStatus: "completed", }); // 删除定时任务 await trigger({ type: "deleteDelayedTask", triggerTaskId: orderId, }); // 发送系统消息 tencentIM({ type: "sendSystemNotification", formAccount: doctorCode, toAccount: orderId, corpId, SyncOtherMachine: 1, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "COMPLETED", Desc: sendText, }, }, ], }); return { success: true, message: "完成成功", }; } catch (error) { return { success: false, message: "完成失败", }; } } // 删除咨询订单 async function deleteConsultOrder(item) { const { orderId } = item; try { // 调用mongo 数据库删除 const res = await db.collection("consult-order").deleteOne({ orderId, }); return { success: true, message: "删除成功", data: res, }; } catch (err) { return { success: false, message: "删除失败", }; } } // 更新咨询订单 async function updateConsultOrder(item) { const { orderId, params } = item; try { // 加密敏感字段 const encryptedParams = encryptOrderFields(params); // 调用mongo 数据库更新 const res = await db.collection("consult-order").updateOne( { orderId }, { $set: { ...encryptedParams, updateTime: Date.now(), }, } ); return { success: true, message: "更新成功", data: res, }; } catch (err) { return { success: false, message: "更新失败", }; } } // 获取咨询订单 分页查询 page 页码 pageSize 每页数量 数据库分页 async function getConsultOrder(item) { const { page, pageSize, orderId, hospitalId, patientId, idCard, orderStatus, mergeStatus, doctorCode, corpId, showPassdiagnostic = false, hasPassDiagnostic, drugStoreId, orderSource, accountId, } = item; const query = {}; if (orderId) query.orderId = orderId; if (hospitalId) query.hospitalId = hospitalId; if (patientId) query.patientId = patientId; if (idCard) query.idCard = idCard; // if (corpId) query.corpId = corpId; if (doctorCode) query.doctorCode = doctorCode; if (orderStatus) query.orderStatus = orderStatus; if (drugStoreId) query.drugStoreId = drugStoreId; if (orderSource) query.orderSource = orderSource; if (typeof accountId === 'string' && accountId.trim()) query.accountId = accountId.trim(); if (mergeStatus === "需处理") { query.orderStatus = { $in: ["pending", "processing", "completed"], }; } // 已完成 包括已完成和已取消 两种状态 或者 过期时间小于当前时间 注意 是或的关系 使用 or if (mergeStatus === "已处理") { query.orderStatus = { $in: ["cancelled", "finished"], }; } try { let res, total; // 优化:分离查询,避免使用 $lookup 聚合操作 if (showPassdiagnostic) { // 方案1:如果需要根据 hasPassDiagnostic 过滤,先查询诊断记录获取相关的 orderId if (typeof hasPassDiagnostic === "boolean") { // 先查询所有通过审核的诊断记录的 orderId const passedDiagnosticOrderIds = await db .collection("diagnostic-record") .distinct("orderId", { status: "PASS" }); // 根据 hasPassDiagnostic 条件调整查询 if (hasPassDiagnostic) { // 只查询有通过诊断的订单 if (query.orderId) { // 如果已经指定了orderId,检查它是否在通过的列表中 if (!passedDiagnosticOrderIds.includes(query.orderId)) { query.orderId = null; // 不在列表中,设为null表示无结果 } } else { // 没有指定orderId,查询所有通过的订单 if (passedDiagnosticOrderIds.length > 0) { query.orderId = { $in: passedDiagnosticOrderIds }; } else { // 如果没有通过的诊断记录,返回空结果 query.orderId = null; } } } else { // 只查询没有通过诊断的订单 if (query.orderId) { // 如果已经指定了orderId,检查它是否不在通过的列表中 if (passedDiagnosticOrderIds.includes(query.orderId)) { query.orderId = null; // 在列表中,设为null表示无结果 } } else { // 没有指定orderId,排除所有通过的订单 if (passedDiagnosticOrderIds.length > 0) { query.orderId = { $nin: passedDiagnosticOrderIds }; } // 如果没有通过的诊断记录,则查询所有订单(不需要额外条件) } } // 如果查询条件导致没有结果,直接返回 if ( query.orderId === null || (Array.isArray(query.orderId?.$in) && query.orderId.$in.length === 0) ) { return { success: true, message: "查询成功", data: [], total: 0, pages: 0, }; } } // const { patientId: _patientId, ...restQuery } = query; // const allQuery = // typeof accountId == "string" // ? { $or: [{ ...restQuery, accountId }, query] } // : query; // console.log("allQuery case!!!!: ", allQuery); const allQuery = query; // 先查询订单列表 res = await db .collection("consult-order") .find(allQuery) .sort({ createTime: -1 }) .skip((page - 1) * pageSize) .limit(pageSize) .toArray(); // 获取总数 total = await db.collection("consult-order").countDocuments(allQuery); // 如果有订单结果,批量查询诊断记录 if (res.length > 0) { const orderIds = res.map((order) => order.orderId); // 批量查询这些订单的通过审核的诊断记录 const diagnosticRecords = await db .collection("diagnostic-record") .find( { orderId: { $in: orderIds }, status: "PASS", }, { projection: { orderId: 1, _id: 0 } } ) .toArray(); // 创建 orderId 到 hasPassDiagnostic 的映射 const diagnosticMap = new Set( diagnosticRecords.map((record) => record.orderId) ); // 为每个订单添加 hasPassDiagnostic 字段 res = res.map((order) => ({ ...order, hasPassDiagnostic: diagnosticMap.has(order.orderId), })); } } else { // 如果不需要诊断信息,直接查询订单 if (typeof hasPassDiagnostic === "boolean") { // 仍然需要根据诊断状态过滤 const passedDiagnosticOrderIds = await db .collection("diagnostic-record") .distinct("orderId", { status: "PASS" }); if (hasPassDiagnostic) { // 只查询有通过诊断的订单 if (query.orderId) { // 如果已经指定了orderId,检查它是否在通过的列表中 if (!passedDiagnosticOrderIds.includes(query.orderId)) { query.orderId = null; // 不在列表中,设为null表示无结果 } } else { // 没有指定orderId,查询所有通过的订单 if (passedDiagnosticOrderIds.length > 0) { query.orderId = { $in: passedDiagnosticOrderIds }; } else { // 如果没有通过的诊断记录,返回空结果 query.orderId = null; } } } else { // 只查询没有通过诊断的订单 if (query.orderId) { // 如果已经指定了orderId,检查它是否不在通过的列表中 if (passedDiagnosticOrderIds.includes(query.orderId)) { query.orderId = null; // 在列表中,设为null表示无结果 } } else { // 没有指定orderId,排除所有通过的订单 if (passedDiagnosticOrderIds.length > 0) { query.orderId = { $nin: passedDiagnosticOrderIds }; } // 如果没有通过的诊断记录,则查询所有订单(不需要额外条件) } } if ( query.orderId === null || (Array.isArray(query.orderId?.$in) && query.orderId.$in.length === 0) ) { return { success: true, message: "查询成功", data: [], total: 0, pages: 0, }; } } // const { patientId: _patientId, ...restQuery } = query; // const allQuery = // typeof accountId == "string" // ? { $or: [{ ...restQuery, accountId }, query] } // : query; // console.log("allQuery case2: ", allQuery); const allQuery = query; res = await db .collection("consult-order") .find(allQuery) .sort({ createTime: -1 }) .skip((page - 1) * pageSize) .limit(pageSize) .toArray(); total = await db.collection("consult-order").countDocuments(allQuery); } // 处理订单状态 const array = res.map((item) => { if (item.payExpireTime < Date.now() && item.payStatus === "pending") { item.payStatus = "expired"; item.payResult = "超时未支付"; } if ( ["processing", "pending", "completed"].includes(item.orderStatus) && item.expireTime < Date.now() ) { item.orderStatus = "cancelled"; } return item; }); // 解密列表中的敏感字段 const decryptedArray = decryptOrderList(array); return { success: true, message: "查询成功", data: decryptedArray, total, pages: Math.ceil(total / pageSize), }; } catch (err) { return { success: false, message: err.message || "查询失败", }; } } // 修改问诊状态 async function updateConsultOrderStatus(item) { const { orderId, orderStatus, payStatus, expireTime, doctorCode, corpId, reason, } = item; try { let query = {}; if (orderStatus) query.orderStatus = orderStatus; if (payStatus) query.payStatus = payStatus; if (expireTime) query.expireTime = expireTime; if (typeof reason === "string") query.reason = reason; // 当医生开始处理, 开始加过期时间, 过期时间为30分钟 const res = await db.collection("consult-order").updateOne( { orderId }, { $set: { ...query, updateTime: Date.now(), }, } ); // 删除会话 if (orderStatus === "cancelled" || orderStatus === "finished") { const res = await tencentIM({ type: "deleteSession", fromAccount: doctorCode, toAccount: orderId, corpId: corpId, }); } return { success: true, message: "更新成功", data: res, }; } catch (err) { return { success: false, message: "更新失败", }; } } // 退费并退款接口 async function refundConsultOrder(item) { // 判断是否有正在审核的单子 const count = await db.collection("diagnostic-record").countDocuments({ orderId: item.orderId, status: "INIT", }); if (count > 0) { return { success: false, message: "存在正在审核的诊断单,不能退单", }; } // 退费并退诊 return await refundFeeAndOrder(item); } // 退费并退诊 换一个方法名 async function refundFeeAndOrder(item) { let { orderId, reason, order } = item; try { // 1. 更新订单状态 if (!order) { order = await db.collection("consult-order").findOne({ orderId }); if (!order) { return { success: false, message: "订单不存在", }; } } if (["cancelled", "finished"].includes(order.orderStatus)) { return { success: false, message: "订单已取消或已完成,不能退单", }; } const { doctorCode, corpId, orderSource } = order; // 如果订单已完成,且 审核通过 if (order.orderStatus === "completed") { const count = await db.collection("diagnostic-record").countDocuments({ orderId, status: "PASS", }); if (count > 0) { return await serviceFinishConsultOrder({ orderId, doctorCode, corpId }); } } // 调用退费接口 // 2. 退费 let payStatus = "", payResult = ""; // 在线购药的咨询订单无需支付所以无需退款; pad端的咨询订单线下收费线下退 if (orderSource !== "MATEPAD" && order.consultType !== 'onlineMedicinePurchase') { const { success, message } = await zytHis({ type: "hlwRefund", patientId: order.patientId, registerId: order.registerId, medorgOrderNo: order.medorgOrderNo, }); payStatus = success ? "refunded" : "refundFailed"; payResult = success ? "退费成功" : message; } // 更新诊断单状态 await setDiagnosticExpired({ orderId }); await tencentIM({ type: "sendSystemNotification", formAccount: doctorCode, toAccount: orderId, SyncOtherMachine: 1, corpId, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "CANCELLED", Desc: "notification", Ext: reason, }, }, ], }); // 3. 更新订单状态 await updateConsultOrderStatus({ orderId, orderStatus: "cancelled", payStatus, payResult, doctorCode, corpId, reason: typeof reason == "string" ? reason : "", }); return { success: true, message: "退费成功", }; } catch (err) { return { success: false, message: "退费失败", }; } } // // 问诊开始 async function startConsultOrder(item) { const { orderId, corpId, doctorCode } = item; const { consultationDuration, acceptDuration } = await getConfig(corpId); const expireTime = dayjs().add(acceptDuration, "minute").valueOf(); try { const item = await db .collection("consult-order") .findOne({ orderId }, { projection: { expireTime: 1, orderStatus: 1 } }); if (!item) { return { success: false, message: "订单不存在" }; } if (item.orderStatus !== "pending") { return { success: false, message: "当前订单已失效,请刷新" }; } if (item.expireTime) { return { success: true, message: "订单已开始" }; } // 更新订单过期时间 await db .collection("consult-order") .updateOne({ orderId }, { $set: { expireTime } }); // 从新建一个定时任务 await trigger({ type: "createDelayedTask", triggerTaskId: orderId, endTime: expireTime, corpId, }); await tencentIM({ type: "sendSystemNotification", formAccount: orderId, toAccount: doctorCode, SyncOtherMachine: 2, corpId, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "STARTCONSULT", Ext: `问诊已开始,本次问诊可持续${consultationDuration}分钟`, }, }, ], }); // 患者向医生发送一个系统消息,告诉医生问诊已经开始 setTimeout(() => { tencentIM({ type: "sendSystemNotification", formAccount: doctorCode, toAccount: orderId, SyncOtherMachine: 2, corpId, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "START", Ext: "医生会尽快接诊,请在当前页面等待,避免错过医生的消息或视频问诊提示", }, }, ], }); }, 1000); return { success: true, message: "开始成功", expireTime, }; } catch (err) { return { success: false, message: "开始失败", }; } } async function refreshOrderPayStatus(params) { const { orderId, patientId, registerId, medorgOrderNo } = params; if (!orderId || !patientId || !registerId || !medorgOrderNo) { return { success: false, message: "参数错误", }; } try { const res = await zytHis({ type: "getPayStatus", patientId, registerId, medorgOrderNo, }); if (res && res.settlement) { await db.collection("consult-order").updateOne( { orderId, patientId, registerId, medorg_order_no: medorgOrderNo, }, { $set: { settlement: res.settlement, }, } ); } return { ...res }; } catch (e) { return { success: false, message: e.message || "刷新失败" }; } } /** * 查询医生是否存在进行中的订单 * @param {*} params * @returns */ async function doctorHasPendingOrder(params) { try { const count = await db.collection("consult-order").countDocuments({ doctorCode: params.doctorCode, orderStatus: { $in: ["pending", "processing", "completed"] }, }); return { success: true, data: count > 0, message: "查询成功" }; } catch (e) { return { success: false, message: e.message || "查询失败" }; } } // 设置处方诊断过期 async function setDiagnosticExpired(item) { const { orderId } = item; try { const res = await db .collection("diagnostic-record") .updateMany({ orderId, status: "INIT" }, { $set: { status: "EXPIRED" } }); return { success: true, message: "操作成功" }; } catch (e) { return { success: false, message: e.message || "操作失败" }; } } async function getHisStoreRegList(ctx) { const { storeId, regType } = ctx; if (typeof storeId !== "string" || storeId.trim() === "") { return { success: false, message: "药店id不能为空" }; } try { const { success, list, message } = await zytHis({ type: "getHisStoreRegList", storeId, }); if (success && list.length) { // channel为1表示浸酒号源 const regList = list.filter(i => regType === 'wine' ? i.channel == '1' : i.channel != '1'); const registerids = regList.map((i) => i.registerid); const existRegisteridData = await db .collection("consult-order") .find( { registerId: { $in: registerids } }, { projection: { _id: 0, registerId: 1 } } ) .toArray(); const existRegisterids = existRegisteridData.map((i) => i.registerId); const data = regList.filter((i) => !existRegisterids.includes(i.registerid)); return { success, list: data, message }; } if (success) { return { success, list, message }; } return { success, message }; } catch (e) { return { success: false, message: e.message }; } } async function validHlwOrderConfig(ctx) { try { const { key, corpId } = ctx; if (typeof key !== "string" || key.trim() === "") { return { success: false, message: "获取失败" }; } const res = await getConfig(corpId); const data = res[key]; if (data) { return { success: true, message: "获取成功", data }; } return { success: false, message: "获取失败" }; } catch (e) { return { success: false, message: e.message }; } } /** * 用户退费导致 取消订单 * @param {*} item * @returns */ async function customerRefundOrder(item) { const { registerId, patientId, refundType = "OFFLINEREFUND" } = item; if ( typeof registerId !== "string" || registerId.trim() === "" || typeof patientId !== "string" || patientId.trim() === "" ) { return { success: false, message: "参数错误", }; } const msg = RefundOrderScene[refundType] || RefundOrderScene.OFFLINEREFUND; try { // 获取订单 const record = await db.collection("consult-order").findOne( { registerId, patientId }, { projection: { _id: 1, doctorCode: 1, orderId: 1, corpId: 1, orderStatus: 1, }, } ); if (!record) return { success: false, message: "订单不存在" }; if (["finished"].includes(record.orderStatus)) { return { success: true, message: "订单已结束,无法取消", orderId: typeof record.orderId === "string" ? record.orderId : "", }; } if (record.orderStatus === "cancelled") { return { success: true, message: "订单已取消", orderId: typeof record.orderId === "string" ? record.orderId : "", }; } const res = await db.collection("consult-order").updateOne( { _id: record._id }, { $set: { orderStatus: "cancelled", payStatus: "cancelled", payResult: "患者已退费", reason: "患者已退费", updateTime: Date.now(), }, } ); if (["processing", "pending", "completed"].includes(record.orderStatus)) { await tencentIM({ type: "sendSystemNotification", formAccount: record.orderId, toAccount: record.doctorCode, SyncOtherMachine: 1, corpId: record.corpId, msgBody: [ { MsgType: "TIMCustomElem", MsgContent: { Data: "CANCELLED", Desc: "notification", Ext: `本次问诊已取消,取消原因:${msg}。`, }, }, ], }); } return { success: true, message: "取消成功", orderId: typeof record.orderId === "string" ? record.orderId : "", }; } catch (error) { return { success: false, message: "取消失败", }; } } async function getPatientOrderList(ctx) { const { patientId, startDate, endDate, isPres, orderStatus } = ctx; if (typeof patientId !== "string" || patientId.trim() === "") { return { success: false, message: "患者id不能为空" }; } 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, payStatus: "success" }; if (typeof orderStatus === "string" && orderStatus.trim() !== "") { query.orderStatus = orderStatus.trim(); } if (typeof isPres === "boolean") { query.preOrderId = { $exists: isPres }; } if (startTime && endTime) { query.createTime = { $gte: startTime, $lte: endTime }; } const list = await db .collection("consult-order") .find(query) .sort({ createTime: -1 }) .toArray(); // 解密列表中的敏感字段 const decryptedList = decryptOrderList(list); return { success: true, message: "查询成功", list: decryptedList }; } catch (e) { return { success: false, message: e.message || "查询失败" }; } } async function getOrderPatientList(ctx) { const { doctorCode, name, mobile, patientId, corpId } = ctx; const query = {}; // 机构隔离:如果传了 corpId,则只查当前机构 if (typeof corpId === "string" && corpId.trim()) { query.corpId = corpId.trim(); } // 优先使用 patientId 精确查询基础信息 if (typeof patientId === "string" && patientId.trim()) { query.patientId = patientId.trim(); } else { // 兼容旧逻辑:按医生/姓名/手机号聚合患者列表 if (typeof doctorCode === "string" && doctorCode.trim()) { query.doctorCode = doctorCode.trim(); } if (typeof name === "string" && name.trim()) { query.name = { $regex: name.trim(), $options: "i" }; } if (typeof mobile === "string" && mobile.trim()) { query.mobile = { $regex: mobile.trim(), $options: "i" }; } } const page = parseInt(ctx.page, 10) > 0 ? parseInt(ctx.page, 10) : 1; const pageSize = parseInt(ctx.pageSize, 10) > 0 ? parseInt(ctx.pageSize, 10) : 10; try { const list = await db .collection("consult-order") .aggregate([ { $match: query }, { $group: { _id: "$patientId", blhno: { $first: "$blhno" }, name: { $first: "$name" }, sex: { $first: "$sex" }, age: { $first: "$age" }, mobile: { $first: "$mobile" }, idCard: { $first: "$idCard" }, address: { $first: "$address" }, createTime: { $first: "$createTime" }, patientId: { $first: "$patientId" }, }, }, { $sort: { createTime: -1 } }, { $skip: (page - 1) * pageSize }, { $limit: pageSize }, ]) .toArray(); const [stats] = await db .collection("consult-order") .aggregate([ { $match: query }, { $group: { _id: "$patientId", }, }, { $count: "total" }, ]) .toArray(); const total = stats ? stats.total : 0; // 解密列表中的敏感字段 const decryptedList = decryptOrderList(list); // 兼容旧用法(直接返回 list/total),同时为 PC 端提供 data 包装 const pages = Math.ceil(total / pageSize); return { success: true, message: "查询成功", list: decryptedList, total, page, pageSize, pages, data: { list: decryptedList, total, page, pageSize, pages, }, }; } catch (e) { return { success: false, message: e.message || "查询失败" }; } } async function getHlwOrderList(ctx) { try { const andConditions = []; const page = parseInt(ctx.page) > 0 ? parseInt(ctx.page) : 1; const pageSize = parseInt(ctx.pageSize) > 0 ? parseInt(ctx.pageSize) : 10; const escapeRegExp = (str) => String(str).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // 姓名筛选:兼容加密存储(精确匹配密文)+ 旧数据明文模糊匹配 if (typeof ctx.name === "string" && ctx.name.trim() !== "") { const keyword = ctx.name.trim(); let encryptedKeyword = ""; try { encryptedKeyword = encryptOrderFields({ name: keyword }).name; } catch (e) { // ignore: fallback to plaintext match } const orList = []; if (encryptedKeyword) { orList.push({ name: encryptedKeyword }); } orList.push({ name: { $regex: `.*${escapeRegExp(keyword)}.*`, $options: "i" } }); andConditions.push({ $or: orList }); } if (typeof ctx.consultType === "string" && ctx.consultType.trim() !== "") { andConditions.push({ consultType: ctx.consultType.trim() }); } if (typeof ctx.orderSource === "string" && ctx.orderSource.trim() !== "") { andConditions.push({ orderSource: ctx.orderSource }); } const orderStatus = typeof ctx.orderStatus === "string" ? ctx.orderStatus.trim() : ""; if (orderStatus) { // 修复:待处理(pending)不应包含“支付超时(前端展示为已取消)”订单 if (orderStatus === "pending") { const now = Date.now(); andConditions.push({ orderStatus: "pending" }); andConditions.push({ $or: [ { payStatus: { $ne: "pending" } }, { payExpireTime: { $gte: now } }, { payExpireTime: { $exists: false } }, ], }); } else { andConditions.push({ orderStatus }); } } if (Array.isArray(ctx.doctorCodes) && ctx.doctorCodes.length) { andConditions.push({ doctorCode: { $in: ctx.doctorCodes } }); } if (typeof ctx.isPres === "boolean") { andConditions.push({ preOrderId: { $exists: ctx.isPres } }); } if (Array.isArray(ctx.storeIds) && ctx.storeIds.length) { andConditions.push({ drugStoreId: { $in: ctx.storeIds } }); } const { startDate, endDate } = ctx; const createTime = {}; if (startDate && dayjs(startDate).isValid()) { createTime.$gte = dayjs(startDate).startOf("day").valueOf(); } if (endDate && dayjs(endDate).isValid()) { createTime.$lte = dayjs(endDate).endOf("day").valueOf(); } if (Object.keys(createTime).length) { andConditions.push({ createTime }); } if (ctx.isDoctorView === true) { andConditions.push({ orderStatus: { $ne: "pending" }, payStatus: { $ne: "pending" }, }); } const allQuery = andConditions.length === 0 ? {} : andConditions.length === 1 ? andConditions[0] : { $and: andConditions }; const list = await db .collection("consult-order") .find(allQuery) .sort({ createTime: -1 }) .skip((page - 1) * pageSize) .limit(pageSize) .toArray(); const total = await db.collection("consult-order").countDocuments(allQuery); // 解密列表中的敏感字段 const decryptedList = decryptOrderList(list); // 聚合已成功的服务端录制数量,用于 PC 订单列表视频图标展示 let videoCountMap = {}; try { const orderIds = decryptedList.map((i) => i.orderId).filter(Boolean); if (orderIds.length) { const agg = await db .collection("mrtc-video-record") .aggregate([ { $match: { orderId: { $in: orderIds }, status: 2, // 2: 录制成功(且至少两路流,见 recordTotalStream 配置) filePath: { $exists: true, $ne: "" }, }, }, { $group: { _id: "$orderId", count: { $sum: 1 } } }, ]) .toArray(); agg.forEach((i) => { if (i && i._id) videoCountMap[i._id] = i.count || 0; }); } } catch (e) { console.warn("[MRTC] aggregate videoRecordCount failed:", e.message); } const listWithVideoCount = decryptedList.map((i) => ({ ...i, videoRecordCount: videoCountMap[i.orderId] || 0, })); return { success: true, list: listWithVideoCount, message: "查询成功", total }; } catch (e) { return { success: false, message: e.message }; } } async function applyRefundOrder(ctx) { const { id: _id, orderId, reason } = ctx; if ( typeof _id !== "string" || _id.trim() === "" || typeof orderId !== "string" || orderId.trim() === "" ) { return { success: false, message: "参数错误" }; } if (typeof reason !== "string" || reason.trim() === "") { return { success: false, message: "退款原因不能为空" }; } if (reason.trim().length > 200) { return { success: false, message: "退款原因最多输入200字" }; } try { const refundInfo = { status: "INIT", createTime: Date.now(), reason: reason.trim(), }; const res = await db .collection("consult-order") .updateOne( { _id: new ObjectId(_id), orderId, refundInfo: { $exists: false } }, { $set: { refundInfo } } ); if (res.matchedCount === 0) { return { success: false, message: "订单不存在或者已经存在申请信息" }; } if (res.modifiedCount === 1) { return { success: true, message: "申请成功", data: refundInfo }; } return { success: false, message: "申请失败" }; } catch (e) { return { success: false, message: e.message || "申请退款失败" }; } } async function getRefundOrderList(ctx) { try { const query = { refundInfo: { $exists: true }, doctorCode: typeof ctx.doctorCode === "string" ? ctx.doctorCode.trim() : "", }; if (typeof ctx.name === "string" && ctx.name.trim() != "") { query.name = { $regex: ".*" + ctx.name.trim() + ".*", $options: "i" }; } if (typeof ctx.mobile === "string" && ctx.mobile.trim() != "") { query.mobile = { $regex: ".*" + ctx.mobile.trim() + ".*", $options: "i" }; } if (typeof ctx.status === "string" && ctx.status.trim() != "") { query["refundInfo.status"] = ctx.status; } const page = parseInt(ctx.page) > 0 ? parseInt(ctx.page) : 1; const pageSize = parseInt(ctx.pageSize) > 0 ? parseInt(ctx.pageSize) : 10; const projection = { _id: 1, name: 1, doctorName: 1, mobile: 1, refundInfo: 1, orderId: 1, }; // const list = await db.collection('consult-order').find(query, { projection }).sort({ 'refundInfo.createTime': -1 }).skip((page - 1) * pageSize).limit(pageSize).toArray(); const list = await db .collection("consult-order") .aggregate([ { $match: query }, { $project: projection }, { $addFields: { initFirst: { $cond: [{ $eq: ["$refundInfo.status", "INIT"] }, 0, 1], }, }, }, { $sort: { initFirst: 1, "refundInfo.createTime": -1, _id: -1 } }, { $skip: (page - 1) * pageSize }, { $limit: pageSize }, ]) .toArray(); const total = await db.collection("consult-order").countDocuments(query); const count = await db .collection("consult-order") .countDocuments({ ...query, "refundInfo.status": "INIT" }); // 解密列表中的敏感字段 const decryptedList = decryptOrderList(list); return { success: true, list: decryptedList, message: "查询成功", total, count }; } catch (e) { return { success: false, message: e.message || "查询失败" }; } } async function handleRefundOrder(ctx) { const { id: _id, orderId, status, reason, operatorId, operator } = ctx; if ( typeof _id !== "string" || _id.trim() === "" || typeof orderId !== "string" || orderId.trim() === "" ) { return { success: false, message: "参数错误" }; } if (typeof status !== "string" || !["PASS", "REJECT"].includes(status)) { return { success: false, message: "无效的退费状态" }; } if ( status === "REJECT" && (typeof reason !== "string" || reason.trim() === "") ) { return { success: false, message: "拒绝退费原因不能为空" }; } try { const doctorCode = typeof ctx.doctorCode === "string" ? ctx.doctorCode : ""; const refundInfo = { "refundInfo.status": status, "refundInfo.rejectReason": status === "REJECT" ? reason.trim() : "", "refundInfo.updateTime": Date.now(), "refundInfo.operatorId": typeof operatorId === "string" ? operatorId.trim() : "", "refundInfo.operator": typeof operator === "string" ? operator.trim() : "", }; const record = await db.collection("consult-order").findOne( { _id: new ObjectId(_id), orderId, "refundInfo.status": "INIT", doctorCode, }, { _id: 1 } ); const rxApi = require("../diagnostic-record"); if (!record) { return { success: false, message: "订单不存在或者退费申请已经处理" }; } if (status === "PASS") { const order = await db .collection("consult-order") .findOne( { orderId }, { projection: { registerId: 1, patientId: 1, medorgOrderNo: 1 } } ); if (order && order.registerId && order.patientId) { const { success, message } = await zytHis({ type: "hlwRefund", patientId: order.patientId, registerId: order.registerId, medorgOrderNo: order.medorgOrderNo, }); if (!success) { return { success: false, message: message || "退费失败", errType: "HIS_REFUND_FAIL", }; } await customerRefundOrder({ registerId: order.registerId, patientId: order.patientId, refundType: "DOCTORAGREEREFUND", }); await rxApi({ type: "discardDiagnosticRecord", orderId }, db); } } await db .collection("consult-order") .updateOne({ _id: record._id }, { $set: refundInfo }); return { success: true, message: "操作成功", data: refundInfo }; } catch (e) { return { success: false, message: e.message || "操作失败" }; } } async function autoHandleExpireOrder() { const hour = dayjs().hour(); if (hour < 22 || hour > 23) { return { success: false, message: '每天无效订单自动退费时间在22:00-24:00之间' } } if (scheduleTaskIsRunning) return; scheduleTaskIsRunning = true; try { // 订单过期判断 有expireTime,则根据expireTime字段判断 否则根据 payExpireTime const conditions = { $or: [ { orderStatus: "pending", createTime: { $gt: dayjs().startOf("day").valueOf() }, payExpireTime: { $lt: Date.now() }, expireTime: { $exists: false } }, { orderStatus: "pending", createTime: { $gt: dayjs().startOf("day").valueOf() }, expireTime: { $lt: Date.now() } } ] } const orderList = await db.collection("consult-order").find(conditions, { projection: { _id: 1, orderId: 1, patientId: 1, registerId: 1, medorgOrderNo: 1, consultType: 1 } }).toArray(); const now = dayjs().format('YYYY-MM-DD HH:mm:ss') const updateTime = Date.now(); let processedCount = 0; let refundedCount = 0; let cancelledCount = 0; let errorCount = 0; for (let order of orderList) { try { const rx = await db.collection("diagnostic-record").findOne({ orderId: order.orderId }, { projection: { _id: 1, status: 1 } }); const hasValidRx = rx && rx.status === 'PASS'; // 配药订单咨询 实际无需支付, 问诊费和药费事后一起收取 if (order.consultType === 'onlineMedicinePurchase') { const target = hasValidRx ? { orderStatus: "finished", updateTime } : { updateTime, orderStatus: "cancelled", payStatus: "cancelled", reason: `取消原因: 订单超时未处理,定时任务自动取消(${now})` }; await db.collection("consult-order").updateOne({ _id: order._id }, { $set: target }); processedCount++; if (!hasValidRx) cancelledCount++; continue; } // 在线问诊 自动结束 if (hasValidRx) { await db.collection("consult-order").updateOne({ _id: order._id }, { $set: { orderStatus: "finished", updateTime } }); processedCount++; continue; } // 检查必要字段 if (!order.patientId || !order.registerId || !order.medorgOrderNo) { // 缺少必要字段,直接取消订单 await db.collection("consult-order").updateOne({ _id: order._id }, { $set: { updateTime, orderStatus: "cancelled", payStatus: "cancelled", reason: `取消原因: 订单信息不完整,定时任务自动取消(${now})` } }); processedCount++; cancelledCount++; continue; } const payStatusResult = await zytHis({ type: 'getPayStatus', patientId: order.patientId, registerId: order.registerId, medorgOrderNo: order.medorgOrderNo }); // 如果查询失败,记录错误但继续处理下一个订单 if (!payStatusResult || !payStatusResult.success) { errorCount++; continue; } const status = payStatusResult.status; // (1 已退费 5 未收费 x 已作废) his状态不需要退费的情况 直接修改为取消状态 if (['5', '1', 'x'].includes(status)) { await db.collection("consult-order").updateOne({ _id: order._id }, { $set: { updateTime, orderStatus: "cancelled", payStatus: "cancelled", reason: `取消原因: 订单超时未处理,定时任务自动取消(${now})` } }); processedCount++; cancelledCount++; continue; } // his状态不是已收费 直接跳过 if (status !== '0') { continue; } const refundResult = await zytHis({ type: 'hlwRefund', patientId: order.patientId, registerId: order.registerId, medorgOrderNo: order.medorgOrderNo }); if (refundResult && refundResult.success) { await db.collection("consult-order").updateOne({ _id: order._id }, { $set: { updateTime, orderStatus: "cancelled", payStatus: "refunded", reason: `取消原因: 订单超时未处理,定时任务自动退费(${now})` } }); processedCount++; refundedCount++; } else { // 退费失败,记录错误但继续处理 errorCount++; } } catch (orderError) { // 单个订单处理失败,记录错误但继续处理下一个 errorCount++; console.error(`处理订单 ${order.orderId} 时出错:`, orderError); } } console.log(`处理完成: 共处理${orderList.length}个订单, 成功${processedCount}个, 退费${refundedCount}个, 取消${cancelledCount}个, 错误${errorCount}个`) scheduleTaskIsRunning = false; return { success: true, message: "处理完成" }; } catch (e) { scheduleTaskIsRunning = false; console.error("处理订单失败:", e.message); return { success: false, message: e.message || "操作失败" }; } }