2143 lines
65 KiB
JavaScript
2143 lines
65 KiB
JavaScript
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 || "操作失败" };
|
||
}
|
||
}
|