503 lines
18 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
const dayjs = require("dayjs");
const { ObjectId } = require("mongodb");
const { getDrugList } = require('./verify');
2026-08-25 13:39:09 +08:00
const { validateApplicableDiagnosisCodes } = require('./applicable-diagnosis');
2026-07-27 11:28:33 +08:00
let db = "";
2026-07-30 16:49:41 +08:00
2026-08-24 16:41:11 +08:00
function getConfigOptionNames(list) {
return [...new Set((Array.isArray(list) ? list : [])
.map(item => typeof item === "string" ? item : item && item.name)
.filter(Boolean))];
}
async function getHlwDrugOptionLists(corpId) {
if (typeof corpId !== "string" || !corpId.trim()) return {};
const records = await db.collection("hlw-config").find(
{ group: `${corpId.trim()}-medicine-related` },
{ projection: { _id: 0, key: 1, list: 1 } }
).toArray();
const configMap = records.reduce((map, item) => {
if (item.key && Array.isArray(item.list)) map[item.key] = item.list;
return map;
}, {});
const optionLists = {
unit: getConfigOptionNames(configMap["medicine-package-unit"]),
frequency: getConfigOptionNames(configMap["store-medicine-frequence"]),
administration_method: getConfigOptionNames(configMap["store-medicine-administration"]),
dose_time_name: getConfigOptionNames(configMap["medicine-use-time"]),
};
return Object.fromEntries(Object.entries(optionLists).filter(([, list]) => list.length));
}
2026-07-27 11:28:33 +08:00
module.exports = async (item, mongodb) => {
db = mongodb;
switch (item.type) {
case "getDrugInfo":
return await getDrugInfo(item);
case "deleteDrugInfo":
return await deleteDrugInfo(item);
case "updateDrugInfo":
return await updateDrugInfo(item);
case "addDrugInfo":
return await addDrugInfo(item);
case "getHlwDrugInfo":
return await getHlwDrugInfo(item);
case "addHlwDrugInfo":
return await addHlwDrugInfo(item);
case "editHlwDrugInfo":
return await editHlwDrugInfo(item);
case "setHlwDrugOnSale":
return await setHlwDrugOnSale(item);
case "importHlwDrugInfo":
return await importHlwDrugInfo(item);
case "getStoreSimilarDrugInfo":
return await getStoreSimilarDrugInfo(item);
case "searchDrugs":
return await searchDrugs(item);
2026-08-06 18:24:33 +08:00
case "getDrugMatchedDisease":
return await getDrugMatchedDisease(item);
2026-07-27 11:28:33 +08:00
}
};
// 药品库信息
async function getDrugInfo(item) {
2026-08-05 18:39:56 +08:00
let { name, _id, ids, pinyin_code, keyword, insuranceCodes, barcode } = item;
2026-07-27 11:28:33 +08:00
let fuzzyQuery = null;
let query = { onSale: true };
if (typeof name === "string") query.name = new RegExp(name.trim(), "i");
if (_id) query._id = new ObjectId(_id);
if (Array.isArray(ids) && ids.length > 0) {
query._id = { $in: ids.filter(id => ObjectId.isValid(id)).map(id => new ObjectId(id)) };
}
2026-08-05 18:39:56 +08:00
if (typeof barcode === "string") {
query.barcode = barcode.trim();
}
2026-07-27 11:28:33 +08:00
if (typeof pinyin_code === "string")
query.pinyin_code = new RegExp(pinyin_code.trim(), "i");
if (Array.isArray(insuranceCodes)) {
query.insurance_code = { $in: insuranceCodes };
}
const page = Number.isInteger(item.page) && item.page > 0 ? item.page : 1;
const pageSize =
Number.isInteger(item.pageSize) && item.pageSize > 0 ? item.pageSize : 15;
if (typeof keyword === "string" && keyword.trim()) {
const arr = [
{ name: new RegExp(keyword.trim(), "i") },
{ generic_name: new RegExp(keyword.trim(), "i") },
{ barcode: keyword.trim() },
{ pinyin_code: new RegExp(keyword.trim(), "i") },
2026-07-30 16:49:41 +08:00
{ erpId: keyword.trim() },
2026-07-27 11:28:33 +08:00
{ product_id_str: keyword.trim() },
];
fuzzyQuery = { $or: arr };
}
const finalQuery = fuzzyQuery ? { $and: [query, fuzzyQuery] } : query;
try {
// 调用mongo 数据库查询
const res = await db
.collection("drug-info")
.find(finalQuery)
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
const total = await db.collection("drug-info").countDocuments(finalQuery);
return {
success: true,
message: "查询成功",
data: res,
total,
pages: Math.ceil(total / pageSize),
};
} catch (err) {
return {
success: false,
message: "查询失败",
};
}
}
// 删除药品信息
async function deleteDrugInfo(item) {
const { _id } = item;
try {
// 调用mongo 数据库删除
const res = await db.collection("drug-info").deleteOne({
_id: new ObjectId(_id),
});
return {
success: true,
message: "删除成功",
};
} catch (err) {
return {
success: false,
message: "删除失败",
};
}
}
// 更新药品信息
async function updateDrugInfo(item) {
const { updateData, _id } = item;
try {
// 调用mongo 数据库更新
const res = await db
.collection("drug-info")
.updateOne(
{ _id: new ObjectId(_id) },
{ $set: { ...updateData, updateTime: Date.now() } }
);
return {
success: true,
message: "更新成功",
};
} catch (err) {
return {
success: false,
message: "更新失败",
};
}
}
//新增药品信息
/**
* pinyin_code拼音操作码
2026-07-30 16:49:41 +08:00
erpIdERP ID
2026-07-27 11:28:33 +08:00
name名称
specification规格
manufacturer厂家
unit单位
category分类
barcode条形码
insurance_code医保国码
dosage用量
dosage_unit用量单位
frequency频率
days天数
administration_method给药方式
recommended_quantity建议销售数量
* @param {*} item
* @returns
*/
async function addDrugInfo(item) {
const { name } = item;
try {
// 调用mongo 数据库新增
const res = await db.collection("drug-info").insertOne({
name,
createTime: Date.now(),
});
return {
success: true,
data: res,
message: "新增成功",
};
} catch (err) {
return {
success: false,
message: "新增失败",
};
}
}
async function getHlwDrugInfo(ctx) {
try {
2026-09-09 11:07:27 +08:00
// HTTP query parameters may arrive as strings. Number.isInteger('385')
// is false, which previously reset every such request to page 1.
const requestedPage = Number(ctx.page);
const requestedPageSize = Number(ctx.pageSize);
const page = Number.isSafeInteger(requestedPage) && requestedPage > 0 ? requestedPage : 1;
const pageSize = Number.isSafeInteger(requestedPageSize) && requestedPageSize > 0 ? requestedPageSize : 10;
const query = {};
if (typeof ctx.corpId === "string" && ctx.corpId.trim()) {
query.corpId = ctx.corpId.trim();
}
2026-07-27 11:28:33 +08:00
if (typeof ctx.name === "string" && ctx.name.trim()) {
query.name = new RegExp(ctx.name.trim(), "i")
};
if (typeof ctx.onSale === "boolean") {
query.onSale = ctx.onSale
}
2026-07-30 16:49:41 +08:00
if (typeof ctx.erpId === 'string' && ctx.erpId.trim()) {
query.$or = [
{ erpId: ctx.erpId.trim() },
{ product_id_str: ctx.erpId.trim() }
]
2026-07-27 11:28:33 +08:00
}
if (typeof ctx.barcode === 'string' && ctx.barcode.trim()) {
query.barcode = ctx.barcode.trim()
}
if (typeof ctx.insuranceCode === 'string' && ctx.insuranceCode.trim()) {
query.insurance_code = ctx.insuranceCode.trim()
}
2026-09-09 11:07:27 +08:00
// _id makes records with the same createTime deterministic across pages.
const res = await db.collection("drug-info").find(query).sort({ onSale: -1, createTime: -1, _id: 1 }).skip((page - 1) * pageSize).limit(pageSize).toArray();
2026-07-27 11:28:33 +08:00
const total = await db.collection("drug-info").countDocuments(query);
return {
success: true,
message: "查询成功",
data: res,
total,
pages: Math.ceil(total / pageSize),
}
} catch (e) {
return { success: false, message: e.message }
}
}
async function addHlwDrugInfo(ctx) {
const { params = {} } = ctx;
if (Object.prototype.toString.call(params) !== "[object Object]") {
return { success: false, message: "参数错误" }
}
try {
2026-08-24 16:41:11 +08:00
const optionLists = await getHlwDrugOptionLists(ctx.corpId);
2026-07-27 11:28:33 +08:00
const peopleInfo = {
creator: typeof ctx.operator === "string" ? ctx.operator : "",
creatorId: typeof ctx.operatorId === "string" ? ctx.operatorId : "",
createTime: Date.now()
}
2026-08-25 13:39:09 +08:00
const diagnosisCodes = await validateApplicableDiagnosisCodes(params, db);
const { onSale, applicableDiagnosisCodes, ...data } = params;
2026-07-27 11:28:33 +08:00
let newDrug = {};
if (Object.keys(data).length) {
2026-08-24 16:41:11 +08:00
const [item] = getDrugList([data], true, peopleInfo, 'hlw', optionLists);
2026-07-27 11:28:33 +08:00
const { msgs, ...drug } = item;
if (msgs.length) {
return { success: false, message: msgs.join(",") }
}
newDrug = { ...drug }
}
if (typeof onSale === "boolean") {
newDrug.onSale = onSale;
}
2026-08-25 13:39:09 +08:00
if (diagnosisCodes.present) {
newDrug.applicableDiagnosisCodes = diagnosisCodes.value;
2026-08-06 16:32:57 +08:00
}
2026-08-12 15:20:58 +08:00
if (!Object.prototype.hasOwnProperty.call(newDrug, "antibiotic_level")) {
newDrug.antibiotic_level = 0;
}
if (!Object.prototype.hasOwnProperty.call(newDrug, "tumor_use")) {
newDrug.tumor_use = 0;
}
2026-07-27 11:28:33 +08:00
newDrug.createTime = Date.now();
const res = await db.collection("drug-info").insertOne(newDrug);
return { success: true, message: "新增药品成功", id: res.insertedId }
} catch (e) {
return { success: false, message: e.message || '新增药品失败' }
}
}
async function editHlwDrugInfo(ctx) {
const { id, params = {} } = ctx;
if (Object.prototype.toString.call(params) !== "[object Object]" || typeof id !== "string") {
return { success: false, message: "参数错误" }
}
try {
2026-08-24 16:41:11 +08:00
const optionLists = await getHlwDrugOptionLists(ctx.corpId);
2026-08-25 13:39:09 +08:00
const diagnosisCodes = await validateApplicableDiagnosisCodes(params, db);
const { onSale, applicableDiagnosisCodes, ...data } = params;
2026-07-30 16:49:41 +08:00
const currentDrug = await db.collection("drug-info").findOne(
{ _id: new ObjectId(id) },
{ projection: { erpId: 1, product_id: 1, product_id_str: 1 } }
);
if (!currentDrug) {
return { success: false, message: "未找到对应药品" }
}
const legacyErpId = currentDrug.product_id_str || currentDrug.product_id;
const erpId = Object.prototype.hasOwnProperty.call(data, "erpId")
? data.erpId
: (currentDrug.erpId || (legacyErpId || legacyErpId === 0 ? String(legacyErpId) : ""));
if (typeof erpId !== "string" || !erpId.trim()) {
return { success: false, message: "ERP ID不能为空" }
}
2026-07-27 11:28:33 +08:00
let updateData = {};
if (Object.keys(data).length) {
const peopleInfo = {
updater: typeof ctx.operator === "string" ? ctx.operator : "",
updaterId: typeof ctx.operatorId === "string" ? ctx.operatorId : "",
updateTime: Date.now()
}
2026-08-24 16:41:11 +08:00
const [item] = getDrugList([data], false, peopleInfo, 'hlw', optionLists);
2026-07-27 11:28:33 +08:00
const { msgs, ...drug } = item;
if (msgs.length) {
return { success: false, message: msgs.join(",") }
}
updateData = { ...drug }
}
if (typeof onSale === "boolean") {
updateData.onSale = onSale;
}
2026-08-25 13:39:09 +08:00
if (diagnosisCodes.present) {
updateData.applicableDiagnosisCodes = diagnosisCodes.value;
2026-08-06 16:32:57 +08:00
}
2026-07-27 11:28:33 +08:00
if (Object.keys(updateData).length) {
updateData.updateTime = Date.now();
const res = await db.collection("drug-info").updateOne({ _id: new ObjectId(id) }, { $set: updateData });
if (res.matchedCount === 0) {
return { success: false, message: "未找到对应药品" }
}
return { success: true, message: "更新成功" }
}
return { success: true, message: "更新成功" }
} catch (e) {
return { success: false, message: e.message }
}
}
async function setHlwDrugOnSale(ctx) {
const { ids, onSale, updaterId, updater } = ctx;
const _ids = Array.isArray(ids) ? ids.filter(i => typeof i === 'string' && i.trim()).map(i => new ObjectId(i.trim())) : [ids];
if (_ids.length == 0 || typeof onSale !== "boolean" || typeof updaterId !== "string" || typeof updater !== "string" || !updaterId.trim() || !updater.trim()) {
return { success: false, message: "参数错误" }
}
try {
const res = await db.collection("drug-info").updateMany({ _id: { $in: _ids } }, { $set: { onSale, updateTime: Date.now(), updaterId, updater } });
return { success: true, message: "更新成功", res }
} catch (e) {
return { success: false, message: e.message }
}
}
async function importHlwDrugInfo(ctx) {
const drugs = Array.isArray(ctx.drugs) ? ctx.drugs.filter(i => typeof i === 'object' && i !== null) : [];
const onSale = typeof ctx.onSale === "boolean" ? ctx.onSale : true;
if (drugs.length == 0) {
return { success: false, message: "参数错误" }
}
try {
2026-08-24 16:41:11 +08:00
const optionLists = await getHlwDrugOptionLists(ctx.corpId);
2026-07-27 11:28:33 +08:00
const peopleInfo = {
creator: typeof ctx.operator === "string" ? ctx.operator : "",
creatorId: typeof ctx.operatorId === "string" ? ctx.operatorId : "",
createTime: Date.now(),
}
2026-08-24 16:41:11 +08:00
const datalist = getDrugList(drugs, true, peopleInfo, 'hlw', optionLists);
2026-07-27 11:28:33 +08:00
const createTime = dayjs().valueOf();
const list = datalist.filter(i => i.msgs.length == 0).map(i => {
const { msgs, ...drug } = i;
drug.createTime = createTime;
drug.onSale = onSale;
return drug
});
const res = await db.collection("drug-info").insertMany(list);
if (res.insertedCount > 0) {
return { success: true, message: `成功导入${res.insertedCount}条数据` }
}
return { success: false, message: "导入失败" }
} catch (e) {
return { success: false, message: e.message }
}
}
async function getStoreSimilarDrugInfo(ctx) {
try {
const accountId = typeof ctx.accountId === "string" && ctx.accountId.trim() !== "" ? ctx.accountId.trim() : "";
const patientId = typeof ctx.patientId === "string" && ctx.patientId.trim() !== "" ? ctx.patientId.trim() : "";
const patientName = typeof ctx.patientName === "string" && ctx.patientName.trim() !== "" ? ctx.patientName.trim() : "";
const phone = typeof ctx.phone === "string" && ctx.phone.trim() !== "" ? ctx.phone.trim() : "";
const drugs = Array.isArray(ctx.drugs) ? ctx.drugs.filter(i => i && typeof i.insurance_code == 'string' && i.insurance_code.trim() !== "") : [];
const insurance_codes = drugs.map(i => i.insurance_code);
const query = { insurance_code: { $in: insurance_codes }, onSale: true };
const medicines = await db.collection("drug-info").find(query).toArray();
const lackMedicines = drugs.filter(i => !medicines.some(med => med.insurance_code === i.insurance_code));
let similarDrugs = [];
if (lackMedicines.length > 0) {
const lackMedicineRegApi = require("../lack-medicine-reg");
// 补全厂商数据:从药品库(包括已下架)中查询完整信息
const lackInsuranceCodes = lackMedicines.map(i => i.insurance_code);
const allDrugsInDb = await db.collection("drug-info").find({
insurance_code: { $in: lackInsuranceCodes }
}).toArray();
const lackDrugsWithManufacturer = lackMedicines.map(drug => {
// 尝试从数据库中找到匹配的药品信息
const dbDrug = allDrugsInDb.find(d => d.insurance_code === drug.insurance_code);
const result = {
...drug,
drugName: drug.drugName || (dbDrug ? dbDrug.name : ''),
spec: drug.spec || (dbDrug ? dbDrug.specification : ''),
manufacturer: drug.manufacturer || (dbDrug ? dbDrug.manufacturer : ''),
insurance_code: drug.insurance_code
};
return result;
});
const res = await lackMedicineRegApi({
type: "batchAddLackMedicineReg",
drugs: lackDrugsWithManufacturer,
accountId,
patientId,
patientName,
phone,
inventory: 'store',
regType: 'outOfStock',
corpId: ctx.corpId,
}, db)
const similarQuery = lackMedicines.map(i => ({
$and: [
{ onSale: true, insurance_code: new RegExp(i.insurance_code.slice(0, -5), "i") },
{ insurance_code: { $ne: i.insuranceCode } }
]
}))
similarDrugs = await db.collection("drug-info").find({ $or: similarQuery }).toArray();
}
2026-07-30 16:49:41 +08:00
return {
success: true,
message: "查询成功",
drugs: medicines,
similarDrugs: similarDrugs
}
2026-08-06 18:24:33 +08:00
} catch (e) {
2026-07-27 11:28:33 +08:00
return { success: false, message: e.message }
}
}
async function searchDrugs(ctx) {
try {
const keyword = typeof ctx.keyword === "string" ? ctx.keyword.trim() : "";
if (!keyword) {
return { success: false, message: "参数错误" }
}
const query = {
$or: [
{ name: { $regex: keyword, $options: "i" } },
{ pinyin_code: keyword },
2026-07-30 16:49:41 +08:00
{ erpId: keyword },
2026-07-27 11:28:33 +08:00
{ product_id_str: keyword },
{ barcode: keyword },
{ insurance_code: keyword }
]
}
const list = await db.collection("drug-info").find(query, { projection: { _id: 1, name: 1, specification: 1, manufacturer: 1, insurance_code: 1 } }).limit(30).toArray();
return { success: true, message: "查询成功", list }
} catch (e) {
return { success: false, message: e.message }
}
2026-07-30 16:49:41 +08:00
}
2026-08-06 18:24:33 +08:00
async function getDrugMatchedDisease(ctx) {
try {
const drugIds = Array.isArray(ctx.drugIds) ? ctx.drugIds.filter(i => typeof i === 'string' && ObjectId.isValid(i)) : [];
if (drugIds.length === 0) {
return { success: false, message: "参数错误" }
}
2026-08-25 13:39:09 +08:00
const list = await db.collection("drug-info").find({ _id: { $in: drugIds.map(i => new ObjectId(i)) } }, { projection: { _id: 1, applicableDiagnosisCodes: 1 } }).toArray();
const codes = [];
2026-08-06 18:24:33 +08:00
list.forEach(i => {
2026-08-25 13:39:09 +08:00
if (i && Array.isArray(i.applicableDiagnosisCodes)) {
codes.push(...i.applicableDiagnosisCodes.filter(code => typeof code === 'string' && code.trim()).map(code => code.trim()));
2026-08-06 18:24:33 +08:00
}
})
2026-08-25 13:39:09 +08:00
const uniqueCodes = [...new Set(codes)];
if (uniqueCodes.length === 0) {
2026-08-06 18:24:33 +08:00
return { success: true, message: "查询成功", list: [] }
}
2026-08-25 13:39:09 +08:00
const diseases = await db.collection("hlw-diagnosis").find({ code: { $in: uniqueCodes } }, { projection: { _id: 1, code: 1, name: 1 } }).toArray();
const diseaseMap = new Map(diseases.map(item => [item.code, item.name]));
const names = uniqueCodes.map(code => diseaseMap.get(code)).filter(name => typeof name === 'string' && name.trim());
return { success: true, message: "查询成功", list: [...new Set(names)] }
2026-08-06 18:24:33 +08:00
} catch (e) {
return { success: false, message: e.message }
}
2026-08-12 15:20:58 +08:00
}