耗材使用申领 — 业务流程说明

独立模块手册 · 来源老系统 D:\workcache\SuppliesManagement

文档:IMP_BoneInspectionSelect/耗材使用申领业务流程说明.html

说明:老库为 SQL Server;文中表名/字段已按新库下划线命名改写为 MySQL 等价写法。

目录

  1. 模块概述
  2. 关键路径
  3. 核心表与视图
  4. 状态码
  5. 业务流程
  6. 可申领耗材列表查询
  7. 选择耗材后校验
  8. 关键操作与 MySQL
  9. 新系统对照

1. 模块概述

老菜单:耗材使用申请 科室向院内库房申领已有库存耗材,库房执行出库。

2. 关键路径

3. 核心表与视图

表 / 视图角色
supplies_warehouse_use_request申领主单(老:Supplies_PurchaseRequest
supplies_warehouse_use_request_detail申领明细行(老:Supplies_InWarehouse
supplies_inwarehouse_out_record出库执行记录
common_entity_update_record操作日志
common_cancel_request_record撤单记录
v_supplies_request_form_detail出库明细视图
v_supplies_request_plan_detail申领明细复合视图
supplies_specification_info耗材规格档案(老:Supplies_Warhouse,可申领候选主数据)
Common_WarhouseOfBookaccount库房账簿参数(院区申领 / 停用不可领 / 锁定库存等)
Common_WarhouseInfo库房信息(与账簿关联)
Common_NormalSuppliesStock普耗库存(老路径 GetNormalSuppliesStock 用)

主单关键字段

字段说明
id主键(雪花)
purchase_request_num申领单号(年 + 6 位流水)
request_department / request_man申请科室 / 申请人
request_submit0 未提交 / 1 已提交
request_state流程状态(见第 4 节)
request_reason0 普通 / 1 备货 / 4 临采 / 6 调拨 / 8 补货等
type常用 1=普通耗材
hos_area / warhouse_department院区 / 目标库房
out_exec_man / out_exec_time出库执行人 / 时间

4. 状态码

4.1 request_state

含义
0待提交
1已提交 / 待库房发放
2部分业务扩展态(如补货通知)
4已出库执行
5审批中(高值等配置开启时)
9已删除 / 已撤单

4.2 明细 state / check_state / exec_state

字段常用值
state0 有效;1/2 部分出库;3 全部出库;9 删除
check_state0 待处理;1 已提交;2 已审核;3 已撤
exec_state0 待提交;1 提交后待执行(及其他扩展态)

5. 业务流程

科室【耗材使用申请】FrmNormalSuppliesRequest ├─ 列表 GetList(Tab:待提交 / 申领待审核 / 执行待审核 / 已结束 / 全部) ├─ 新开 AddRequest → request_state=0, request_submit=0 ├─ 加明细 supplies_warehouse_use_request_detail.Add ├─ 提交 AddSuppliesRequest → request_state=1, request_submit=1 │ (可按账簿/库房级别/院区拆多张主单;明细 check_state=1, exec_state=1) ├─ 删除 Delete → request_state=9,明细 state=9 └─ 撤销 CancelPurchasePlan → 回到 request_state=0 │ 库房【耗材出库】NormalSuppliesOutForm ├─ 出库 OutSupplies → request_state=4 + OutRecord └─ 撤单 UndoRequestForm → request_state=9 + CancelRecord

列表单据状态过滤(对齐 FrmNormalSuppliesRequest)

单据状态条件
待提交request_state = 0
申领待审核id in (select purchase_request_id from supplies_warehouse_use_request_detail where check_state=1 and exec_state=1)request_state = 1
执行待审核同上明细条件,且 request_state = 4
已结束id in (select purchase_request_id from supplies_warehouse_use_request_detail where exec_state <> 1 and exec_state <> 0)

6. 可申领耗材列表查询

入口:FrmNormalSuppliesRequest.InitialLookUpList → 内存表 SearchDataSource → 弹窗 FrmCommonSearchControal / FrmFastSearch。 DAL:Supplies_Warhouse.GetSearchData / GetNormalSuppliesStock / GetMedicalPackageListEx

当前主路径是查耗材档案 Supplies_Warhouse(新库 supplies_specification_info)。 按库存过滤的 GetNormalSuppliesStock 在申领窗体中已被注释,但仍保留完整逻辑,迁移时需知悉。

6.1 按申请原因 / 借用标志分支

条件老方法过滤要点
borrow_flag ≠ 0(借用) GetMedicalPackageListEx 医用包:use_status=0entity_type=4
request_reason = 2(补货类) GetSearchData history_flag=0use_status=0
request_reason = 4(临采) GetSearchData + 临采子查询 仅当前医生临采计划中仍有剩余额度的编码
request_reason = 8 GetSearchData orthope_flag=0history_flag=0use_status=0
其它(如日常 0 GetNormalSuppliesStock(已注释) 按库房账簿参数拼库存,且 库存−在途申领 > 0

6.2 主路径:档案查询 GetSearchData(MySQL)

老表 Supplies_Warhouse → 新表 supplies_specification_infoHistoryFlag≈历史版本标记,UseStateuse_status(0 启用 / 1 停用)。

MySQL 通用可申领档案(reason=2)
SELECT
  w.id,
  w.supplies_code,
  w.supplies_name,
  w.supplies_specs,
  w.supplies_model,
  w.supplies_made_in,
  w.supplies_brand,
  w.account_book_id AS account_book,
  w.new_price AS purchase_price,
  w.manufacturer_id,
  w.manage_department_id,
  w.data_version,
  IFNULL(w.use_status, '0') AS use_status,
  (SELECT item_text FROM v_sysdict
    WHERE item_value = w.supplies_unit AND dict_code = 'sys_unit' LIMIT 1) AS unit,
  (SELECT manager FROM common_warhouseinfo
    WHERE IFNULL(warhouse_level, 0) = 1
      AND account_book_id = w.account_book_id LIMIT 1) AS manage_department_id_wh,
  1 AS warhouse_level,
  0 AS kcsl
FROM supplies_specification_info w
WHERE IFNULL(w.del_flag, '0') = '0'
  AND IFNULL(w.history_flag, 0) = 0          -- 老:HistoryFlag = 0
  AND IFNULL(w.use_status, '0') = '0';       -- 老:UseState = 0
MySQL reason=8(排除骨科标记)
SELECT ... -- 字段同 6.2
FROM supplies_specification_info w
WHERE IFNULL(w.del_flag, '0') = '0'
  AND IFNULL(w.orthope_flag, 0) = 0
  AND IFNULL(w.history_flag, 0) = 0
  AND IFNULL(w.use_status, '0') = '0'
ORDER BY w.supplies_name, w.supplies_model, w.supplies_specs;
MySQL reason=4(临采:编码落在剩余可采计划内)
-- 1) 临采计划候选(对应 GetTempPurchaseDt)
SELECT b.id, ...
FROM common_tem_purchase_plan_detail a
LEFT JOIN common_tem_purchase_plan b ON a.request_id = b.id
LEFT JOIN common_tem_purchase_count_of_user c ON c.request_id = b.id
WHERE b.state = '9'
  AND c.request_doctor = :userId
  AND (c.request_count - c.purchased_count - c.purchasing_count) > 0;

-- 2) 可申领档案:编码属于选中临采单剩余明细
SELECT ...
FROM supplies_specification_info w
WHERE IFNULL(w.del_flag, '0') = '0'
  AND IFNULL(w.history_flag, 0) = 0
  AND w.supplies_code IN (
    SELECT a.supp_num
    FROM common_tem_purchase_plan_detail a
    LEFT JOIN common_tem_purchase_plan b ON a.request_id = b.id
    WHERE b.state = '9'
      AND b.id IN (
        SELECT request_id FROM common_tem_purchase_count_of_user
        WHERE (request_count - purchased_count - purchasing_count) > 0
          AND request_doctor = :userId
          AND id = :tmpPurchaseFormId
      )
  );
MySQL 借用医用包 GetMedicalPackageListEx
SELECT
  w.supplies_name, w.supplies_code, w.id,
  IFNULL(w.new_price, 0) AS purchase_price,
  w.supplies_specs, w.entity_type,
  0 AS kcsl
FROM supplies_specification_info w
WHERE IFNULL(w.use_status, '0') = '0'
  AND IFNULL(w.entity_type, 0) = 4;   -- 医用包

6.3 注释路径:按库存 GetNormalSuppliesStock(MySQL)

申领窗体里原调用已注释,但 DAL 仍完整。先读库房账簿参数,再按账簿拼库存 UNION。

MySQL ① 库房账簿参数(本段即你问过的那段)
SELECT
  IFNULL(a.request_by_hos_area, 0) AS request_by_hos_area,  -- 按院区申请
  a.zero_can_request,                                       -- 零库存可领用
  a.stop_un_request,                                        -- 停用不可领用
  a.account_book_id,
  a.request_lock_stock,                                     -- 申请即锁定库存
  b.warhouse_level
FROM common_warhouseofbookaccount a
LEFT JOIN common_warhouseinfo b ON a.warhouse_info_id = b.id;
MySQL ② 每个账簿拼一段库存(循环 UNION ALL)
SELECT
  a.account_book AS account_book_id,
  w.supplies_name,
  w.supplies_specs,
  w.supplies_code AS supplies_num,
  w.supplies_model,
  a.purchase_price,
  SUM(a.stock_count) AS kcsl,
  a.department_id AS manage_department_id,
  a.warhouse_level,
  a.hos_area,
  -- RequestLockStock=1 时才算在途申领量,否则恒为 0
  IFNULL((
    SELECT SUM(d.supplies_count)
    FROM v_supplies_request_count_detail d
    WHERE d.state <> 9
      AND d.request_reason IN (0, 9)
      AND d.exec_state = 1
      AND d.hos_area = a.hos_area
      AND d.supp_num = a.supp_num
  ), 0) AS requesting_count
FROM common_normal_supplies_stock a
LEFT JOIN supplies_specification_info w
  ON a.supp_num = w.supplies_code AND IFNULL(w.history_flag, 0) = 0
WHERE IFNULL(a.high_supplies_flag, 0) = 0
  AND a.account_book = :accountBookId
  AND a.warhouse_level = :warhouseLevel
  -- RequestByHosArea=1 时追加:
  -- AND a.hos_area = :hosArea
GROUP BY
  w.supplies_code, w.supplies_name, w.supplies_specs, w.supplies_model,
  a.purchase_price, a.account_book, a.department_id, a.warhouse_level, a.hos_area, a.supp_num;
MySQL ③ 外层过滤可用量
SELECT *
FROM (
  -- 上面各账簿 UNION ALL 结果 + 高值柜外库存段 ...
) t
WHERE (IFNULL(t.kcsl, 0) - IFNULL(t.requesting_count, 0)) > 0
ORDER BY t.supplies_name, t.supplies_specs, t.supplies_model;

6.4 新系统当前实现

前端 useRequest.api.tsGET /supplies/suppliesSpecificationInfo/list, 固定传 useStatus: '0'(启用),尚未按 request_reason / 库存账簿参数分支。

7. 选择耗材后校验

入口:FrmNormalSuppliesRequest.ShowEditor 选中行之后。 先取当前版本档案,再按账簿参数与业务规则拦截;通过后才 InitialDetailCtrlInfo 写入明细。

7.1 校验顺序(老系统)

  1. 取档案:SuppliesNum = :code AND HistoryFlag = 0(无记录则直接 return)
  2. 停用不可申领:档案 UseState=1 且该账簿 StopUnRequest=1 → 提示「已停用不可申领」
  3. 未接收配送不可再申领:账簿 CanRequestHaveNoRecvSupplies=1 且存储过程判定科室有未接收配送 → 拦截
  4. 二级库以耗代领:开启二级库逻辑且 HisAccountFlagForRequestFlag=1 → 不可主动申领
  5. 明细去重:同一申领单已存在相同 SuppliesNum → 「请修改数量」
  6. 通过后写入明细;日常/调拨可用库存取 KCSL - RequestingCount

7.2 相关查询(MySQL)

MySQL 取当前版本档案
SELECT *
FROM supplies_specification_info
WHERE supplies_code = :suppliesCode
  AND IFNULL(history_flag, 0) = 0
  AND IFNULL(del_flag, '0') = '0'
LIMIT 1;
MySQL 窗体初始化:加载账簿停用策略(AccountBookDataSource)
SELECT
  account_book_id AS account_book,
  stop_un_request
FROM common_warhouseofbookaccount;
-- 老:GetWarhosueAccountBookList
MySQL 停用不可申领判定
-- 伪逻辑
-- IF archive.use_status = '1'
--    AND EXISTS (
SELECT 1
FROM common_warhouseofbookaccount a
WHERE a.account_book_id = :accountBookId
  AND IFNULL(a.stop_un_request, '0') = '1'
-- ) THEN 拒绝:已停用不可申领
MySQL 取账簿申领相关参数(GetAccountbookModelOfWarhouseEx)
SELECT
  a.account_book_id,
  a.type,
  a.request_lock_stock,
  a.request_by_hos_area,
  a.zero_can_request,
  a.stop_un_request,
  a.can_request_have_no_recv_supplies,   -- 有未接收配送时是否禁止再申领
  a.dpt_accept_flag,
  a.logic_flag
FROM common_warhouseofbookaccount a
LEFT JOIN v_sysdict d
  ON CAST(a.account_book_id AS CHAR) = d.item_value
 AND d.dict_code = 'account_book'
WHERE a.account_book_id = :accountBookId
LIMIT 1;
MySQL 未接收配送校验(老:存储过程 Sp_NormalSuppliesHaveNoRecvsupplies)
-- 老代码调用:HaveNoRecvSupplies(accountBook, sectionId)
-- 输出 ResultCode='1' 表示「有配送未接收」
-- MySQL 等价示意(具体以库内过程/配送表为准,可迁为函数或查询):
SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS has_no_recv
FROM common_supplies_deliver_record r   -- 表名按实际配送/接收表对齐
WHERE r.account_book = :accountBookId
  AND r.request_department = :deptOrgCode
  AND IFNULL(r.recv_flag, '0') = '0'    -- 未接收
  AND IFNULL(r.state, '0') <> '9';

-- 当 can_request_have_no_recv_supplies = '1' 且 has_no_recv = 1
-- → 提示:有配送没有接收的耗材,接收之前无法申请新耗材
MySQL 明细去重
SELECT COUNT(1)
FROM supplies_warehouse_use_request_detail d
WHERE d.purchase_request_id = :headerId
  AND IFNULL(d.state, '0') <> '9'
  AND (
    d.supp_num = :suppliesCode
    OR d.supplies_entity_id = :entityId
  );
-- COUNT > 0 → 申请单中已存在该耗材,请修改数量
MySQL 可用库存(日常 reason=0 / 调拨 reason=6)
-- 选中行展示/写入时:
-- available = kcsl - requesting_count
-- requesting_count 来自账簿 RequestLockStock=1 时的在途申领汇总(见 6.3)
SELECT
  IFNULL(kcsl, 0) - IFNULL(requesting_count, 0) AS available_qty
FROM (
  -- 库存查询结果行
) t;

7.3 校验一览

校验项条件提示
档案存在当前版本档案查无直接中断
停用不可领use_status=1 且账簿 stop_un_request=1已停用不可申领
未接收配送can_request_have_no_recv_supplies=1 且有未接收请先接收耗材
以耗代领二级库 + his_account_flag_for_request_flag=1无法主动申领
明细重复同单已有相同编码请修改数量

8. 关键操作与 MySQL

MySQL 列表 GetList
SELECT
  id AS purchase_request_id, request_department, request_time, check_time, check_man,
  arrival_time, purchase_request_num, operate_man, request_man, request_submit,
  create_time, request_reason, request_state, warhouse_department,
  (SELECT realname FROM sys_user WHERE username = request_man LIMIT 1) AS request_man_name,
  `type`,
  (SELECT depart_name FROM sys_depart WHERE org_code = request_department LIMIT 1) AS sqks,
  remark, account_book, IFNULL(borrow_flag, 0) AS borrow_flag
FROM supplies_warehouse_use_request
WHERE request_department = :dept
  AND request_state = :state;
MySQL 新开空白单 AddRequest
INSERT INTO supplies_warehouse_use_request (
  request_department, request_time, operate_man, request_man, request_submit, create_time,
  request_reason, request_state, `type`, id, hos_area, request_out_type, ...
) VALUES (
  :dept, NOW(), :operateMan, :requestMan, '0', NOW(),
  :reason, 0, :type, :snowId, :hosArea, :outType, ...
);
MySQL 添加明细
INSERT INTO supplies_warehouse_use_request_detail (
  purchase_request_id, supplies_count, supplies_entity_id, create_user, create_time,
  state, request_price, id, supp_num, supp_out_count, manager_department_id, ...
) VALUES (
  :headerId, :qty, :entityId, :user, NOW(),
  0, :price, :snowId, :suppNum, 0, :managerDept, ...
);

INSERT INTO common_entity_update_record (table_name, record_id, operate_type, operate_user)
VALUES ('supplies_warehouse_use_request_detail', :snowId, 1, :user);
MySQL 提交 AddSuppliesRequest(摘要)
SELECT MAX(lsh) FROM supplies_warehouse_use_request WHERE YEAR(request_time) = YEAR(NOW());

DELETE FROM supplies_warehouse_use_request WHERE id = :draftId;

INSERT INTO supplies_warehouse_use_request (
  request_department, request_time, check_time, check_man, purchase_request_num,
  request_man, request_submit, create_time, request_reason, request_state, `type`,
  id, lsh, account_book, hos_area, warhouse_department, ...
) VALUES (
  :dept, NOW(), NOW(), :checkMan, CONCAT(YEAR(NOW()), LPAD(:lsh, 6, '0')),
  :man, '1', NOW(), :reason, 1, 1,
  :newId, :lsh, :book, :hosArea, :whDept, ...
);

UPDATE supplies_warehouse_use_request_detail
SET supp_request_count = :qty, supplies_count = :qty, state = 0,
    purchase_request_id = :newId, check_state = 1, exec_state = 1
WHERE id = :detailId;
MySQL 删除 / 撤销 / 出库 / 撤单
-- 软删主单
UPDATE supplies_warehouse_use_request_detail SET state=9, del_user=:u, del_time=NOW() WHERE purchase_request_id=:id;
UPDATE supplies_warehouse_use_request SET request_state=9, del_user=:u, del_time=NOW() WHERE id=:id;

-- 科室撤销提交(仅 request_state=1)
UPDATE supplies_warehouse_use_request SET request_submit=0, request_state=0 WHERE id=:id;
UPDATE supplies_warehouse_use_request_detail SET exec_state=0 WHERE purchase_request_id=:id;

-- 库房出库
UPDATE supplies_warehouse_use_request
SET request_state=4, out_exec_man=:u, out_exec_time=NOW() WHERE id=:id;
UPDATE supplies_warehouse_use_request_detail
SET state = CASE WHEN supplies_count <= :outQty THEN 3 WHEN :outQty = 0 THEN 1 ELSE 2 END,
    supp_out_count = :outQty
WHERE id = :detailId;
INSERT INTO supplies_inwarehouse_out_record
  (id, supplies_id, out_count, state, supp_num, entity_id, hos_area, purchase_price)
VALUES (:snowId, :detailId, :outQty, 0, :suppNum, :entityId, :hosArea, :price);

-- 库房撤单
UPDATE supplies_warehouse_use_request SET request_state=9, check_time=NOW(), check_man=:u WHERE id=:id;
INSERT INTO common_cancel_request_record (request_id, cancel_user, cancel_time, cancel_remark, `type`)
VALUES (:id, :u, NOW(), :remark, :type);
UPDATE supplies_warehouse_use_request_detail SET exec_state=0 WHERE purchase_request_id=:id AND state <> 9;

9. 新系统对照

老系统新系统(Platform)
Supplies_PurchaseRequestsupplies_warehouse_use_request
Supplies_InWarehousesupplies_warehouse_use_request_detail
Supplies_Warhouse(可申领档案)supplies_specification_info
GetSearchData / UseState=0GET /supplies/suppliesSpecificationInfo/list?useStatus=0
GetNormalSuppliesStock(已注释)尚未迁移;依赖 Common_WarhouseOfBookaccount + 库存表
选中后校验(停用/未接收/去重)前端添加耗材弹窗尚未完整复刻,待补
AddRequestPOST /useRequest/addPurchaseRequest
AddSuppliesRequest(提交)POST /useRequest/submitPurchaseRequest
DeletePOST /useRequest/deletePurchaseRequest
CancelPurchasePlan(撤销提交)POST /useRequest/revokePurchaseRequest
OutSupplies库房出库服务(另模块)
前端views/supplies/purchaseRequest/useRequest/