911 lines
25 KiB
JavaScript
911 lines
25 KiB
JavaScript
|
|
const dayjs = require("dayjs");
|
|||
|
|
const setCountText = require("./order-status");
|
|||
|
|
const { ObjectId } = require("mongodb");
|
|||
|
|
const unionPay = require("../union-pay");
|
|||
|
|
|
|||
|
|
module.exports = async (item, db) => {
|
|||
|
|
const builded = process.env.IS_BUILDED === 'YES';
|
|||
|
|
switch (item.statsType) {
|
|||
|
|
case "order":
|
|||
|
|
return await getOrderCount(item, db);
|
|||
|
|
case "doctorOrder":
|
|||
|
|
return await getDoctorOrderCount(item, db);
|
|||
|
|
case "getStoreMatePadRxStats":
|
|||
|
|
return await getStoreMatePadRxStats(item, db);
|
|||
|
|
case "zyStoreRx":
|
|||
|
|
return await getZyStoreRxCount(item, db);
|
|||
|
|
// case "oldRx":
|
|||
|
|
// return await getZyStoreAgeRxCount(item, db);
|
|||
|
|
case "getPayStatus":
|
|||
|
|
return await getHisPayStatus(item, db);
|
|||
|
|
case "rxDurationStats":
|
|||
|
|
return await getRxDurationStats(item, db);
|
|||
|
|
case "drugStats":
|
|||
|
|
return await getDrugStats(item, db);
|
|||
|
|
case "createAlipayOrder":
|
|||
|
|
return builded ? null : await createAlipayOrder(item, db);
|
|||
|
|
case "queryAlipayOrder":
|
|||
|
|
return await queryAlipayOrder(item, db);
|
|||
|
|
case "refundAlipayOrder":
|
|||
|
|
return builded ? null : await refundAlipayOrder(item, db);
|
|||
|
|
case "fengniaoTest":
|
|||
|
|
return await fengniaoTest(item, db);
|
|||
|
|
case "emsTest":
|
|||
|
|
return await emsTest(item, db);
|
|||
|
|
case "hisTest":
|
|||
|
|
return await hisTest(item, db);
|
|||
|
|
case "lackTest":
|
|||
|
|
return await lackTest(item, db);
|
|||
|
|
case "purchaseTest":
|
|||
|
|
return await purchaseTest(item, db);
|
|||
|
|
case "testMedicineNotify":
|
|||
|
|
return await testMedicineNotify(item, db);
|
|||
|
|
case "tradeTest":
|
|||
|
|
return await tradeTest(item, db);
|
|||
|
|
case "unionTest":
|
|||
|
|
// return await unionPay.main({ type: "refundUnionPayBill", billNo: '3JHR202604091344UN' , billDate: Date.now(), refundAmount: 100 });
|
|||
|
|
// return await unionPay.main({ type: "getUnionPayQrcode", billNo: '3JHR202604091344UN' , billDate: Date.now(), totalAmount: 100 });
|
|||
|
|
case "wineTest":
|
|||
|
|
return await wineTest(item, db);
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
return { success: false, message: "未知统计类型!!" };
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function getDateRange({ dates }) {
|
|||
|
|
console.log("dates", dates);
|
|||
|
|
const dateArr =
|
|||
|
|
typeof dates === "string"
|
|||
|
|
? dates
|
|||
|
|
.split(",")
|
|||
|
|
.filter((i) => i && dayjs(i).isValid())
|
|||
|
|
.map((i) => dayjs(i))
|
|||
|
|
: [];
|
|||
|
|
console.log("dateArr", dateArr);
|
|||
|
|
const [dateStart = dayjs(), dateEnd = dayjs(dateStart)] = dateArr;
|
|||
|
|
const minDate = dateStart.isBefore(dateEnd) ? dateStart : dateEnd;
|
|||
|
|
const maxDate = dateStart.isBefore(dateEnd) ? dateEnd : dateStart;
|
|||
|
|
if (Math.abs(minDate.diff(maxDate, "day")) > 30) {
|
|||
|
|
return [
|
|||
|
|
minDate.startOf("day").valueOf(),
|
|||
|
|
minDate.add(31, "day").endOf("day").valueOf(),
|
|||
|
|
];
|
|||
|
|
}
|
|||
|
|
console.log("minDate", minDate);
|
|||
|
|
console.log("maxDate", maxDate);
|
|||
|
|
return [minDate.startOf("day").valueOf(), maxDate.endOf("day").valueOf()];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getOrderCount(params, db) {
|
|||
|
|
try {
|
|||
|
|
const [startTime, endTime] = params;
|
|||
|
|
const startTimeTemp = dayjs(startTime).startOf("day").valueOf();
|
|||
|
|
const endTimeTemp = dayjs(endTime).endOf("day").valueOf();
|
|||
|
|
const data = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.aggregate([
|
|||
|
|
{ $match: { createTime: { $gte: startTimeTemp, $lte: endTimeTemp } } },
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: {
|
|||
|
|
orderStatus: "$orderStatus",
|
|||
|
|
payStatus: "$payStatus",
|
|||
|
|
},
|
|||
|
|
count: { $sum: 1 }, // 统计每个组合的数量
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$project: {
|
|||
|
|
_id: 0, // 如果不需要显示 _id
|
|||
|
|
orderStatus: "$_id.orderStatus",
|
|||
|
|
payStatus: "$_id.payStatus",
|
|||
|
|
count: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
const res = setCountText(data);
|
|||
|
|
const allCount = res.reduce((acc, cur) => acc + cur.count, 0);
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: "查询成功",
|
|||
|
|
startDate: dayjs(startTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
endDate: dayjs(endTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
allCount: allCount,
|
|||
|
|
data: res,
|
|||
|
|
};
|
|||
|
|
} catch (err) {
|
|||
|
|
return { success: false, message: err.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getDoctorOrderCount(params, db) {
|
|||
|
|
try {
|
|||
|
|
const [startTime, endTime] = getDateRange(params);
|
|||
|
|
const doctorCount = await db
|
|||
|
|
.collection("hlw-doctor")
|
|||
|
|
.countDocuments({ job: "doctor" });
|
|||
|
|
const doctorList = await db
|
|||
|
|
.collection("hlw-doctor")
|
|||
|
|
.find(
|
|||
|
|
{ job: "doctor" },
|
|||
|
|
{ projection: { doctorName: 1, doctorNo: 1, _id: 0 } }
|
|||
|
|
)
|
|||
|
|
.toArray();
|
|||
|
|
const data = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.aggregate([
|
|||
|
|
{ $match: { createTime: { $gte: startTime, $lte: endTime } } },
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: {
|
|||
|
|
orderStatus: "$orderStatus",
|
|||
|
|
payStatus: "$payStatus",
|
|||
|
|
doctorCode: "$doctorCode",
|
|||
|
|
},
|
|||
|
|
count: { $sum: 1 }, // 统计每个组合的数量
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$project: {
|
|||
|
|
_id: 0, // 如果不需要显示 _id
|
|||
|
|
doctorCode: "$_id.doctorCode",
|
|||
|
|
orderStatus: "$_id.orderStatus",
|
|||
|
|
payStatus: "$_id.payStatus",
|
|||
|
|
count: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
const res = setCountText(data, doctorList);
|
|||
|
|
const allCount = res.reduce((acc, cur) => acc + (cur.allCount || 0), 0);
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: "查询成功",
|
|||
|
|
startDate: dayjs(startTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
endDate: dayjs(endTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
allCount,
|
|||
|
|
doctorCount,
|
|||
|
|
statsCount: res.length,
|
|||
|
|
data: res,
|
|||
|
|
};
|
|||
|
|
} catch (err) {
|
|||
|
|
return { success: false, message: err.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getStoreCount(params, db) {
|
|||
|
|
try {
|
|||
|
|
let storeIds = [];
|
|||
|
|
const [startTime, endTime] = getDateRange(params);
|
|||
|
|
if (params.dataType === "storeOrder" || params.dataType === "storeRx") {
|
|||
|
|
if (typeof params.area !== "string" || params.area.trim() === "") {
|
|||
|
|
return { success: false, message: "区域不能为空" };
|
|||
|
|
}
|
|||
|
|
const stores = await db
|
|||
|
|
.collection("store-list")
|
|||
|
|
.find(
|
|||
|
|
{ "region.2": params.area },
|
|||
|
|
{ projection: { store_id: 1, _id: 0 } }
|
|||
|
|
)
|
|||
|
|
.toArray();
|
|||
|
|
storeIds = stores.map((i) => i.store_id);
|
|||
|
|
}
|
|||
|
|
// 统计越城区药店的今日订单数量 start
|
|||
|
|
if (params.dataType === "storeOrder") {
|
|||
|
|
const storeOrderStats = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.aggregate([
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
drugStoreNo: { $in: storeIds },
|
|||
|
|
createTime: { $gte: startTime, $lte: endTime },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: "$drugStoreNo",
|
|||
|
|
drugStoreName: { $first: "$drugStoreName" },
|
|||
|
|
count: { $sum: 1 }, // 统计每个组合的数量
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
const storeOrderRes = Array.from(storeOrderStats.values());
|
|||
|
|
return storeOrderRes;
|
|||
|
|
}
|
|||
|
|
if (params.dataType === "storeRx") {
|
|||
|
|
// 统计药店的处方数量 start
|
|||
|
|
const orders = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.find(
|
|||
|
|
{
|
|||
|
|
drugStoreNo: { $in: storeIds },
|
|||
|
|
createTime: { $gte: startTime, $lte: endTime },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
projection: {
|
|||
|
|
orderId: 1,
|
|||
|
|
_id: 0,
|
|||
|
|
drugStoreName: 1,
|
|||
|
|
drugStoreNo: 1,
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
.toArray();
|
|||
|
|
const orderIds = orders.map((i) => i.orderId);
|
|||
|
|
const record = await db
|
|||
|
|
.collection("diagnostic-record")
|
|||
|
|
.aggregate([
|
|||
|
|
{ $match: { orderId: { $in: orderIds }, status: "PASS" } },
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: "$orderId",
|
|||
|
|
count: { $sum: 1 }, // 统计每个组合的数量
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
const om = record.reduce((acc, cur) => {
|
|||
|
|
acc[cur._id] = cur.count;
|
|||
|
|
return acc;
|
|||
|
|
}, {});
|
|||
|
|
const rxOrders = orders.filter((i) => om[i.orderId] > 0);
|
|||
|
|
const storeRx = rxOrders.reduce((acc, cur) => {
|
|||
|
|
const data = acc.get(cur.drugStoreNo) || {
|
|||
|
|
drugStoreNo: cur.drugStoreNo,
|
|||
|
|
drugStoreName: cur.drugStoreName,
|
|||
|
|
count: 0,
|
|||
|
|
};
|
|||
|
|
data.count += 1;
|
|||
|
|
acc.set(cur.drugStoreNo, data);
|
|||
|
|
return acc;
|
|||
|
|
}, new Map());
|
|||
|
|
const storeRxRes = Array.from(storeRx.values());
|
|||
|
|
// 统计不同类型药店的数据
|
|||
|
|
const typeStore = storeRxRes.reduce(
|
|||
|
|
(acc, cur) => {
|
|||
|
|
if (cur.drugStoreName.startsWith("浙江震元")) {
|
|||
|
|
acc.zy += cur.count;
|
|||
|
|
} else {
|
|||
|
|
acc.nzy += cur.count;
|
|||
|
|
}
|
|||
|
|
return acc;
|
|||
|
|
},
|
|||
|
|
{ zy: 0, nzy: 0 }
|
|||
|
|
);
|
|||
|
|
return { ...typeStore, storeRxRes };
|
|||
|
|
}
|
|||
|
|
if (params.dataType === "doctorRx") {
|
|||
|
|
// 统计医生的处方数量 start
|
|||
|
|
const doctorRx = await db
|
|||
|
|
.collection("diagnostic-record")
|
|||
|
|
.aggregate([
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
createTime: { $gte: startTime, $lte: endTime },
|
|||
|
|
status: "PASS",
|
|||
|
|
_id: {
|
|||
|
|
$nin: [
|
|||
|
|
new ObjectId("67eca29fecce43c72c51d1e7"),
|
|||
|
|
new ObjectId("67ecfe26ecce43c72c520ec7"),
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: "$doctorCode",
|
|||
|
|
doctorName: { $first: "$doctorName" },
|
|||
|
|
count: { $sum: 1 }, // 统计每个组合的数量
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
return doctorRx;
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getPeriodRxCount(params, db) {
|
|||
|
|
const data =
|
|||
|
|
params.date && dayjs(params.period).isValid()
|
|||
|
|
? dayjs(params.date).format("YYYY-MM-DD")
|
|||
|
|
: dayjs().format("YYYY-MM-DD");
|
|||
|
|
try {
|
|||
|
|
let time = dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss");
|
|||
|
|
const group = [];
|
|||
|
|
while (dayjs(time).isBefore(dayjs().endOf("day"))) {
|
|||
|
|
group.push([
|
|||
|
|
dayjs(time).valueOf(),
|
|||
|
|
dayjs(time).add(30, "minutes").valueOf(),
|
|||
|
|
]);
|
|||
|
|
// group.push({ $match: { createTime: { $gte: dayjs(time).format('YYYY-MM-DD HH:mm:ss'), $lt: dayjs(time).add(30, 'minutes').format('YYYY-MM-DD HH:mm:ss') }, status: 'PASS' } })
|
|||
|
|
time = dayjs(time).add(30, "minutes").format("YYYY-MM-DD HH:mm:ss");
|
|||
|
|
}
|
|||
|
|
const result = [];
|
|||
|
|
for (let [start, end] of group) {
|
|||
|
|
const total = await db.collection("diagnostic-record").countDocuments({
|
|||
|
|
createTime: { $gte: start, $lt: end },
|
|||
|
|
status: "PASS",
|
|||
|
|
});
|
|||
|
|
result.push({
|
|||
|
|
start: dayjs(start).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
end: dayjs(end).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
total,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getStoreMatePadRxStats(params, db) {
|
|||
|
|
const [startTime, endTime] = getDateRange(params);
|
|||
|
|
try {
|
|||
|
|
const res = await db
|
|||
|
|
.collection("diagnostic-record")
|
|||
|
|
.aggregate([
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
orderSource: "MATEPAD",
|
|||
|
|
createTime: { $gte: startTime, $lte: endTime },
|
|||
|
|
status: "PASS",
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: "$drugStoreNo",
|
|||
|
|
count: { $sum: 1 },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
const stores = await db
|
|||
|
|
.collection("store-list")
|
|||
|
|
.find(
|
|||
|
|
{ store_id: { $in: res.map((i) => i._id) } },
|
|||
|
|
{ projection: { store_id: 1, name: 1, _id: 0 } }
|
|||
|
|
)
|
|||
|
|
.toArray();
|
|||
|
|
return { success: true, data: res, stores };
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getZyStoreRxCount(ctx, db) {
|
|||
|
|
const [startTime, endTime, storeType, source] = getDateRange(ctx);
|
|||
|
|
const storeTypes = storeType === "other" ? ["其他"] : ["加盟", "直营"];
|
|||
|
|
try {
|
|||
|
|
const stores = await db
|
|||
|
|
.collection("store-list")
|
|||
|
|
.find(
|
|||
|
|
{ type: { $in: storeTypes } },
|
|||
|
|
{ projection: { store_id: 1, name: 1, _id: 0 } }
|
|||
|
|
)
|
|||
|
|
.toArray();
|
|||
|
|
const storeIds = stores.map((i) => i.store_id);
|
|||
|
|
const m = stores.reduce((acc, cur) => {
|
|||
|
|
// console.log(cur.store_id, cur.name)
|
|||
|
|
acc.set(cur.store_id, cur.name);
|
|||
|
|
return acc;
|
|||
|
|
}, new Map());
|
|||
|
|
const matches = {
|
|||
|
|
drugStoreNo: { $in: storeIds },
|
|||
|
|
createTime: { $gte: startTime, $lte: endTime },
|
|||
|
|
status: "PASS",
|
|||
|
|
};
|
|||
|
|
if (source) {
|
|||
|
|
matches.orderSource = source;
|
|||
|
|
}
|
|||
|
|
const res = await db
|
|||
|
|
.collection("diagnostic-record")
|
|||
|
|
.aggregate([
|
|||
|
|
{ $match: matches },
|
|||
|
|
{
|
|||
|
|
$addFields: {
|
|||
|
|
date: {
|
|||
|
|
$dateToString: {
|
|||
|
|
format: "%Y-%m-%d",
|
|||
|
|
date: { $toDate: "$createTime" },
|
|||
|
|
timezone: "Asia/Shanghai", // 设置为中国标准时间
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: { date: "$date", id: "$drugStoreNo" },
|
|||
|
|
date: { $first: "$date" },
|
|||
|
|
drugStoreNo: { $first: "$drugStoreNo" },
|
|||
|
|
count: { $sum: 1 },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$project: {
|
|||
|
|
_id: 0,
|
|||
|
|
date: 1,
|
|||
|
|
drugStoreNo: 1,
|
|||
|
|
count: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
res.forEach((i) => {
|
|||
|
|
i.name = m.get(i.drugStoreNo) || "";
|
|||
|
|
});
|
|||
|
|
return res;
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getZyStoreAgeRxCount(ctx, db) {
|
|||
|
|
const [startTime, endTime] = getDateRange(ctx);
|
|||
|
|
try {
|
|||
|
|
const query = { createTime: { $gte: startTime, $lte: endTime } };
|
|||
|
|
if (ctx.ageType === "old") {
|
|||
|
|
query.age = { $gte: 70 };
|
|||
|
|
} else {
|
|||
|
|
query.age = { $lt: 70 };
|
|||
|
|
}
|
|||
|
|
const orders = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.find(query, { projection: { orderId: 1, _id: 0 } })
|
|||
|
|
.toArray();
|
|||
|
|
const orderIds = orders.map((i) => i.orderId);
|
|||
|
|
const rxCountGroup = await db
|
|||
|
|
.collection("diagnostic-record")
|
|||
|
|
.aggregate([
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
createTime: { $gte: startTime, $lte: endTime },
|
|||
|
|
status: "PASS",
|
|||
|
|
orderId: { $in: orderIds },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: "$drugStoreNo",
|
|||
|
|
drugStoreNo: { $first: "$drugStoreNo" },
|
|||
|
|
count: { $sum: 1 },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
])
|
|||
|
|
.toArray();
|
|||
|
|
const stores = await db
|
|||
|
|
.collection("store-list")
|
|||
|
|
.find(
|
|||
|
|
{ store_id: { $in: rxCountGroup.map((i) => i.drugStoreNo) } },
|
|||
|
|
{ projection: { store_id: 1, name: 1, _id: 0, type: 1, region: 1 } }
|
|||
|
|
)
|
|||
|
|
.toArray();
|
|||
|
|
const m = stores.reduce((acc, cur) => {
|
|||
|
|
acc.set(cur.store_id, cur);
|
|||
|
|
return acc;
|
|||
|
|
}, new Map());
|
|||
|
|
|
|||
|
|
rxCountGroup.forEach((i) => {
|
|||
|
|
const store = m.get(i.drugStoreNo) || null;
|
|||
|
|
if (store) {
|
|||
|
|
i.name = store.name || "";
|
|||
|
|
i.type = store.type || "";
|
|||
|
|
i.area = Array.isArray(store.region) ? store.region[2] : "";
|
|||
|
|
} else {
|
|||
|
|
i.name = "";
|
|||
|
|
i.type = "";
|
|||
|
|
i.area = "";
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
return rxCountGroup;
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getHisPayStatus(ctx) {
|
|||
|
|
// patientId, registerId, medorgOrderNo
|
|||
|
|
const { patientId, registerId } = ctx;
|
|||
|
|
const hisApi = require("../zyt-his");
|
|||
|
|
const res = await hisApi({
|
|||
|
|
type: "getPayStatus",
|
|||
|
|
patientId,
|
|||
|
|
registerId,
|
|||
|
|
medorgOrderNo: registerId,
|
|||
|
|
});
|
|||
|
|
if (res.success) {
|
|||
|
|
return { success: true, data: res };
|
|||
|
|
} else {
|
|||
|
|
return { success: false, message: res.message || "查询失败" };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function refundFee(ctx) {
|
|||
|
|
// patientId, registerId, medorgOrderNo
|
|||
|
|
const { patientId, registerId } = ctx;
|
|||
|
|
const hisApi = require("../zyt-his");
|
|||
|
|
const res = await hisApi({
|
|||
|
|
type: "hlwRefund",
|
|||
|
|
patientId,
|
|||
|
|
registerId,
|
|||
|
|
medorgOrderNo: registerId,
|
|||
|
|
});
|
|||
|
|
if (res.success) {
|
|||
|
|
return { success: true, data: res };
|
|||
|
|
} else {
|
|||
|
|
return { success: false, message: res.message || "查询失败" };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getRxDurationStats(params, db) {
|
|||
|
|
const { startTime, endTime } = params;
|
|||
|
|
const startTimeTemp = dayjs(startTime).startOf("day").valueOf();
|
|||
|
|
const endTimeTemp = dayjs(endTime).endOf("day").valueOf();
|
|||
|
|
|
|||
|
|
const pipeline = [
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
// age: { $gte: 60 },
|
|||
|
|
createTime: { $gte: startTimeTemp, $lte: endTimeTemp },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$project: {
|
|||
|
|
orderId: 1,
|
|||
|
|
_id: 0,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$lookup: {
|
|||
|
|
from: "hlw-doctor-times",
|
|||
|
|
localField: "orderId",
|
|||
|
|
foreignField: "orderId",
|
|||
|
|
as: "doctorTimes",
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$unwind: {
|
|||
|
|
path: "$doctorTimes",
|
|||
|
|
preserveNullAndEmptyArrays: false,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
"doctorTimes.rxDuration": { $gt: 0 },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
// 6. 计算统计信息
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: null,
|
|||
|
|
totalCount: { $sum: 1 },
|
|||
|
|
avgDuration: { $avg: "$doctorTimes.rxDuration" },
|
|||
|
|
minDuration: { $min: "$doctorTimes.rxDuration" },
|
|||
|
|
maxDuration: { $max: "$doctorTimes.rxDuration" },
|
|||
|
|
durations: { $push: "$doctorTimes.rxDuration" },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const result = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.aggregate(pipeline)
|
|||
|
|
.toArray();
|
|||
|
|
|
|||
|
|
if (result.length === 0) {
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: "查询成功",
|
|||
|
|
startDate: dayjs(startTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
endDate: dayjs(endTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
totalOrders: 0,
|
|||
|
|
stats: {
|
|||
|
|
totalCount: 0,
|
|||
|
|
avgDuration: 0,
|
|||
|
|
minDuration: 0,
|
|||
|
|
maxDuration: 0,
|
|||
|
|
durationRanges: [],
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const stats = result[0];
|
|||
|
|
const durations = stats.durations;
|
|||
|
|
|
|||
|
|
// 按时长范围分组统计
|
|||
|
|
const durationRanges = [
|
|||
|
|
{ range: "0-30s", min: 0, max: 30000, count: 0 },
|
|||
|
|
{ range: "30s-1分钟", min: 30000, max: 60000, count: 0 },
|
|||
|
|
{ range: "1分钟-2分钟", min: 60000, max: 120000, count: 0 },
|
|||
|
|
{ range: "2-3分钟", min: 120000, max: 180000, count: 0 },
|
|||
|
|
{ range: "3分钟以上", min: 180000, max: Infinity, count: 0 },
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
durations.forEach((duration) => {
|
|||
|
|
const range = durationRanges.find(
|
|||
|
|
(r) => duration >= r.min && duration < r.max
|
|||
|
|
);
|
|||
|
|
if (range) {
|
|||
|
|
range.count++;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: "查询成功",
|
|||
|
|
startDate: dayjs(startTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
endDate: dayjs(endTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
totalOrders: stats.totalCount,
|
|||
|
|
stats: {
|
|||
|
|
totalCount: stats.totalCount,
|
|||
|
|
avgDuration: Math.round(stats.avgDuration),
|
|||
|
|
minDuration: stats.minDuration,
|
|||
|
|
maxDuration: stats.maxDuration,
|
|||
|
|
durationRanges: durationRanges.filter((range) => range.count > 0),
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getDrugStats(params, db) {
|
|||
|
|
const { startTime, endTime } = params;
|
|||
|
|
const startTimeTemp = dayjs(startTime).startOf("day").valueOf();
|
|||
|
|
const endTimeTemp = dayjs(endTime).endOf("day").valueOf();
|
|||
|
|
// 先检查基础数据
|
|||
|
|
const baseCount = await db.collection("consult-order").countDocuments({
|
|||
|
|
age: { $gte: 60 },
|
|||
|
|
createTime: { $gte: startTimeTemp, $lte: endTimeTemp },
|
|||
|
|
});
|
|||
|
|
console.log("基础订单数量 (age >= 60):", baseCount);
|
|||
|
|
|
|||
|
|
const pipeline = [
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
age: { $gte: 60 },
|
|||
|
|
createTime: { $gte: startTimeTemp, $lte: endTimeTemp },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$project: {
|
|||
|
|
orderId: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$lookup: {
|
|||
|
|
from: "diagnostic-record",
|
|||
|
|
localField: "orderId",
|
|||
|
|
foreignField: "orderId",
|
|||
|
|
as: "diagnosticRecords",
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$unwind: {
|
|||
|
|
path: "$diagnosticRecords",
|
|||
|
|
preserveNullAndEmptyArrays: false,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$match: {
|
|||
|
|
"diagnosticRecords.status": "PASS",
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
// 调试:检查诊断记录数量
|
|||
|
|
{
|
|||
|
|
$addFields: {
|
|||
|
|
debug_drugs_count: {
|
|||
|
|
$size: { $ifNull: ["$diagnosticRecords.drugs", []] },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$unwind: {
|
|||
|
|
path: "$diagnosticRecords.drugs",
|
|||
|
|
preserveNullAndEmptyArrays: false,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
$group: {
|
|||
|
|
_id: {
|
|||
|
|
drugName: "$diagnosticRecords.drugs.drugName",
|
|||
|
|
insuranceCode: "$diagnosticRecords.drugs.insurance_code",
|
|||
|
|
productId: "$diagnosticRecords.drugs.product_id",
|
|||
|
|
specification: "$diagnosticRecords.drugs.specification",
|
|||
|
|
unit: "$diagnosticRecords.drugs.unit",
|
|||
|
|
},
|
|||
|
|
totalQuantity: { $sum: "$diagnosticRecords.drugs.quantity" },
|
|||
|
|
prescriptionCount: { $sum: 1 },
|
|||
|
|
drugInfo: { $first: "$diagnosticRecords.drugs" },
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
// 8. 格式化输出
|
|||
|
|
{
|
|||
|
|
$project: {
|
|||
|
|
_id: 0,
|
|||
|
|
drugName: "$_id.drugName",
|
|||
|
|
insuranceCode: "$_id.insuranceCode",
|
|||
|
|
productId: "$_id.productId",
|
|||
|
|
specification: "$_id.specification",
|
|||
|
|
unit: "$_id.unit",
|
|||
|
|
totalQuantity: 1,
|
|||
|
|
prescriptionCount: 1,
|
|||
|
|
drugInfo: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
// 9. 按总数量降序排序
|
|||
|
|
{
|
|||
|
|
$sort: {
|
|||
|
|
totalQuantity: -1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
// 10. 限制返回前30条记录
|
|||
|
|
{
|
|||
|
|
$limit: 30,
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const result = await db
|
|||
|
|
.collection("consult-order")
|
|||
|
|
.aggregate(pipeline)
|
|||
|
|
.toArray();
|
|||
|
|
console.log("聚合结果数量:", result.length);
|
|||
|
|
console.log("前3条结果:", result.slice(0, 3));
|
|||
|
|
|
|||
|
|
// 计算总统计信息
|
|||
|
|
const totalPrescriptions = result.reduce(
|
|||
|
|
(sum, item) => sum + item.prescriptionCount,
|
|||
|
|
0
|
|||
|
|
);
|
|||
|
|
const totalQuantity = result.reduce(
|
|||
|
|
(sum, item) => sum + item.totalQuantity,
|
|||
|
|
0
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
success: true,
|
|||
|
|
message: "查询成功",
|
|||
|
|
startDate: dayjs(startTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
endDate: dayjs(endTime).format("YYYY-MM-DD HH:mm:ss"),
|
|||
|
|
summary: {
|
|||
|
|
totalPrescriptions, // 总处方次数
|
|||
|
|
totalDrugTypes: result.length, // 药品种类数(前30)
|
|||
|
|
totalQuantity, // 总药品数量(盒数)
|
|||
|
|
},
|
|||
|
|
data: result, // Top30 药品统计,按数量降序排列
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
async function createAlipayOrder() {
|
|||
|
|
try {
|
|||
|
|
const tradeApi = require("../trade");
|
|||
|
|
const payload = {
|
|||
|
|
totalAmount: 0.02,
|
|||
|
|
businessNo: dayjs().valueOf().toString(),
|
|||
|
|
businessType: 'onlineMedicinePurchase',
|
|||
|
|
desc: `[${dayjs().format('YYYY-MM-DD HH:mm:ss')}] 线上购药订单测试`,
|
|||
|
|
openId: '2088612594454930'
|
|||
|
|
}
|
|||
|
|
const { success, message, tradeNo } = await tradeApi.getAlipayTradeNo(payload);
|
|||
|
|
if (success) {
|
|||
|
|
return { success: true, message: '创建交易订单成功', tradeNo: tradeNo };
|
|||
|
|
} else {
|
|||
|
|
return { success: false, message: message };
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function queryAlipayOrder(data) {
|
|||
|
|
try {
|
|||
|
|
const tradeApi = require("../trade");
|
|||
|
|
const { success, message, data: tradeInfo } = await tradeApi.queryAlipayTradeNo(data);
|
|||
|
|
if (success) {
|
|||
|
|
return { success: true, message: '查询交易订单成功', data: tradeInfo };
|
|||
|
|
} else {
|
|||
|
|
return { success: false, message: message };
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function refundAlipayOrder(data) {
|
|||
|
|
try {
|
|||
|
|
const tradeApi = require("../trade");
|
|||
|
|
console.log(`申请退费: ${data.tradeNo}`)
|
|||
|
|
const res = await tradeApi.refundTrade({ tradeNo: data.tradeNo, reason: `${dayjs().format('YYYY-MM-DD HH:mm:ss')} 用户申请退款` });
|
|||
|
|
return res
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function fengniaoTest(ctx) {
|
|||
|
|
try {
|
|||
|
|
const fengniaoApi = require("../fengniao");
|
|||
|
|
const res = await fengniaoApi.fengniaoTest(ctx);
|
|||
|
|
return { success: true, data: res }
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
async function emsTest() {
|
|||
|
|
try {
|
|||
|
|
const emsApi = require("../ems-express");
|
|||
|
|
const res = await emsApi.emsTest();
|
|||
|
|
return { success: true, data: res }
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function hisTest() {
|
|||
|
|
const hisApi = require("../zyt-his");
|
|||
|
|
const res = await hisApi({
|
|||
|
|
type: "hisTest"
|
|||
|
|
});
|
|||
|
|
return { success: true, data: res }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function lackTest(item, db) {
|
|||
|
|
try {
|
|||
|
|
const lackApi = require("../lack-medicine-reg");
|
|||
|
|
const res = await lackApi({
|
|||
|
|
type: "lackTest"
|
|||
|
|
}, db);
|
|||
|
|
return { success: true, data: res }
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function wineTest(item, db) {
|
|||
|
|
try {
|
|||
|
|
const api = require("../chinese-medicine-order");
|
|||
|
|
return await api.main({
|
|||
|
|
type: "wineTest"
|
|||
|
|
}, db);
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function purchaseTest(item, db) {
|
|||
|
|
try {
|
|||
|
|
const purchaseApi = require("../medicine-purchase-order");
|
|||
|
|
const res = await purchaseApi({
|
|||
|
|
type: "purchaseTest"
|
|||
|
|
}, db);
|
|||
|
|
return { success: true, data: res }
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function testMedicineNotify(item, db) {
|
|||
|
|
try {
|
|||
|
|
const purchaseApi = require("../medicine-purchase-order");
|
|||
|
|
return await purchaseApi({
|
|||
|
|
type: "testMedicineNotify"
|
|||
|
|
}, db);
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function tradeTest(item, db) {
|
|||
|
|
try {
|
|||
|
|
const tradeApi = require("../trade");
|
|||
|
|
const res = await tradeApi.tradeTest();
|
|||
|
|
return { success: true, data: res }
|
|||
|
|
} catch (e) {
|
|||
|
|
return { success: false, message: e.message }
|
|||
|
|
}
|
|||
|
|
}
|