2143 lines
65 KiB
JavaScript
Raw Permalink Normal View History

2026-07-27 11:28:33 +08:00
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 || "操作失败" };
}
}