|
|
#!/usr/bin/env python
|
|
|
# encoding: utf-8
|
|
|
"""
|
|
|
@author: tx
|
|
|
@file: drug.py
|
|
|
@time: 2023/5/11 11:04
|
|
|
@desc: 药剂领用归还
|
|
|
"""
|
|
|
import asyncio
|
|
|
import datetime
|
|
|
from decimal import Decimal
|
|
|
|
|
|
from fastapi import APIRouter, Request, Depends
|
|
|
from fastapi.encoders import jsonable_encoder
|
|
|
from pydantic import BaseModel
|
|
|
from tortoise.queryset import Q, QuerySet
|
|
|
from tortoise.functions import Function
|
|
|
from pypika import CustomFunction
|
|
|
|
|
|
from conf import setting
|
|
|
from helper.drug import drugs_except_info, drugs_list_info, gram_to_milligram, milligram_to_gram, open_update_expired_at
|
|
|
from helper import respond_to, login_required
|
|
|
from models import Dictionary, DrawerBoard, Drawer, User
|
|
|
from models.drug import Drug, DrugStateEnum
|
|
|
from models.terminal import Terminal
|
|
|
from models.taboo import Taboo
|
|
|
from models.cabinet import Cabinet
|
|
|
from transfer.standard import Standard
|
|
|
from transfer.code_standard import CodeStandard
|
|
|
from helper.tool import parse_datetime
|
|
|
from helper.log import logger_wrapper
|
|
|
|
|
|
router = APIRouter(prefix='/drugs', dependencies=[Depends(login_required)])
|
|
|
return_router = APIRouter(prefix='/drugs/return',)
|
|
|
|
|
|
|
|
|
class DrugUpdateRequest(BaseModel):
|
|
|
open_date: str = "" # 开封日期
|
|
|
weight: int = 0 # 余量
|
|
|
use_weight: str | Decimal = 0.0 # 用量
|
|
|
rfid: str = ""
|
|
|
id: str = ""
|
|
|
cabinet_id: str = "" # 柜体id
|
|
|
selectDrawer_id:str = ""
|
|
|
|
|
|
|
|
|
class DrugUpdateExpired(BaseModel):
|
|
|
expired_at: str
|
|
|
rfid: str = ""
|
|
|
id: str = ""
|
|
|
|
|
|
|
|
|
class DrugRfids(BaseModel):
|
|
|
rfids: list
|
|
|
|
|
|
class DrugBackTrack(BaseModel):
|
|
|
drug_list: list[dict]
|
|
|
|
|
|
class DrugTakeOut(BaseModel):
|
|
|
terminal_id: str | None
|
|
|
page_no: int = 1
|
|
|
page_size: int = 20
|
|
|
|
|
|
|
|
|
class UpdateDictionary(BaseModel):
|
|
|
lack_stock_count: int = 0
|
|
|
expiration_alert: int = 0
|
|
|
|
|
|
|
|
|
class EmptyBottleDisposal(BaseModel):
|
|
|
rfid: str
|
|
|
weight: int | None
|
|
|
open_date: str | None
|
|
|
|
|
|
|
|
|
class JsonExtract(Function):
|
|
|
database_func=CustomFunction('JSON_EXTRACT', ['field', 'value'])
|
|
|
|
|
|
class BlinkLocation(BaseModel):
|
|
|
ip: str
|
|
|
position: list[int]
|
|
|
duration: int
|
|
|
function: int
|
|
|
|
|
|
# 查询药剂信息,
|
|
|
@router.get('/get_drug_position_info',summary='获取试剂信息')
|
|
|
async def get_drug_info(request:Request,rfid:str):
|
|
|
if len(rfid)==0:
|
|
|
return respond_to(404, desc="请传入药剂rfid")
|
|
|
drug = await Drug.get_or_none(rfid=rfid)
|
|
|
if not drug:
|
|
|
return respond_to(404, desc="药剂信息不存在")
|
|
|
drawer_obj = await Drawer.get_or_none(id=drug.drawer_id)
|
|
|
if not drawer_obj:
|
|
|
return respond_to(404, desc="药剂缺少drawer_id")
|
|
|
drawer_number = drawer_obj.line_no
|
|
|
drawer_board_obj = await DrawerBoard.filter(drawer_id =drawer_obj.id ).all()
|
|
|
if not drawer_board_obj:
|
|
|
return respond_to(404, desc="药剂绑定的层板drawer_board不存在")
|
|
|
board_addresses = []
|
|
|
for item in drawer_board_obj:
|
|
|
board_addresses.append(item.line_no)
|
|
|
res={}
|
|
|
res['drawer_number'] = drawer_number
|
|
|
res['board_addresses'] = board_addresses
|
|
|
return respond_to(200,desc="获取药剂位置信息成功",data=res)
|
|
|
|
|
|
@router.post('/empty', summary='试剂置为空瓶')
|
|
|
async def empty_bottle_disposal(request: Request, post: EmptyBottleDisposal):
|
|
|
"""
|
|
|
试剂置为空瓶
|
|
|
:param request: Request请求头信息
|
|
|
:param post: 空瓶信息的请求体
|
|
|
:return:
|
|
|
"""
|
|
|
users = request.state.users
|
|
|
standard = Standard(users)
|
|
|
rfid = post.rfid
|
|
|
drug = await Drug.get_or_none(rfid=rfid)
|
|
|
if not drug:
|
|
|
return respond_to(404, desc="药剂不存在")
|
|
|
# user_weight = post.weight
|
|
|
open_date = post.open_date
|
|
|
if open_date:
|
|
|
drug.open_date = parse_datetime(open_date, "%Y-%m-%d")
|
|
|
await drug.save()
|
|
|
await standard.empty(rfid)
|
|
|
return respond_to()
|
|
|
|
|
|
|
|
|
@router.post('/weight', summary="药剂用量或余量更新")
|
|
|
async def update(request: Request, keyword: DrugUpdateRequest):
|
|
|
"""
|
|
|
药剂用量或余量更新
|
|
|
接收id或rfid都可以更新重量
|
|
|
余量与用量二选一,只有一个有值
|
|
|
:param keyword: 包含更新信息的请求体
|
|
|
:return:
|
|
|
"""
|
|
|
print("open_date", keyword.open_date)
|
|
|
rfid = keyword.rfid if keyword.rfid else ""
|
|
|
if keyword.id:
|
|
|
drug_obj = await Drug.get_or_none(id=keyword.id).prefetch_related("template")
|
|
|
else:
|
|
|
drug_obj = await Drug.get_or_none(Q(barcode=rfid) | Q(rfid=rfid)).prefetch_related("template")
|
|
|
|
|
|
if not drug_obj:
|
|
|
return respond_to(404, desc="药剂不存在")
|
|
|
|
|
|
if keyword.weight:
|
|
|
if not drug_obj.remain_gross_weight:
|
|
|
drug_obj.remain_gross_weight = keyword.weight
|
|
|
await drug_obj.save()
|
|
|
else:
|
|
|
# 余量转用量,更新用量
|
|
|
mill_weight = drug_obj.remain_gross_weight - keyword.weight
|
|
|
await drug_obj.update_last_use_weight(weight=float(mill_weight))
|
|
|
elif keyword.use_weight:
|
|
|
mill_weight = keyword.use_weight if keyword.use_weight and keyword.use_weight != "NaN" else 0
|
|
|
await drug_obj.update_last_use_weight(weight=float(mill_weight))
|
|
|
if keyword.open_date:
|
|
|
if not drug_obj.open_date:
|
|
|
drug_obj.open_date = parse_datetime(keyword.open_date, "%Y-%m-%d")
|
|
|
template_obj = drug_obj.template
|
|
|
new_expired_at = open_update_expired_at(drug_obj, template_obj, keyword.open_date)
|
|
|
if new_expired_at:
|
|
|
drug_obj.expired_at = new_expired_at
|
|
|
await drug_obj.save()
|
|
|
# 一维条码扫码归还更新重量后直接修改药剂状态,生成流转记录
|
|
|
rfid = drug_obj.rfid
|
|
|
if len(rfid) < 16 and drug_obj.state == DrugStateEnum.OUT:
|
|
|
cabinet_id = keyword.cabinet_id if keyword.cabinet_id else request.state.client_id
|
|
|
if not cabinet_id:
|
|
|
cabinet_obj = await Cabinet.filter(terminal_id=setting.TERMINAL_ID).first()
|
|
|
else:
|
|
|
cabinet_obj = await Cabinet.get_or_none(id=cabinet_id)
|
|
|
if cabinet_obj:
|
|
|
# 位置更新
|
|
|
position_str = f"{cabinet_obj.label}"
|
|
|
drug_obj.position = position_str
|
|
|
|
|
|
drug_obj.last_return_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
open_date = drug_obj.open_date
|
|
|
if not open_date:
|
|
|
drug_obj.open_date = datetime.datetime.now()
|
|
|
drug_obj.last_return_id = request.state.current_user.id
|
|
|
drug_obj.cabinet_id = cabinet_obj.id
|
|
|
if keyword.selectDrawer_id:
|
|
|
drawer_board = await DrawerBoard.filter(id = keyword.selectDrawer_id).get_or_none()
|
|
|
if drawer_board:
|
|
|
drug_obj.drawer_id = drawer_board.drawer_id
|
|
|
drug_obj.drawer_board_id = keyword.selectDrawer_id
|
|
|
await drug_obj.save()
|
|
|
|
|
|
# 一维条码生成流转记录
|
|
|
standard = CodeStandard(request.state.users, drug_obj)
|
|
|
await standard.put_in(barcode=drug_obj.barcode if len(drug_obj.rfid) < 16 else drug_obj.rfid)
|
|
|
return respond_to(code=200, desc="更新成功")
|
|
|
return respond_to(code=200, desc="更新成功")
|
|
|
|
|
|
|
|
|
@router.post('/except', summary='RFID药剂异常信息')
|
|
|
async def index(request: DrugRfids):
|
|
|
"""
|
|
|
获取RFID药剂异常信息
|
|
|
:return:
|
|
|
"""
|
|
|
if not request.rfids:
|
|
|
return respond_to(code=200, desc="", data=[])
|
|
|
result = list()
|
|
|
drugs = await Drug.filter(rfid__in=request.rfids).prefetch_related('dictionary', 'template').all()
|
|
|
# terminal_obj = await Terminal.get(id=setting.TERMINAL_ID)
|
|
|
taboo_list = []
|
|
|
# 130个rfid,如何快速获取里面的异常标签信息
|
|
|
# 并发执行多个任务
|
|
|
tasks = [drugs_except_info(drug, "") for drug in drugs]
|
|
|
results = await asyncio.gather(*tasks)
|
|
|
for drug, data in zip(drugs, results):
|
|
|
data["rfid"] = drug.rfid
|
|
|
result.append(data)
|
|
|
# 药剂禁忌判断
|
|
|
if not drug.taboo_species:
|
|
|
continue
|
|
|
else:
|
|
|
taboo_list_str = ",".join(set(taboo_list)) if taboo_list else ""
|
|
|
trigger, taboo_desc = await Taboo.conflict(drug.taboo_species, taboo_list_str)
|
|
|
if trigger:
|
|
|
result.append({
|
|
|
"rfid": "",
|
|
|
"is_rfid_except": True,
|
|
|
"sound": True,
|
|
|
"message": taboo_desc,
|
|
|
"state": 6,
|
|
|
})
|
|
|
taboo_list.append(drug.taboo_species)
|
|
|
|
|
|
# for drug in drugs:
|
|
|
# data = await drugs_except_info(drug, "")
|
|
|
# data["rfid"] = drug.rfid
|
|
|
# result.append(data)
|
|
|
# # 药剂禁忌判断
|
|
|
# if not drug.taboo_species:
|
|
|
# continue
|
|
|
# else:
|
|
|
# taboo_list_str = ",".join(set(taboo_list)) if taboo_list else ""
|
|
|
# trigger, taboo_desc = await Taboo.conflict(drug.taboo_species, taboo_list_str)
|
|
|
# if trigger:
|
|
|
# result.append({
|
|
|
# "rfid": "",
|
|
|
# "is_rfid_except": True,
|
|
|
# "sound": True,
|
|
|
# "message": taboo_desc,
|
|
|
# "state": 6,
|
|
|
# })
|
|
|
# taboo_list.append(drug.taboo_species)
|
|
|
|
|
|
# 传入rfid与data所有rfid比较,差集就是非法标签
|
|
|
post_rfid = set(request.rfids)
|
|
|
effective_rfid = set([i["rfid"] for i in result])
|
|
|
diff_rfid = post_rfid - effective_rfid
|
|
|
if diff_rfid:
|
|
|
result.extend([{
|
|
|
"rfid": rfid,
|
|
|
"is_rfid_except": True,
|
|
|
"sound": True,
|
|
|
"message": "非法标签",
|
|
|
"state": 0,
|
|
|
} for rfid in diff_rfid])
|
|
|
return respond_to(code=200, desc="获取RFID药剂信息成功", data=result)
|
|
|
|
|
|
|
|
|
@router.post('', summary='RFID药剂详情')
|
|
|
async def index(request: DrugRfids):
|
|
|
"""
|
|
|
获取RFID药剂信息 药剂信息详情
|
|
|
:return:
|
|
|
"""
|
|
|
drugs = list()
|
|
|
for rfid in request.rfids:
|
|
|
drug_obj = await Drug.get_or_none(rfid=rfid).prefetch_related('dictionary', 'template', 'drawer_board', 'template__archive')
|
|
|
if drug_obj is None:
|
|
|
drugs.append({
|
|
|
"drugs_except_info": {
|
|
|
"sound": False,
|
|
|
"message": "非法标签",
|
|
|
"state": 0,
|
|
|
},
|
|
|
"rfid_drug": {rfid: f"[{rfid}]未知药剂"}
|
|
|
})
|
|
|
continue
|
|
|
result = jsonable_encoder(drug_obj)
|
|
|
template_obj = drug_obj.template
|
|
|
terminal_obj = await Terminal.get(id=setting.TERMINAL_ID)
|
|
|
data = await drugs_except_info(drug_obj, terminal_obj)
|
|
|
|
|
|
drug_info = await drug_obj.attribute_drug_info()
|
|
|
parse_fill_json_content = await drug_obj.parse_fill_json_content()
|
|
|
|
|
|
parse_fill_json_content.update({f'余重': f'{milligram_to_gram(drug_obj.remain_gross_weight)}'})
|
|
|
|
|
|
return_require_weigh = template_obj.archive.params.get("return_require_weigh", '')
|
|
|
|
|
|
drug_info_dict = {
|
|
|
"drugs_except_info": data,
|
|
|
"fill_json_content": parse_fill_json_content,
|
|
|
"rfid_drug": {drug_obj.rfid: ",".join(list(map(lambda x:str(x), drug_info.values())))},
|
|
|
"return_require_weigh": return_require_weigh
|
|
|
}
|
|
|
# 2000型号柜子,需要灯光指引,返回值添加灯光序号参数
|
|
|
if setting.CLIENT_NUMBER == "2000":
|
|
|
if drug_obj.drawer_board:
|
|
|
drawer_board_line_no = drug_obj.drawer_board.line_no
|
|
|
# 亮灯位置 = 层数*36+编号
|
|
|
blink_no = (drawer_board_line_no - 1) * 36 + drug_obj.hole
|
|
|
drug_info_dict.update({"blink_no": blink_no})
|
|
|
|
|
|
result.update(drug_info_dict)
|
|
|
drugs.append(result)
|
|
|
return respond_to(code=200, desc="获取RFID药剂信息成功", data=drugs)
|
|
|
|
|
|
|
|
|
@router.get('/take_out', summary='药剂领用查询')
|
|
|
async def take_out_index(request: Request, drug_name: str = '', take_out_type: int = 0, page_no: int = 1, page_size: int = 20):
|
|
|
"""
|
|
|
药剂领用列表查询
|
|
|
本终端的排前面
|
|
|
默认按照入库时间倒叙,条件查询按照有效期倒叙
|
|
|
take_out_type 本终端0 全局终端1
|
|
|
:return:
|
|
|
"""
|
|
|
terminal = await Terminal.get(id=setting.TERMINAL_ID)
|
|
|
current_user = request.state.current_user
|
|
|
order_key = "-created_at"
|
|
|
# 普通用户只能领用自己的药剂,管理员可以领取所有药剂
|
|
|
role = await current_user.role
|
|
|
if role.grade >= 50:
|
|
|
query = Drug.filter(state=DrugStateEnum.IN)
|
|
|
else:
|
|
|
query = Drug.filter(state=DrugStateEnum.IN, rfid__in=current_user.keys)
|
|
|
# 本终端的时候查看当前登录柜子的药剂, 全局终端查看大类所有柜子药剂
|
|
|
if not take_out_type:
|
|
|
query = query.filter(cabinet__terminal=terminal)
|
|
|
# 如果带辅柜则只查询选择的柜体药剂
|
|
|
if request.state and request.state.client_id:
|
|
|
query = query.filter(cabinet_id=request.state.client_id)
|
|
|
else:
|
|
|
# 全局终端 大类对应所有柜子
|
|
|
cabinet_ids = await Cabinet.filter(archive_id=request.state.archive_id).values_list('id', flat=True)
|
|
|
query = query.filter(cabinet_id__in=cabinet_ids)
|
|
|
|
|
|
if drug_name:
|
|
|
annotate = {}
|
|
|
annotate['json_batch_no'] = JsonExtract('fill_json_content', '$.cas_number')
|
|
|
query = query.annotate(**annotate).filter(
|
|
|
Q(json_batch_no__contains=drug_name) | Q(fill_json_content__filter={"seq_no": drug_name}) | Q(
|
|
|
dictionary__k1__contains=drug_name) | Q(dictionary__k2__contains=drug_name))
|
|
|
order_key = "-expired_at"
|
|
|
|
|
|
total_count = await query.count()
|
|
|
offset = (page_no - 1) * page_size
|
|
|
drugs = await query.offset(offset).order_by(order_key).limit(page_size).all()
|
|
|
|
|
|
result = await drugs_list_info(drugs)
|
|
|
return respond_to(200, data=dict(count=total_count, drugs=result))
|
|
|
|
|
|
|
|
|
@router.get('/put_in', summary='获取当前用户待归还清单')
|
|
|
async def put_in_index(request: Request):
|
|
|
"""
|
|
|
获取当前用户待归还清单
|
|
|
:return:
|
|
|
"""
|
|
|
current_user = request.state.current_user
|
|
|
|
|
|
cabinet_ids = await Cabinet.filter(terminal_id=setting.TERMINAL_ID).values_list('id', flat=True)
|
|
|
# 当前柜体待归还清单
|
|
|
query = Drug.filter(last_receive_id=current_user.id, state=2).filter(cabinet_id__in=cabinet_ids)
|
|
|
drugs = await query.all()
|
|
|
result = await drugs_list_info(drugs)
|
|
|
return respond_to(data=result)
|
|
|
|
|
|
@router.get('/keys_list', summary='获取钥匙清单')
|
|
|
async def get_keys_list(request: Request):
|
|
|
"""
|
|
|
获取钥匙清单
|
|
|
:return:
|
|
|
"""
|
|
|
current_user = request.state.current_user
|
|
|
role = await current_user.role
|
|
|
if role.grade >= 50:
|
|
|
query = Drug.filter(state__in=[DrugStateEnum.IN, DrugStateEnum.OUT])
|
|
|
drugs = await query.all()
|
|
|
result = await drugs_list_info(drugs)
|
|
|
return respond_to(data=result)
|
|
|
else:
|
|
|
return respond_to(code=403, desc="没有权限")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put('/expired_at', summary='药剂信息修改')
|
|
|
@logger_wrapper
|
|
|
async def update(keyword: DrugUpdateExpired):
|
|
|
"""
|
|
|
药剂信息过期时间修改
|
|
|
:param id: 用户药剂模板条目id
|
|
|
:param keyword:
|
|
|
:return:
|
|
|
"""
|
|
|
rfid = keyword.rfid if keyword.rfid else ""
|
|
|
query_param = {"id": keyword.id} if keyword.id else {"rfid": rfid}
|
|
|
drug_obj = await Drug.get(**query_param)
|
|
|
drug_obj.expired_at = keyword.expired_at
|
|
|
await drug_obj.save()
|
|
|
return respond_to(code=200, desc="更新成功")
|
|
|
|
|
|
|
|
|
@router.get('/dictionaries', summary='获取药剂字典列表')
|
|
|
async def index(request: Request, keyword: str = '', page_no: int = 1, page_size: int = 10):
|
|
|
"""
|
|
|
获取本终端药剂字典列表
|
|
|
:param keyword: 按药剂信息搜索
|
|
|
:param page_no: 分页页码,默认为1
|
|
|
:param page_size: 分页大小,默认为10
|
|
|
:return:
|
|
|
"""
|
|
|
query = QuerySet(Dictionary).filter()
|
|
|
archive_id = request.state.archive_id
|
|
|
if archive_id:
|
|
|
query = query.filter(archive_id=archive_id)
|
|
|
if keyword:
|
|
|
keyword = keyword.strip()
|
|
|
query = query.filter(Q(k1__icontains=keyword) | Q(k2__icontains=keyword) | Q(k3__icontains=keyword)
|
|
|
| Q(k4__icontains=keyword) | Q(k5__icontains=keyword)
|
|
|
| Q(k6__icontains=keyword))
|
|
|
offset = (page_no - 1) * page_size
|
|
|
count = await query.count()
|
|
|
dictionary_objs = await query.limit(page_size).offset(offset).order_by('-created_at').values()
|
|
|
result_list = []
|
|
|
for obj in dictionary_objs:
|
|
|
drug_info = ",".join([value for key, value in obj.items() if key.startswith('k') and value is not None])
|
|
|
item = dict(obj)
|
|
|
if obj['params']:
|
|
|
for k, v in obj['params'].items():
|
|
|
item[k] = v
|
|
|
item.pop("params")
|
|
|
item['drug_info'] = drug_info
|
|
|
result_list.append(item)
|
|
|
return respond_to(data={'data': result_list, 'count': count})
|
|
|
|
|
|
@router.put('/dictionary/{id}', summary='编辑药剂字典')
|
|
|
async def update(id: str, post: UpdateDictionary):
|
|
|
"""
|
|
|
编辑药剂字典
|
|
|
:param id: id
|
|
|
:param post:
|
|
|
:return:
|
|
|
"""
|
|
|
dictionary = await Dictionary.get(id=id)
|
|
|
dictionary.params = post.dict()
|
|
|
await dictionary.save()
|
|
|
return respond_to()
|
|
|
|
|
|
|
|
|
@router.post('/backtrack', summary='药剂是否原路返回')
|
|
|
async def index(request: Request, keyword: DrugBackTrack):
|
|
|
"""
|
|
|
判断药剂是否原路返回
|
|
|
drug_list[{
|
|
|
rfid: str
|
|
|
cabinet_id: str
|
|
|
drawer_id: str
|
|
|
hole: int = 0
|
|
|
}]
|
|
|
:return:
|
|
|
"""
|
|
|
if setting.BACKTRACK == 0:
|
|
|
return respond_to(200, data=[], desc="药剂不需要原路返回")
|
|
|
drugs = list()
|
|
|
for drug in keyword.drug_list:
|
|
|
drug_obj = await Drug.get_or_none(rfid=drug.get("rfid")).prefetch_related('template__archive')
|
|
|
if drug_obj is None:
|
|
|
continue
|
|
|
if drug_obj.cabinet_id != drug.get("cabinet_id") or \
|
|
|
drug_obj.drawer_id != drug.get("drawer_id") or \
|
|
|
drug.get("hole") and drug_obj.hole != drug.get("hole"):
|
|
|
|
|
|
drug_info = await drug_obj.attribute_drug_info()
|
|
|
drug_info_comment = ",".join(list(map(lambda x: str(x), drug_info.values())))
|
|
|
|
|
|
drugs.append({
|
|
|
"drugs_except_info": {
|
|
|
"sound": False,
|
|
|
"message": f"[{drug_info_comment}]药剂放入位置不正确",
|
|
|
"state": 5,
|
|
|
},
|
|
|
})
|
|
|
return respond_to(200, data=drugs)
|
|
|
|
|
|
@router.post('/blink', summary='灯光闪烁接口')
|
|
|
async def blink(request: BlinkLocation):
|
|
|
import httpx
|
|
|
post_data={}
|
|
|
post_data["position"] = request.position
|
|
|
post_data["duration"] = request.duration
|
|
|
post_data["function"] = request.function
|
|
|
url = "http://"+request.ip+"/api/cabinet/v1/led"
|
|
|
async with httpx.AsyncClient() as client:
|
|
|
try:
|
|
|
response = await client.post(url, json=post_data)
|
|
|
except Exception:
|
|
|
return respond_to(code=400, desc='下位机通讯失败')
|
|
|
return respond_to()
|
|
|
|
|
|
|
|
|
@return_router.post("/info", summary='RFID药剂详情(免登录)')
|
|
|
async def drug_info(request: DrugRfids):
|
|
|
"""
|
|
|
获取RFID药剂信息 药剂信息详情
|
|
|
:return:
|
|
|
"""
|
|
|
drugs = list()
|
|
|
for rfid in request.rfids:
|
|
|
drug_obj = await Drug.get_or_none(rfid=rfid).prefetch_related('dictionary', 'template', 'drawer_board', 'template__archive')
|
|
|
if drug_obj is None:
|
|
|
drugs.append({
|
|
|
"drugs_except_info": {
|
|
|
"sound": False,
|
|
|
"message": "非法标签",
|
|
|
"state": 0,
|
|
|
},
|
|
|
"rfid_drug": {rfid: f"[{rfid}]未知药剂"}
|
|
|
})
|
|
|
continue
|
|
|
result = jsonable_encoder(drug_obj)
|
|
|
template_obj = drug_obj.template
|
|
|
terminal_obj = await Terminal.get(id=setting.TERMINAL_ID)
|
|
|
data = await drugs_except_info(drug_obj, terminal_obj)
|
|
|
|
|
|
drug_info = await drug_obj.attribute_drug_info()
|
|
|
parse_fill_json_content = await drug_obj.parse_fill_json_content()
|
|
|
|
|
|
parse_fill_json_content.update({f'余重': f'{milligram_to_gram(drug_obj.remain_gross_weight)}'})
|
|
|
|
|
|
return_require_weigh = template_obj.archive.params.get("return_require_weigh", '')
|
|
|
|
|
|
drug_info_dict = {
|
|
|
"drugs_except_info": data,
|
|
|
"fill_json_content": parse_fill_json_content,
|
|
|
"rfid_drug": {drug_obj.rfid: ",".join(list(map(lambda x:str(x), drug_info.values())))},
|
|
|
"return_require_weigh": return_require_weigh
|
|
|
}
|
|
|
# 2000型号柜子,需要灯光指引,返回值添加灯光序号参数
|
|
|
if setting.CLIENT_NUMBER == "2000":
|
|
|
if drug_obj.drawer_board:
|
|
|
drawer_board_line_no = drug_obj.drawer_board.line_no
|
|
|
# 亮灯位置 = 层数*36+编号
|
|
|
blink_no = (drawer_board_line_no - 1) * 36 + drug_obj.hole
|
|
|
drug_info_dict.update({"blink_no": blink_no})
|
|
|
|
|
|
result.update(drug_info_dict)
|
|
|
drugs.append(result)
|
|
|
return respond_to(code=200, desc="获取RFID药剂信息成功", data=drugs)
|
|
|
|
|
|
|
|
|
@return_router.post('/weight', summary="药剂用量或余量更新(快速归还)")
|
|
|
async def return_drug(request: Request, keyword: DrugUpdateRequest):
|
|
|
"""
|
|
|
药剂用量或余量更新
|
|
|
接收id或rfid都可以更新重量
|
|
|
余量与用量二选一,只有一个有值
|
|
|
:param keyword: 包含更新信息的请求体
|
|
|
:return:
|
|
|
"""
|
|
|
print("open_date", keyword.open_date)
|
|
|
rfid = keyword.rfid if keyword.rfid else ""
|
|
|
if keyword.id:
|
|
|
drug_obj = await Drug.filter(id=keyword.id).prefetch_related("template","last_receive").first()
|
|
|
else:
|
|
|
drug_obj = await Drug.filter(Q(barcode=rfid) | Q(rfid=rfid)).prefetch_related("template","last_receive").first()
|
|
|
|
|
|
if not drug_obj:
|
|
|
return respond_to(404, desc="药剂不存在")
|
|
|
syr = drug_obj.fill_json_content.get('syr') # 入库模板药剂使用人
|
|
|
syr_user = await User.get_or_none(name=syr.replace(' ', ''))
|
|
|
# 用户默认为药剂使用人
|
|
|
current_user = syr_user if syr_user else drug_obj.last_receive
|
|
|
# 柜子的当前使用人更新,盘点时需要
|
|
|
cabinet_id = keyword.cabinet_id
|
|
|
if not cabinet_id:
|
|
|
cabinet_obj = await Cabinet.filter(terminal_id=setting.TERMINAL_ID).first()
|
|
|
else:
|
|
|
cabinet_obj = await Cabinet.get_or_none(id=cabinet_id)
|
|
|
cabinet_obj.user_id = current_user.id
|
|
|
await cabinet_obj.save()
|
|
|
|
|
|
if keyword.weight:
|
|
|
if not drug_obj.remain_gross_weight:
|
|
|
drug_obj.remain_gross_weight = keyword.weight
|
|
|
await drug_obj.save()
|
|
|
else:
|
|
|
# 余量转用量,更新用量
|
|
|
mill_weight = drug_obj.remain_gross_weight - keyword.weight
|
|
|
await drug_obj.update_last_use_weight(weight=float(mill_weight))
|
|
|
elif keyword.use_weight:
|
|
|
mill_weight = keyword.use_weight if keyword.use_weight and keyword.use_weight != "NaN" else 0
|
|
|
await drug_obj.update_last_use_weight(weight=float(mill_weight))
|
|
|
if keyword.open_date:
|
|
|
if not drug_obj.open_date:
|
|
|
drug_obj.open_date = parse_datetime(keyword.open_date, "%Y-%m-%d")
|
|
|
template_obj = drug_obj.template
|
|
|
new_expired_at = open_update_expired_at(drug_obj, template_obj, keyword.open_date)
|
|
|
if new_expired_at:
|
|
|
drug_obj.expired_at = new_expired_at
|
|
|
await drug_obj.save()
|
|
|
# 一维条码扫码归还更新重量后直接修改药剂状态,生成流转记录
|
|
|
rfid = drug_obj.rfid
|
|
|
if len(rfid) < 16 and drug_obj.state == DrugStateEnum.OUT:
|
|
|
|
|
|
if cabinet_obj:
|
|
|
# 位置更新
|
|
|
position_str = f"{cabinet_obj.label}"
|
|
|
drug_obj.position = position_str
|
|
|
|
|
|
drug_obj.last_return_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
open_date = drug_obj.open_date
|
|
|
if not open_date:
|
|
|
drug_obj.open_date = datetime.datetime.now()
|
|
|
# drug_obj.last_return_id = request.state.current_user.id
|
|
|
drug_obj.last_return_id = current_user.id
|
|
|
drug_obj.cabinet_id = cabinet_obj.id
|
|
|
if keyword.selectDrawer_id:
|
|
|
drawer_board = await DrawerBoard.filter(id = keyword.selectDrawer_id).get_or_none()
|
|
|
if drawer_board:
|
|
|
drug_obj.drawer_id = drawer_board.drawer_id
|
|
|
drug_obj.drawer_board_id = keyword.selectDrawer_id
|
|
|
await drug_obj.save()
|
|
|
|
|
|
# 一维条码生成流转记录
|
|
|
standard = CodeStandard([current_user.id,], drug_obj)
|
|
|
await standard.put_in(barcode=drug_obj.barcode if len(drug_obj.rfid) < 16 else drug_obj.rfid)
|
|
|
return respond_to(code=200, desc="更新成功")
|
|
|
return respond_to(code=200, desc="更新成功")
|
|
|
|
|
|
|
|
|
@return_router.post('/empty', summary='试剂置为空瓶')
|
|
|
async def return_empty(request: Request, post: EmptyBottleDisposal):
|
|
|
"""
|
|
|
试剂置为空瓶
|
|
|
:param request: Request请求头信息
|
|
|
:param post: 空瓶信息的请求体
|
|
|
:return:
|
|
|
"""
|
|
|
# users = request.state.users
|
|
|
# standard = Standard(users)
|
|
|
rfid = post.rfid
|
|
|
drug = await Drug.filter(rfid=rfid).prefetch_related("last_receive").first()
|
|
|
if not drug:
|
|
|
return respond_to(404, desc="药剂不存在")
|
|
|
# user_weight = post.weight
|
|
|
open_date = post.open_date
|
|
|
if open_date:
|
|
|
drug.open_date = parse_datetime(open_date, "%Y-%m-%d")
|
|
|
await drug.save()
|
|
|
syr = drug.fill_json_content.get('syr') # 入库模板药剂使用人
|
|
|
syr_user = await User.get_or_none(name=syr.replace(' ', ''))
|
|
|
# 用户默认为药剂使用人
|
|
|
current_user = syr_user if syr_user else drug.last_receive
|
|
|
standard = Standard([current_user.id,])
|
|
|
await standard.empty(rfid)
|
|
|
return respond_to()
|