/** * 线上购药药品库 online-drug-info * 与互联网医院药品库(drug-info)字段、功能保持一致,但使用独立的集合 */ const dayjs = require("dayjs"); const { ObjectId } = require("mongodb"); const { getDrugList } = require("../drug-info/verify"); const validator = require("../../utils/validator"); exports.main = async (item, db) => { switch (item.type) { // 供患者/医生侧检索使用的简单查询(已在线使用,保留) case "getOnlineDrugList": return await getOnlineDrugList(item, db); case "getOnlineSimilarDrugInfo": return await getOnlineSimilarDrugInfo(item, db); // 供后台管理使用的完整管理接口 case "getOnlineDrugInfo": return await getOnlineDrugInfo(item, db); case "addOnlineDrugInfo": return await addOnlineDrugInfo(item, db); case "editOnlineDrugInfo": return await editOnlineDrugInfo(item, db); case "setOnlineDrugOnSale": return await setOnlineDrugOnSale(item, db); case "importOnlineDrugInfo": return await importOnlineDrugInfo(item, db); case "checkOnlineDrugInfoStock": return await checkOnlineDrugInfoStock(item, db); case "getOnlineDrugRepeatTags": return await getOnlineDrugRepeatTags(item, db); default: return { success: false, message: "未找到接口" }; } }; // 患者/医生端使用:关键字+在售过滤 async function getOnlineDrugList(ctx, db) { try { const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1; const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10; const keyword = typeof ctx.keyword === "string" ? ctx.keyword.trim() : ""; const query = {}; const onSale = typeof ctx.onSale === "boolean" ? ctx.onSale : true; query.onSale = onSale; let fuzzyQuery = null; if (keyword) { fuzzyQuery = { $or: [ { name: new RegExp(keyword.trim(), "i") }, { generic_name: new RegExp(keyword.trim(), "i") }, { barcode: keyword.trim() }, { pinyin_code: new RegExp(keyword.trim(), "i") }, { product_id_str: keyword.trim() }, ], }; } if (Array.isArray(ctx.ids)) { const ids = ctx.ids .map((i) => typeof i === "string" && i.trim() ? new ObjectId(i.trim()) : null ) .filter((i) => !!i); if (ids.length) { query._id = { $in: ids }; } } const applyQuery = fuzzyQuery ? { $and: [query, fuzzyQuery] } : query; const [total, list] = await Promise.all([ db.collection("online-drug-info").countDocuments(applyQuery), db .collection("online-drug-info") .find(applyQuery) .skip((page - 1) * pageSize) .limit(pageSize) .toArray(), ]); return { success: true, message: "查询成功", data: list, total, pages: Math.ceil(total / pageSize), }; } catch (e) { return { success: false, message: e.message }; } } // 后台管理:分页查询(字段与 getHlwDrugInfo 一致) async function getOnlineDrugInfo(ctx, db) { try { const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1; const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10; const query = {}; 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; } if (typeof ctx.productId === "string" && ctx.productId.trim()) { query.product_id_str = ctx.productId.trim(); } 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(); } if (typeof ctx.hisDrugCode === "string" && ctx.hisDrugCode.trim()) { query.his_drug_code = ctx.hisDrugCode.trim(); } if (typeof ctx.applyPeople === "string" && ctx.applyPeople.trim()) { query.apply_people = ctx.applyPeople.trim(); } const res = await db .collection("online-drug-info") .find(query) .sort({ onSale: -1, createTime: -1 }) .skip((page - 1) * pageSize) .limit(pageSize) .toArray(); const total = await db .collection("online-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 addOnlineDrugInfo(ctx, db) { const { params = {} } = ctx; if (Object.prototype.toString.call(params) !== "[object Object]") { return { success: false, message: "参数错误" }; } try { const peopleInfo = { creator: typeof ctx.operator === "string" ? ctx.operator : "", creatorId: typeof ctx.operatorId === "string" ? ctx.operatorId : "", createTime: Date.now(), }; const { onSale, ...data } = params; let newDrug = {}; if (Object.keys(data).length) { if (!data.his_drug_code || !String(data.his_drug_code).trim()) { return { success: false, message: "ERP编码不能为空" }; } if (data.his_drug_code) { const count = await db.collection("online-drug-info").countDocuments({ his_drug_code: data.his_drug_code }); if (count > 0) { return { success: false, message: "ERP编码已存在" }; } } const [item] = getDrugList([data], true, peopleInfo); const { msgs, ...drug } = item; if (msgs.length) { return { success: false, message: msgs.join(",") }; } newDrug = { ...drug }; } if (typeof onSale === "boolean") { newDrug.onSale = onSale; } newDrug.createTime = Date.now(); const res = await db .collection("online-drug-info") .insertOne(newDrug); return { success: true, message: "新增药品成功", id: res.insertedId, }; } catch (e) { return { success: false, message: e.message || "新增药品失败", }; } } // 编辑线上药品 async function editOnlineDrugInfo(ctx, db) { const { id, params = {} } = ctx; if ( Object.prototype.toString.call(params) !== "[object Object]" || typeof id !== "string" ) { return { success: false, message: "参数错误" }; } try { const { onSale, ...data } = params; let updateData = {}; if (Object.keys(data).length) { if ("his_drug_code" in data && !String(data.his_drug_code).trim()) { return { success: false, message: "ERP编码不能为空" }; } if (data.his_drug_code) { const count = await db.collection("online-drug-info").countDocuments({ his_drug_code: data.his_drug_code, _id: { $ne: new ObjectId(id) } }); if (count > 0) { return { success: false, message: "ERP编码已存在" }; } } const peopleInfo = { updater: typeof ctx.operator === "string" ? ctx.operator : "", updaterId: typeof ctx.operatorId === "string" ? ctx.operatorId : "", updateTime: Date.now(), }; const [item] = getDrugList([data], false, peopleInfo); const { msgs, ...drug } = item; if (msgs.length) { return { success: false, message: msgs.join(",") }; } updateData = { ...drug }; } if (typeof onSale === "boolean") { updateData.onSale = onSale; } if (Object.keys(updateData).length) { updateData.updateTime = Date.now(); const res = await db .collection("online-drug-info") .updateOne( { _id: new ObjectId(id) }, { $set: updateData } ); if (res.matchedCount === 0) { return { success: false, message: "未找到对应药品" }; } } return { success: true, message: "更新成功" }; } catch (e) { console.log("editOnlineDrugInfo error", e); return { success: false, message: e.message }; } } // 批量上/下架 async function setOnlineDrugOnSale(ctx, db) { 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("online-drug-info") .updateMany( { _id: { $in: _ids } }, { $set: { onSale, updateTime: Date.now(), updaterId, updater, }, } ); return { success: true, message: "更新成功", res }; } catch (e) { console.log("setOnlineDrugOnSale error", e); return { success: false, message: e.message }; } } // 批量导入(用于程序接口调用,CSV 上传走单独 upload-online-drug-csv) async function importOnlineDrugInfo(ctx, db) { 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 { const peopleInfo = { creator: typeof ctx.operator === "string" ? ctx.operator : "", creatorId: typeof ctx.operatorId === "string" ? ctx.operatorId : "", createTime: Date.now(), }; const datalist = getDrugList(drugs, true, peopleInfo); datalist.forEach((i) => { if (!i.his_drug_code || !String(i.his_drug_code).trim()) { i.msgs.push("ERP编码不能为空"); } }); 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; }); if (!list.length) { return { success: false, message: "导入失败" }; } const res = await db .collection("online-drug-info") .insertMany(list); if (res.insertedCount > 0) { return { success: true, message: `成功导入${res.insertedCount}条数据`, }; } return { success: false, message: "导入失败" }; } catch (e) { console.log("importOnlineDrugInfo error", e); return { success: false, message: e.message }; } } async function getOnlineSimilarDrugInfo(ctx, db) { 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("online-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("online-drug-info").find({ insurance_code: { $in: lackInsuranceCodes } }).toArray(); const lackDrugsWithManufacturer = lackMedicines.map(drug => { // 尝试从数据库中找到匹配的药品信息 const dbDrug = allDrugsInDb.find(d => d.insurance_code === drug.insurance_code); return { ...drug, drugName: drug.drugName || (dbDrug ? dbDrug.name : ''), spec: drug.spec || (dbDrug ? dbDrug.specification : ''), manufacturer: drug.manufacturer || (dbDrug ? dbDrug.manufacturer : ''), insurance_code: drug.insurance_code }; }); const res = await lackMedicineRegApi({ type: "batchAddLackMedicineReg", drugs: lackDrugsWithManufacturer, accountId, patientId, patientName, phone, inventory: 'online', 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("online-drug-info").find({ $or: similarQuery }).toArray(); } return { success: true, message: "查询成功", drugs: medicines, similarDrugs } } catch (e) { return { success: false, message: e.message } } } async function checkOnlineDrugInfoStock(ctx, db) { try { const accountId = typeof ctx.accountId === 'string' ? ctx.accountId.trim() : ''; const patientId = typeof ctx.patientId === 'string' ? ctx.patientId.trim() : ''; const patientName = typeof ctx.patientName === 'string' ? ctx.patientName.trim() : ''; const phone = typeof ctx.phone === 'string' ? ctx.phone.trim() : ''; const drugs = Array.isArray(ctx.drugs) ? ctx.drugs.map(i => ({ insurance_code: i && typeof i.insurance_code === 'string' ? i.insurance_code.trim() : '', num: i && Number(i.num) > 0 && Number.isInteger(Number(i.num)) ? Number(i.num) : 0, })) : []; const areaCode = typeof ctx.areaCode === 'string' ? ctx.areaCode.trim() : ''; if (accountId.length === 0) { return { success: false, message: "账号id不能为空" } } if (accountId.length > 50) { return { success: false, message: "账号id不能超过50个字" } } if (areaCode.length === 0) { return { success: false, message: "地区编码不能为空" } } if (patientId.length > 50) { return { success: false, message: "患者id不能超过50个字" } } if (patientName.length === 0) { return { success: false, message: "患者姓名不能为空" } } if (patientName.length > 30) { return { success: false, message: "患者姓名不能超过30个字" } } // 手机号验证:如果提供了手机号则必须格式正确 if (phone.length > 0 && !validator.isMobile(phone)) { return { success: false, message: "患者手机号格式不正确" } } if (drugs.length === 0 || drugs.length > 5) { return { success: false, message: "药品数量不能为空且不能超过5个" } } if (drugs.some(i => !(i.insurance_code && i.num))) { return { success: false, message: "药品信息不完整" } } const list = await db.collection("online-drug-info").find({ insurance_code: { $in: drugs.map(i => i.insurance_code) } }, { projection: { name: 1, specification: 1, manufacturer: 1, insurance_code: 1 } }).toArray(); const arr = drugs.map(i => { const drug = list.find(m => m.insurance_code === i.insurance_code); return { drug, num: i.num, insurance_code: i.insurance_code } }) const unvalid = arr.find(i => !i.drug); if (unvalid) { return { success: false, message: `药品${unvalid.insurance_code}不存在` } } const zytHis = require("../zyt-his") const res = await zytHis({ type: 'getHisDrugInfo', areaCode, insuranceCodes: drugs.map(i => i.insurance_code) }); if (!res || !res.success) { return { success: false, message: res && res.message ? res.message : '查询his库存信息失败' } } const hisDrugs = Array.isArray(res.data) ? res.data : []; const lackMedicines = []; const result = []; arr.forEach(i => { const hisDrug = hisDrugs.find(m => m.gjbm === i.insurance_code); const stock = hisDrug && Number(hisDrug.stock_amount) > 0 ? Number(hisDrug.stock_amount) : 0; const price = hisDrug && Number(hisDrug.pack_retprice) > 0 ? Number(hisDrug.pack_retprice) : undefined; if (stock < i.num) { lackMedicines.push({ drugName: i.drug.name, spec: i.drug.specification, manufacturer: i.drug.manufacturer, insuranceCode: i.drug.insurance_code }) } result.push({ insuranceCode: i.insurance_code, stock, price }) }) if (lackMedicines.length > 0) { const lackMedicineRegApi = require("../lack-medicine-reg"); lackMedicineRegApi({ type: "batchAddLackMedicineReg", drugs: lackMedicines, accountId, patientId, patientName, phone, inventory: 'online', regType: 'lowStock', corpId: ctx.corpId, }, db) } return { success: true, message: '查询成功', data: result } } catch (e) { return { success: false, message: e.message } } } async function getOnlineDrugRepeatTags(ctx, db) { try { const pipeline = [ { $match: { repeatTag: { $type: "array", $ne: [] } } }, { $unwind: "$repeatTag" }, { $match: { repeatTag: { $type: "number", $gt: 0 } } }, { $group: { _id: "$repeatTag" } }, { $sort: { _id: 1 } }, { $group: { _id: null, uniqueTags: { $push: "$_id" } } }, { $project: { _id: 0, uniqueTags: 1 } } ]; const result = await db.collection("online-drug-info").aggregate(pipeline).toArray(); const uniqueTags = result.length > 0 ? result[0].uniqueTags : []; return { success: true, message: '查询成功', data: uniqueTags } } catch (e) { return { success: false, message: e.message } } }