You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import datetime
from datetime import timedelta
from decimal import Decimal
from tortoise.queryset import Q
from conf.setting import setting
from helper.drug import milligram_to_gram, gram_to_milligram
from helper.log import record_log
from helper.logger import logger
from models.dictionary import Dictionary
from models.drawer_board import DrawerBoard
from models.drug import Drug, DrugStateEnum
from models.drug_use_log import DrugUseLog, DrugUseStateEnum
from models.template import Template
from models.terminal import Terminal
from models.user import User
from models.cabinet import Cabinet
from transfer.basic import BasicStandard
class Standard(BasicStandard):
'''标准流转类'''
def __init__(self, users: list[str]):
self.users = users
self.rfid = ""
self.hole = None
self.drug_obj = None
self.drawer_board_obj = None
self.in_return_func = {
DrugStateEnum.OUT: self.return_drug,
DrugStateEnum.INITIAL: self.in_drug,
DrugStateEnum.IN: self.in_drug,
DrugStateEnum.EMPTY: None
}
async def _get_drug_related(self, cabinet_id):
drugs = await Drug.filter(rfid=self.rfid).prefetch_related("dictionary", "template")
if not drugs:
return False
self.drug_obj = drugs[0]
# self.drawer_board_obj = await DrawerBoard.filter(cabinet_id=cabinet_id).prefetch_related("cabinet", "drawer", "board").first()
self.template_obj = self.drug_obj.template
self.terminal_obj = await Terminal.get_or_none(id=setting.TERMINAL_ID)
self.cabinet_obj = await Cabinet.get_or_none(id=cabinet_id)
return True
def parse_position(self, hole):
"""
解析位置信息
:return:
"""
# terminal_name = self.terminal_obj.name
drawer_label = self.drawer_board_obj.drawer.label if self.drawer_board_obj else ""
cabinet_location_label = f"{self.cabinet_obj.label}"
board_hole = ""
if self.drawer_board_obj:
board_hole = self.drawer_board_obj.board.chip_dict.get(str(hole), "") if self.drawer_board_obj.board.chip_dict \
else ""
position_str = f"{cabinet_location_label}-{drawer_label}"
if self.drawer_board_obj and self.drawer_board_obj.label:
position_str += f"-{self.drawer_board_obj.label}"
if board_hole:
position_str += f"-{board_hole}"
return position_str
async def return_drug(self):
"""
归还药剂
归还输入用量
:return:
"""
if self.drug_obj.state == DrugStateEnum.EMPTY:
operate_state = DrugUseStateEnum.EMPTY
else:
operate_state = DrugUseStateEnum.PUT
operate_type = "return"
response_info = {
"operate_type": operate_type,
"operate_state": operate_state,
}
return response_info
async def in_drug(self):
"""
入库药剂
:return:
"""
if self.drug_obj.state == DrugStateEnum.EMPTY:
operate_state = DrugUseStateEnum.EMPTY
else:
operate_state = DrugUseStateEnum.IN
operate_type = "in"
response_info = {
"operate_type": operate_type,
"operate_state": operate_state,
}
return response_info
async def put_in(self, rfid: str, cabinet_id: str, position):
"""
归还/入库
:param rfid: rfid
:param cabinet_id: 柜体id
:param line_no: 接线号
:param hole: 孔位
:return:
"""
self.rfid = rfid
# check = await self._get_drug_related(cabinet_id,)
# if not check:
# return False
# 入库或归还
response_info = await self.in_return_func[self.drug_obj.state]()
operate_state = response_info.get("operate_state")
operate_type = response_info.get("operate_type")
if operate_type == 'return':
# 归还流转日志保存
user_id = self.users[0]
peer_ids = ",".join(self.users[1:])
users_name = await User.parse_id_user(self.users)
drug_use_dict = {
"drug": self.drug_obj,
"state": operate_state,
"user_id": user_id,
"peer_ids": peer_ids,
"users": users_name,
"cabinet_id": cabinet_id,
# "drawer_id": self.drawer_board_obj.drawer_id if self.drawer_board_obj else None,
# "drawer_board_id": self.drawer_board_obj.id if self.drawer_board_obj else None,
"position": position,
}
else:
# 入库流转日志保存
drug_use_dict = {
"drug": self.drug_obj,
"state": operate_state,
"user_id": self.users[0],
"peer_ids": ",".join(self.users[1:]),
"users": await User.parse_id_user(self.users),
"cabinet_id": cabinet_id,
# "drawer_id": self.drawer_board_obj.drawer_id if self.drawer_board_obj else None,
# "drawer_board_id": self.drawer_board_obj.id if self.drawer_board_obj else None,
"position": position,
# "weight": weight,
# "use_weight": use_weight,
# "alarm_state": response_info.get("alarm_state"),
# "alarm_desc": response_info.get("alarm_desc"),
}
if setting.TERMINAL_ID:
drug_use_dict.update({
"terminal_id": setting.TERMINAL_ID
})
return_obj = await DrugUseLog().create(**drug_use_dict)
if operate_type == 'return':
receive_obj = await DrugUseLog.filter(drug_id=self.drug_obj.id, state=2).order_by('-created_at').first()
if receive_obj:
# 更新return_log_id字段
receive_obj.return_log_id = return_obj.id
await receive_obj.save()
# 药剂更新
drug_update_dict = {
"state": DrugStateEnum.IN if self.drug_obj.state != DrugStateEnum.EMPTY else DrugStateEnum.EMPTY,
# "drawer_board": self.drawer_board_obj if self.drawer_board_obj else None,
# "board_id": self.drawer_board_obj.board_id if self.drawer_board_obj else None,
# "drawer_id": self.drawer_board_obj.drawer_id if self.drawer_board_obj else None,
"cabinet_id": cabinet_id,
# "position": position,
}
if operate_type == "in":
drug_update_dict.update({
"storage_id": self.users[0],
"storage_at": self._now_strftime(),
})
else:
drug_update_dict.update({
"last_return_at": self._now_strftime(),
"last_return_id": self.users[0],
"last_use_weight": None,
})
await self.drug_obj.update_from_dict(drug_update_dict)
await self.drug_obj.save()
# data = {
# "drug_info": await self.drug_obj.attribute_drug_info(),
# "position": position,
# "operate_type": operate_type,
# "remain_gross_weight": milligram_to_gram(self.drug_obj.remain_gross_weight),
# "use_weight": milligram_to_gram(float(use_weight)) if use_weight else None,
# "created_at": self._now_strftime(),
# "state": drug_update_dict["state"],
# "unit_code": self.drug_obj.attribute("unit_code"), # 单位编码
# "expired_at": self.drug_obj.expired_at.strftime("%Y-%m-%d") if self.drug_obj.expired_at else None # 过期时间
# }
# await self.write_log(operate_type, drug_use_dict)
# return data
async def take_out(self, rfid: str, cabinet_id: str, position):
"""
领用
领用需称重的情况,关上柜门选择条目称重,更新重量。如果没有称,定时任务五分钟扫到后报警
领用的时候如果上一次归还必称重未称重drug_use_log中weight为空那么就必须称重称重后更新上一次的归还记录重量与用量
:param rfid:
:param cabinet_id:
:param line_no:
:return: 领用清单条目
"""
self.rfid = rfid
# check = await self._get_drug_related(cabinet_id, line_no)
# if not check or self.drug_obj.state == 3:
# self.drug_obj.position = None
# await self.drug_obj.save()
# return False
# 领用是否需称重(上次归还未称重则本次领用需称重)
# receive_require_weigh = await DrugUseLog.judge_receive_require_weigh(drug_id=self.drug_obj.id,
# terminal_obj=self.terminal_obj)
#
# # 是否领用即空瓶
drug_obj = await Drug.get(rfid=rfid).prefetch_related('template','dictionary')
# terminal_obj = await Template.get(id=drug_obj.template.id).prefetch_related('archive')
# first_will_empty = terminal_obj.archive.params.get("first_will_empty", '')
# first_will_open = terminal_obj.archive.params.get("first_will_open", '')
# position = f"{self.parse_position(self.drug_obj.hole)}"
drug_use_dict = {
"drug": self.drug_obj,
"state": DrugUseStateEnum.TAKE,
"user_id": self.users[0],
"peer_ids": ",".join(self.users[1:]),
"users": await User.parse_id_user(self.users),
"terminal_id": setting.TERMINAL_ID,
"cabinet_id": cabinet_id,
# "drawer_id": self.drawer_board_obj.drawer_id,
# "drawer_board_id": self.drawer_board_obj.id,
"hole": self.drug_obj.hole,
"position": position,
}
await DrugUseLog().create(**drug_use_dict)
# 更新药剂信息
drug_update_dict = {
"state": DrugStateEnum.OUT if self.drug_obj.state != DrugStateEnum.EMPTY else DrugStateEnum.EMPTY,
# "last_weight": 0,
# "drawer_board": self.drawer_board_obj,
# "board_id": self.drawer_board_obj.board_id,
"last_receive_at": self._now_strftime(),
"last_receive_id": self.users[0],
"position": position,
}
await self.drug_obj.update_from_dict(drug_update_dict)
await self.drug_obj.save()
dic_obj = await Dictionary.get(id=drug_obj.dictionary.id)
dic_obj.use_count += 1
await dic_obj.save()
# data = {
# "drug_info": await self.drug_obj.attribute_drug_info(),
# "position": position,
# "hole": self.drug_obj.hole,
# "remain_gross_weight": await self.drug_obj.format_weight(), # 领用清单条目余重
# "created_at": self._now_strftime(),
# "state": drug_update_dict["state"],
# "unit_code": self.drug_obj.attribute("unit_code"), # 单位编码
# "expired_at": self.drug_obj.expired_at.strftime("%Y-%m-%d"), # 过期时间
# "fill_json_content": self.drug_obj.fill_json_content
# }
# await self.write_log("take_out", drug_use_dict)
#
# return data
async def decap(self, rfid: str, cabinet_id: str, line_no: str, hole: int = 0):
'''报废处置 传入值是什么?'''
self.rfid = rfid
await self._get_drug_related(cabinet_id, line_no)
drug_use_dict = {
"drug": self.drug_obj,
"state": DrugUseStateEnum.SCRAP,
"user_id": self.users[0],
"peer_ids": ",".join(self.users[1:]),
"users": await User.parse_id_user(self.users),
"terminal_id": setting.TERMINAL_ID,
"cabinet_id": self.drawer_board_obj.cabinet_id,
"drawer_id": self.drawer_board_obj.drawer_id,
"drawer_board_id": self.drawer_board_obj.id,
"hole": hole,
"position": self.drug_obj.position,
"alerted": False,
"use_weight": 0,
}
drug_use_log_obj = await DrugUseLog().create(**drug_use_dict)
# 更新药剂信息
drug_update_dict = {
"state": DrugStateEnum.SCRAP,
"last_use_weight": 0,
"drawer_board_id": self.drawer_board_obj.id,
"hole": hole,
"board_id": self.drawer_board_obj.board_id,
}
await self.drug_obj.update_from_dict(drug_update_dict)
await self.drug_obj.save()
drug_use_dict.update({
"drug_use_log_id": drug_use_log_obj.id,
})
return drug_use_dict