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