# -*- 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))