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.

300 lines
10 KiB

# -*- coding:utf-8 -*-
"""
@Created on : 2023/5/23 11:26
@Author: hxl
@Des: 抽屉管理
"""
from fastapi import APIRouter, Request, Depends
from pydantic import BaseModel
from tortoise.exceptions import BaseORMException
from tortoise.transactions import in_transaction
from helper.log import logger_wrapper
from helper import respond_to, login_required
from models import Cabinet, Drawer, DrawerBoard, Board, Drug
router = APIRouter(prefix='/drawers', dependencies=[Depends(login_required)], responses={404: {"description": "Not found"}},)
return_router = APIRouter(prefix='/drawers')
class CreateDrawer(BaseModel):
line_no: int
label: str
tags: str | None
rank: int
class UpdateDrawer(BaseModel):
id: str
line_no: int
label: str
tags: str | None
rank: int
class DrawerConfig(BaseModel):
line_no: int
label: str | None
capacity: int
rank: int
board_id: str
class UpdateConfig(BaseModel):
id: str
line_no: int
label: str | None
capacity: int
board_id: str
class CreateDrawerConfig(BaseModel):
drawer: CreateDrawer
board_config: list[DrawerConfig]
class UpdateDrawerConfig(BaseModel):
drawer: UpdateDrawer
board_config: list[DrawerConfig]
@router.get('/{cabinet_id}', summary='抽屉列表')
async def index(request: Request, cabinet_id: str):
"""
柜体管理列表
:param request: Request
:param cabinet_id: str
:return:
"""
cabinet = await Cabinet.get(id=cabinet_id)
if not cabinet.matrix:
return respond_to(400, '请先设置布局信息')
cabinet.user_id = ','.join(request.state.users)
current_user = request.state.current_user
await cabinet.save()
query = Drawer.filter(cabinet_id=cabinet.id)
drawers = await query.order_by("-rank").values("id", "cabinet_id", "line_no", "label", "tags", "rank")
result = []
for drawer in drawers:
drawer_board_values = await DrawerBoard.filter(drawer_id=drawer.get("id")).values("id", "line_no", "label")
drawer['drawer_board'] = drawer_board_values
drawer['is_permission'] = True if str(drawer['id']) in current_user.drawers else False
result.append(drawer)
return respond_to(data=dict(drawers=result))
@router.post("/{cabinet_id}", summary="级联抽屉添加")
@logger_wrapper
async def create(cabinet_id: str, post: CreateDrawerConfig):
"""
级联抽屉添加
:param cabinet_id: str
:param post: CreateDrawerConfig
:return:
"""
# 解析 JSON 数据
drawer_data = post.drawer
configs_data = post.board_config
for conf in configs_data:
drawer = await DrawerBoard.get_or_none(cabinet=cabinet_id, line_no=conf.line_no)
if drawer:
return respond_to(409, desc=f"该柜体接线号为{conf.line_no}的定位版已存在")
async with in_transaction() as conn:
# 创建柜体记录
try:
drawer = await Drawer.create(**drawer_data.dict(), cabinet_id=cabinet_id, connection=conn)
# 创建抽屉记录
for config_data in configs_data:
board = await DrawerBoard.get_or_none(cabinet_id=cabinet_id, line_no=config_data.line_no)
if board:
raise BaseORMException()
await DrawerBoard.create(**config_data.dict(), drawer_id=drawer.id, cabinet_id=cabinet_id,
connection=conn)
except BaseORMException as e:
return respond_to(409, desc=f"该柜体接线号为{config_data.line_no}的定位版已存在")
return respond_to(desc="创建成功!")
@router.put("/{cabinet_id}", summary="级联抽屉更新")
@logger_wrapper
async def update_drawer_config(cabinet_id: str, post: UpdateDrawerConfig):
"""
级联抽屉更新
:param cabinet_id: int 抽屉 ID
:param post: UpdateDrawerConfig 更新信息
:return:
"""
# 解析 JSON 数据
for conf in post.board_config:
drawer = await DrawerBoard.get_or_none(cabinet=cabinet_id, line_no=conf.line_no)
if drawer:
return respond_to(409, desc=f"该柜体接线号为{conf.line_no}的定位版已存在")
async with in_transaction() as conn:
try:
# 更新抽屉记录
data = post.drawer.dict()
data.pop('id')
await Drawer.filter(id=post.drawer.id).update(**data)
# 更新定位版记录
configs_data = post.board_config
for config_data in configs_data:
board = await DrawerBoard.get_or_none(cabinet_id=cabinet_id, line_no=config_data.line_no)
if board:
raise BaseORMException()
await DrawerBoard.create(**config_data.dict(), drawer_id=post.drawer.id, cabinet_id=cabinet_id,
connection=conn)
except BaseORMException as e:
return respond_to(409, desc=f"该柜体接线号为{config_data.line_no}的定位版已存在")
return respond_to(desc="更新成功!")
@router.post('/config/{drawer_id}', summary='配置定位板')
@logger_wrapper
async def create(drawer_id: str, post: DrawerConfig):
"""
配置定位板
:param drawer_id:str
:param post:DrawerConfig
:return:
"""
drawer = await Drawer.get(id=drawer_id).values('id', 'cabinet_id')
board = await Board.get(id=post.board_id).values('id')
board_config = await DrawerBoard.get_or_none(cabinet_id=drawer['cabinet_id'], line_no=post.line_no)
if board_config:
return respond_to(code=409, desc='添加失败,接线号不能相同!')
data = post.dict()
data.pop("board_id")
result = await DrawerBoard.create(**data, board_id=board['id'], drawer_id=drawer['id'],
cabinet_id=drawer['cabinet_id'])
if not result:
return respond_to(code=400, desc='配置失败')
return respond_to()
@router.delete('/config/{config_id}', summary='删除配置定位板')
@logger_wrapper
async def delete(config_id: str):
"""
删除配置定位板
:param config_id:str
:return:
"""
result = await DrawerBoard.filter(id=config_id).delete()
if not result:
return respond_to(code=400, desc='删除失败')
return respond_to()
@router.get('/config/{drawer_id}', summary='获取配置定位板')
async def index(drawer_id: str):
"""
获取配置定位板
:param drawer_id:str
:return:
"""
result = await DrawerBoard.filter(drawer=drawer_id).prefetch_related('board')
data = []
for con in result:
data.append({
'id': con.id,
'line_no': con.line_no,
'board_name': con.board.name,
'label': con.label,
'capacity': con.capacity,
'board_id': con.board.id
})
return respond_to(data=data)
@router.get('/board/{drawer_id}', summary='抽屉下的定位板详情')
async def index(drawer_id: str):
"""
获取抽屉下的定位板详情
:param drawer_id:str
:return:
"""
drawer_boards = await DrawerBoard.filter(drawer_id=drawer_id).prefetch_related('board')
results = []
for drawer_board in drawer_boards:
# 查询板子信息和药品数量
board_info = await Board.get(id=drawer_board.board.id).values()
drugs_list = await Drug.filter(drawer_board_id=drawer_board.id, state__in=[1, 3], position__isnull=False).values('rfid', 'hole')
if drugs_list:
if drugs_list[0]['hole'] == 0:
drugs = [item['rfid'] for item in drugs_list]
else:
drugs = {item['hole']: item['rfid'] for item in drugs_list}
else:
drugs = None
existing_capacity = len(drugs_list)
# 构造结果
results.append({
drawer_board.line_no: {
**board_info,
'drugs_dict': drugs,
'existing_capacity': existing_capacity,
'capacity': drawer_board.capacity,
'label': drawer_board.label,
}
})
return respond_to(data=results)
@router.get('/drug/{drawer_id}', summary='抽屉下药剂详情')
async def index(drawer_id: str):
"""
抽屉下药剂详情
:param drawer_id:str
:return:
"""
drawer_boards = await DrawerBoard.filter(drawer_id=drawer_id).prefetch_related("drawer").all()
drugs_list = await Drug.filter(drawer_id=drawer_id, state__in=[1, 3], position__isnull=False).values('rfid', 'hole')
if drugs_list:
if not drugs_list[0]['hole'] or drugs_list[0]['hole'] == 0:
drugs = [item['rfid'] for item in drugs_list]
else:
drugs = {item['hole']: item['rfid'] for item in drugs_list}
else:
drugs = None
existing_capacity = len(drugs_list)
# 构造结果
results = [{
'drugs_dict': drugs,
'existing_capacity': existing_capacity,
'capacity': sum([drawer_board.capacity for drawer_board in drawer_boards]) if drawer_boards else -1,
'label': drawer_boards[0].drawer.label if drawer_boards else "",
}]
return respond_to(data=results)
@return_router.get('/info/{cabinet_id}', summary='抽屉列表(免登录)')
async def index(request: Request, cabinet_id: str):
"""
柜体管理列表
:param request: Request
:param cabinet_id: str
:return:
"""
cabinet = await Cabinet.get(id=cabinet_id)
if not cabinet.matrix:
return respond_to(400, '请先设置布局信息')
# cabinet.user_id = ','.join(request.state.users) # 移至扫码归还处,需要提供给盘点使用
# current_user = request.state.current_user
# await cabinet.save()
query = Drawer.filter(cabinet_id=cabinet.id)
drawers = await query.order_by("-rank").values("id", "cabinet_id", "line_no", "label", "tags", "rank")
result = []
for drawer in drawers:
drawer_board_values = await DrawerBoard.filter(drawer_id=drawer.get("id")).values("id", "line_no", "label")
drawer['drawer_board'] = drawer_board_values
drawer['is_permission'] = True
result.append(drawer)
return respond_to(data=dict(drawers=result))