#!/usr/bin/env python # encoding: utf-8 """ @author: tx @file: report.py @time: 2023/6/9 19:40 @desc: """ from datetime import datetime, timedelta import pytz from fastapi import Request from fastapi.encoders import jsonable_encoder from pypika.functions import Cast from tortoise.expressions import RawSQL from tortoise.queryset import QuerySet, Q, Count from tortoise import Tortoise, fields, models from conf import setting from models.drug_use_log import DrugUseLog, DrugUseStateEnum from models.drug import Drug, DrugStateEnum from models.cabinet import Cabinet from models.dictionary import Dictionary from models.template import Template from models.user import User from models.archive import Archive from models.log import EnvironmentLogs from helper.drug import milligram_to_gram, gram_to_milliliter from helper.tool import parse_datetime from endpoints.warning import get_already_expired async def query_logs(query, out_drug_ids, other_drug_ids, archive_id): if archive_id: query = query.filter(drug__template__archive__id=archive_id) out_drug_logs = await query.prefetch_related('drug').filter(drug_id__in=out_drug_ids).filter(state=DrugUseStateEnum.TAKE).all().order_by( '-created_at') other_drug_logs = await query.prefetch_related('drug').filter(drug_id__in=other_drug_ids).filter(state=DrugUseStateEnum.TAKE).all().order_by( '-created_at') drug_use_logs = await query.filter(state=DrugUseStateEnum.EMPTY) \ .filter(drug__template__archive__params__contains={'first_will_empty': True}) \ .prefetch_related('drug') drug_logs = out_drug_logs + other_drug_logs + drug_use_logs count = len(drug_logs) return count, drug_logs async def parse_cabinet_ids(): cabinet_obj = await Cabinet.filter(terminal_id=setting.TERMINAL_ID).prefetch_related("archive").first() cabinets_ids = await Cabinet.filter(archive_id=cabinet_obj.archive.id).values_list("id", flat=True) return cabinets_ids async def parse_archive_cabinet_ids(archive_id: str, client_ids: list): """ 根据大类ID获取柜体 如果传递客户端ids参数,则返回用户有权限的大类柜体列表 :param archive_id: :param client_ids: 用户有权限的柜体id,如果不传则代表全部柜体 :return: """ query = QuerySet(Cabinet).filter() if archive_id: query = query.filter(archive_id=archive_id) if client_ids: query = query.filter(id__in=client_ids) # 用户有权限的柜体 cabinets_ids = await query.values_list("id", flat=True) return cabinets_ids async def report_drug_logs(request: Request, keyword): """ 平台流转日志列表 :return: """ page_no = keyword.page_no page_size = keyword.page_size offset = (page_no - 1) * page_size query = QuerySet(DrugUseLog) if setting.TERMINAL_ID: query = query.filter(terminal_id=setting.TERMINAL_ID) if keyword.user_id: query = query.filter(user_id=keyword.user_id) else: user = await User.filter(id=request.state.current_user.id).get_or_none() if user.role_id!=1 and user.role_id!=100: query = query.filter(user_id=request.state.current_user.id) if keyword.state in [0, 1, 2, 3, 4]: query = query.filter(state=keyword.state) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") # if keyword.drug_id: # query = query.filter(drug_id=keyword.drug_id) count = await query.count() if page_no: logs = await query.prefetch_related('drug').limit(page_size).offset(offset).order_by('-created_at') else: logs = await query.prefetch_related('drug').order_by('-created_at') attribute_key = await logs[0].drug.attribute_drug_info() if logs else {} result = list() for log in logs: if not log.drug: continue if log.state in [1, 3]: use_weight = log.use_weight finally_use_weight = "" if not use_weight and log.state != DrugUseStateEnum.PUT else use_weight else: finally_use_weight = '' # weight > 1000 转换为g 保留一位小数否则返回mg weight = float(log.weight) if log.weight else 0 if weight > 1000: weight_str = f"{milligram_to_gram(log.weight)}g" else: weight_str = f"{log.weight}mg" if log.weight is not None else "-" finally_use_weight_str = log.parse_use_weight(finally_use_weight) attribute_drug = await log.drug.attribute_drug_info() result.append({ **jsonable_encoder(log), "drug_info": attribute_drug, "weight": weight_str, "use_weight": finally_use_weight_str, **attribute_drug, "created_at": log.created_at.strftime("%Y-%m-%d %H:%M:%S"), }) return dict(count=count, data=result, attribute_key=list(attribute_key.keys())) async def report_inventory_drug(request: Request, keyword): """ 库存明细报表 :return: """ page_no = keyword.page_no page_size = keyword.page_size drug_name = keyword.drug_name dictionary_id = keyword.dictionary_id rfid = keyword.rfid spec = keyword.spec cabinet_ids = keyword.cabinet_ids purity = keyword.purity batch_no = keyword.batch_no manufacturer = keyword.manufacturer position = keyword.position report_ids = keyword.report_ids offset = (page_no - 1) * page_size query = QuerySet(Drug).filter() order_key = "remain_gross_weight" if rfid: query = query.filter(rfid=rfid) if position: query = query.filter(position=position) if batch_no: query = query.filter(fill_json_content__contains={"ph": batch_no}) # if manufacturer: # query = query.filter(Q(fill_json_content__contains={"manufacturer": manufacturer}) # | Q(fill_json_content__contains={"cs": manufacturer})) archive_id = request.state.archive_id if cabinet_ids: query = query.filter(cabinet_id__in=cabinet_ids) else: if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) else: # 根据终端筛选 if setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) if drug_name or spec or purity: dict_query = QuerySet(Dictionary) if drug_name: dict_query = dict_query.filter(k1__contains=drug_name) if spec: dict_query = dict_query.filter(k2__contains=spec) if purity: dict_query = dict_query.filter(k3__contains=purity) dictionary_ids = await dict_query.all().values_list("id", flat=True) if not dictionary_ids: return dict(count=0, data=[], attribute_key=[]) query = query.filter(dictionary_id__in=dictionary_ids) order_key = "expired_at" if dictionary_id: query = query.filter(dictionary_id__in=[dictionary_id]) order_key = "expired_at" query = query.filter(state__in=[DrugStateEnum.IN, DrugStateEnum.OUT]) if report_ids: query = query.filter(id__in=report_ids) count = 0 drug_objs = await query.order_by(order_key) attribute_key = await drug_objs[0].attribute_drug_info() if drug_objs else {} result = list() archive_obj = await Archive.get_or_none(id=archive_id) archive_name = archive_obj.name if archive_obj else "" for drug_obj in drug_objs: if manufacturer and ((drug_obj.attribute("cs") and drug_obj.attribute("cs") != manufacturer) or (drug_obj.attribute("manufacturer") and drug_obj.attribute("manufacturer") != manufacturer)): continue attribute_drug = await drug_obj.attribute_drug_info() data = { "id": drug_obj.id, "dictionary_id": drug_obj.dictionary_id, "drug_info": attribute_drug, "rfid": drug_obj.rfid, "position": drug_obj.position, "expired_at": drug_obj.expired_at.strftime("%Y-%m-%d") if drug_obj.expired_at else "", "net_weight": drug_obj.attribute("net_weight"), "remain_gross_weight": await drug_obj.format_weight(), "state": drug_obj.state, "last_user": await drug_obj.attribute_last_user(), "cas_code": drug_obj.attribute("cas_code") if drug_obj.attribute("cas_code") else drug_obj.attribute("cas"), "manufacturer": drug_obj.attribute("manufacturer") if drug_obj.attribute("manufacturer") else drug_obj.attribute("cs"), "batch_no": drug_obj.attribute("ph"), "storage_at": drug_obj.storage_at.strftime("%Y-%m-%d") if drug_obj.storage_at else "", **attribute_drug } if archive_name == "耗材": data.update({ "remain_count": int(drug_obj.attribute("total_count")) - drug_obj.total_use_weight if drug_obj.attribute("total_count") else "-", "unit_code": drug_obj.attribute("unit_code"), "manufacturer": drug_obj.attribute("cs") # 生产厂商 }) result.append(data) count += 1 if page_no: result = result[offset: offset + page_size] return dict(count=count, data=result, attribute_key=list(attribute_key.keys())) async def report_put_in_detail_drug(request: Request, keyword): """ 入库明细 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size dictionary_id = keyword.dictionary_id drug_name = keyword.drug_name rfid = keyword.rfid spec = keyword.spec purity = keyword.purity batch_no = keyword.batch_no manufacturer = keyword.manufacturer position = keyword.position report_ids = keyword.report_ids query = QuerySet(DrugUseLog).filter() if rfid: query = query.filter(drug__rfid=rfid) if position: query = query.filter(drug__position=position) if batch_no: query = query.filter(drug__fill_json_content__contains={"ph": batch_no}) if keyword.user_id: query = query.filter(user_id=keyword.user_id) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") archive_id = request.state.archive_id archive_obj = await Archive.get_or_none(id=archive_id) archive_name = archive_obj.name if archive_obj else "" if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) else: # 根据终端筛选 if setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) if drug_name or spec or purity: dict_query = QuerySet(Dictionary) if drug_name: dict_query = dict_query.filter(k1__contains=drug_name) if spec: dict_query = dict_query.filter(k2__contains=spec) if purity: dict_query = dict_query.filter(k3__contains=purity) dictionary_ids = await dict_query.all().values_list("id", flat=True) if not dictionary_ids: return dict(count=0, data=[], attribute_key=[]) query = query.filter(drug__dictionary_id__in=dictionary_ids) if dictionary_id: query = query.filter(drug__dictionary_id__in=[dictionary_id]) if report_ids: query = query.filter(id__in=report_ids) result_drug_logs = await query.filter(state__in=[DrugUseStateEnum.IN]).prefetch_related('drug', "drug__storage").all() result = list() total_count = 0 offset = (page_no - 1) * page_size attribute_key = await result_drug_logs[0].drug.attribute_drug_info() if result_drug_logs else {} for use_log in result_drug_logs: if not use_log.drug: continue if manufacturer and ((use_log.drug.attribute("cs") and use_log.drug.attribute("cs") != manufacturer) or (use_log.drug.attribute("manufacturer") and use_log.drug.attribute("manufacturer") != manufacturer)): continue total_count += 1 drug_info = await use_log.drug.attribute_drug_info() data = { "id": use_log.id, "drug_info": ",".join(list(map(lambda x: str(x), drug_info.values()))), "expired_at": use_log.drug.expired_at.strftime("%Y-%m-%d %H:%M:%S") if use_log.drug.expired_at else '', "dictionary_id": use_log.drug.dictionary_id, "rfid": use_log.drug.rfid, "net_weight": use_log.drug.attribute("net_weight"), "remain_gross_weight": await use_log.drug.format_weight(), "position": use_log.drug.position, "cas_code": use_log.drug.attribute("cas_code") if use_log.drug.attribute("cas_code") else use_log.drug.attribute("cas"), "manufacturer": use_log.drug.attribute("manufacturer") if use_log.drug.attribute("manufacturer") else use_log.drug.attribute("cs"), "batch_no": use_log.drug.attribute("ph"), "storage_user": use_log.drug.storage.name, "storage_at": use_log.drug.storage_at.strftime("%Y-%m-%d") if use_log.drug.storage_at else "", "state": use_log.drug.state, "created_at": use_log.created_at.strftime("%Y-%m-%d %H:%M:%S"), **drug_info, } if archive_name == "耗材": data.update({ "use_weight": use_log.use_weight, "unit_code": use_log.drug.attribute("unit_code"), # 单位编号 "manufacturer": use_log.drug.attribute("cs") # 生产厂商 }) result.append(data) if page_no: result = result[offset: offset + page_size] return dict(count=total_count, data=result, attribute_key=list(attribute_key.keys())) async def report_take_out_detail_drug(request: Request, keyword): """ 出库明细 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size dictionary_id = keyword.dictionary_id drug_name = keyword.drug_name rfid = keyword.rfid spec = keyword.spec purity = keyword.purity batch_no = keyword.batch_no manufacturer = keyword.manufacturer position = keyword.position report_ids = keyword.report_ids query = QuerySet(DrugUseLog).filter() if rfid: query = query.filter(drug__rfid=rfid) if position: query = query.filter(drug__position=position) if batch_no: query = query.filter(drug__fill_json_content__contains={"ph": batch_no}) if keyword.user_id: query = query.filter(user_id=keyword.user_id) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") archive_id = request.state.archive_id archive_obj = await Archive.get_or_none(id=archive_id) archive_name = archive_obj.name if archive_obj else "" if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) else: # 根据终端筛选 if setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) if drug_name or spec or purity: dict_query = QuerySet(Dictionary) if drug_name: dict_query = dict_query.filter(k1__contains=drug_name) if spec: dict_query = dict_query.filter(k2__contains=spec) if purity: dict_query = dict_query.filter(k3__contains=purity) dictionary_ids = await dict_query.all().values_list("id", flat=True) if not dictionary_ids: return dict(count=0, data=[], attribute_key=[]) query = query.filter(drug__dictionary_id__in=dictionary_ids) if dictionary_id: query = query.filter(drug__dictionary_id__in=[dictionary_id]) if report_ids: query = query.filter(id__in=report_ids) result_drug_logs = await query.filter(state__in=[DrugUseStateEnum.TAKE]).prefetch_related('drug').all() result = list() total_count = 0 offset = (page_no - 1) * page_size attribute_key = await result_drug_logs[0].drug.attribute_drug_info() if result_drug_logs else {} for use_log in result_drug_logs: if not use_log.drug: continue if manufacturer and ((use_log.drug.attribute("cs") and use_log.drug.attribute("cs") != manufacturer) or (use_log.drug.attribute("manufacturer") and use_log.drug.attribute("manufacturer") != manufacturer)): continue total_count += 1 drug_info = await use_log.drug.attribute_drug_info() data = { "id": use_log.id, "drug_info": ",".join(list(map(lambda x: str(x), drug_info.values()))), "expired_at": use_log.drug.expired_at.strftime("%Y-%m-%d %H:%M:%S") if use_log.drug.expired_at else '', "dictionary_id": use_log.drug.dictionary_id, "rfid": use_log.drug.rfid, "net_weight": use_log.drug.attribute("net_weight"), "remain_gross_weight": await use_log.drug.format_weight(), "position": use_log.drug.position, "cas_code": use_log.drug.attribute("cas_code") if use_log.drug.attribute("cas_code") else use_log.drug.attribute("cas"), "manufacturer": use_log.drug.attribute("manufacturer") if use_log.drug.attribute("manufacturer") else use_log.drug.attribute("cs"), "batch_no": use_log.drug.attribute("ph"), "receive_user": use_log.users, "receive_position": use_log.position, "receive_at": use_log.created_at.strftime("%Y-%m-%d %H:%M:%S"), "peer_ids": use_log.peer_ids, "created_at": use_log.created_at.strftime("%Y-%m-%d %H:%M:%S"), **drug_info, } if archive_name == "耗材": data.update({ "use_weight": use_log.use_weight, "unit_code": use_log.drug.attribute("unit_code"), # 单位编号 "manufacturer": use_log.drug.attribute("cs") # 生产厂商 }) result.append(data) if page_no: result = result[offset: offset + page_size] return dict(count=total_count, data=result, attribute_key=list(attribute_key.keys())) async def report_use_drug(request: Request, keyword): """ 使用明细 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size dictionary_id = keyword.dictionary_id drug_name = keyword.drug_name rfid = keyword.rfid spec = keyword.spec purity = keyword.purity batch_no = keyword.batch_no manufacturer = keyword.manufacturer position = keyword.position report_ids = keyword.report_ids query = QuerySet(DrugUseLog).filter() if rfid: query = query.filter(drug__rfid=rfid) if position: query = query.filter(drug__position=position) if batch_no: query = query.filter(drug__fill_json_content__contains={"ph": batch_no}) if keyword.user_id: query = query.filter(user_id=keyword.user_id) if keyword.state: query = query.filter(state=keyword.state) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") archive_id = request.state.archive_id archive_obj = await Archive.get_or_none(id=archive_id) archive_name = archive_obj.name if archive_obj else "" if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) else: # 根据终端筛选 if setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) if drug_name or spec or purity: dict_query = QuerySet(Dictionary) if drug_name: dict_query = dict_query.filter(k1__contains=drug_name) if spec: dict_query = dict_query.filter(k2__contains=spec) if purity: dict_query = dict_query.filter(k3__contains=purity) dictionary_ids = await dict_query.all().values_list("id", flat=True) if not dictionary_ids: return dict(count=0, total_use=0, data=[], attribute_key=[]) query = query.filter(drug__dictionary_id__in=dictionary_ids) if dictionary_id: query = query.filter(drug__dictionary_id__in=[dictionary_id]) if report_ids: query = query.filter(id__in=report_ids) # out_drug_query = QuerySet(Drug).filter(state=DrugStateEnum.OUT) # other_drug_query = QuerySet(Drug).filter(~Q(state=DrugStateEnum.OUT)) # # if keyword.dictionary_id or keyword.drug_name: # if keyword.dictionary_id: # dictionary_ids = [keyword.dictionary_id] # else: # dictionary_ids = await Dictionary.filter(k1__contains=keyword.drug_name).all().values_list("id", flat=True) # # out_drug_query = out_drug_query.filter(dictionary_id__in=dictionary_ids) # other_drug_query = other_drug_query.filter(Q(dictionary_id__in=dictionary_ids)) # # out_drug_ids = await out_drug_query.all().values_list('id', flat=True) # other_drug_ids = await other_drug_query.all().values_list('id', flat=True) # count, result_drug_logs = await query_logs(query, out_drug_ids, other_drug_ids, archive_id) result_drug_logs = await query.filter(state__in=[DrugUseStateEnum.TAKE, DrugUseStateEnum.EMPTY]).prefetch_related('drug').all() result = list() total_count = 0 total_use = 0 offset = (page_no - 1) * page_size attribute_key = await result_drug_logs[0].drug.attribute_drug_info() if result_drug_logs else {} out_count = 0; for use_log in result_drug_logs: if not use_log.drug: # or use_log.state != 2 continue if manufacturer and ((use_log.drug.attribute("cs") and use_log.drug.attribute("cs") != manufacturer) or (use_log.drug.attribute("manufacturer") and use_log.drug.attribute("manufacturer") != manufacturer)): continue return_at, return_position, return_users, use_weight = None, None, None, None total_count += 1 drug_info = await use_log.drug.attribute_drug_info() finally_use_weight_str = '-' if use_log.return_log_id: drug_return_log = await DrugUseLog.get(id=use_log.return_log_id).prefetch_related("drug") # drug = await Drug.get(id=use_log.drug.id) use_weight = drug_return_log.use_weight # 用量计算错误 finally_use_weight = "" if not use_weight and drug_return_log.state != DrugUseStateEnum.PUT else use_weight finally_use_weight_str = drug_return_log.parse_use_weight(finally_use_weight) return_at = drug_return_log.created_at.strftime("%Y-%m-%d %H:%M:%S") return_position = drug_return_log.position return_users = drug_return_log.users # total_use = total_use + use_weight if use_log.drug.state == 3: state = 3 else: state = 1 if use_log.return_log_id else 2 data = { "id": use_log.id, "receive_users": use_log.users, "receive_at": use_log.created_at.strftime("%Y-%m-%d %H:%M:%S"), "receive_position": use_log.position, "return_users": return_users, "return_at": return_at, "return_position": return_position, "drug_info": ",".join(list(map(lambda x: str(x), drug_info.values()))), "state": state, "expired_at": use_log.drug.expired_at.strftime("%Y-%m-%d %H:%M:%S") if use_log.drug.expired_at else '', "use_weight": finally_use_weight_str, "dictionary_id": use_log.drug.dictionary_id, "rfid": use_log.drug.rfid, "net_weight": use_log.drug.attribute("net_weight"), "cas_code": use_log.drug.attribute("cas_code") if use_log.drug.attribute("cas_code") else use_log.drug.attribute("cas"), "manufacturer": use_log.drug.attribute("manufacturer") if use_log.drug.attribute("manufacturer") else use_log.drug.attribute("cs"), "batch_no": use_log.drug.attribute("ph"), **drug_info, } if archive_name == "耗材": data.update({ "use_weight": use_log.use_weight, "unit_code": use_log.drug.attribute("unit_code"), # 单位编号 "manufacturer": use_log.drug.attribute("cs") # 生产厂商 }) if use_log.return_log_id: result.append(data) else: result.insert(out_count, data) out_count+=1 if page_no: result = result[offset: offset + page_size] return dict(count=total_count, total_use=total_use, data=result, attribute_key=list(attribute_key.keys())) async def report_slack_drug(request: Request, keyword): """ 呆滞物料 :param request: :param keyword: :return: """ page_no = keyword.get("page_no") page_size = keyword.get("page_size") slack_day = keyword.get("slack_day", 30) drug_name = keyword.get("drug_name") offset = (page_no - 1) * page_size threshold_time = (datetime.now() - timedelta(days=slack_day)).strftime("%Y-%m-%d") dictionary_ids = list() if drug_name: dictionary_ids = await Dictionary.filter(k1=drug_name).values_list("id", flat=True) query = QuerySet(Drug).filter( Q(last_receive_at__lt=threshold_time) | (Q(last_receive_at__isnull=True) & Q(storage_at__lt=threshold_time)) ) if dictionary_ids: query = query.filter(dictionary_id__in=dictionary_ids) archive_id = request.state.archive_id if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) # 根据终端筛选 elif setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) count = await query.count() if page_no: slack_drug_objs = await query.limit(page_size).offset(offset).order_by("-created_at") else: slack_drug_objs = await query.order_by("-created_at") attribute_key = await slack_drug_objs[0].attribute_drug_info() if slack_drug_objs else {} result = list() now_time = datetime.now(pytz.timezone('Asia/Shanghai')) for drug_obj in slack_drug_objs: now_slack_days = (now_time - drug_obj.last_receive_at).days if drug_obj.last_receive_at else ( now_time - drug_obj.storage_at).days last_use_at = drug_obj.last_return_at.strftime("%Y-%m-%d") if drug_obj.last_return_at else '' attribute_drug = await drug_obj.attribute_drug_info() data = { "drug_id": drug_obj.id, "rfid": drug_obj.rfid, "hole": drug_obj.hole, "cabinet_id": drug_obj.cabinet_id if drug_obj.cabinet_id else await drug_obj.attribute_cabinet_id(), "drawer_id": drug_obj.drawer_id, "board_id": drug_obj.board_id, "position": drug_obj.position, "expired_at": drug_obj.expired_at.strftime("%Y-%m-%d") if drug_obj.expired_at else '-', "remain_gross_weight": await drug_obj.format_weight(), "drug_info": attribute_drug, "now_slack_days": now_slack_days, # 呆滞天数 "last_use_at": last_use_at, # 最后使用时间 "last_user": await drug_obj.attribute_last_user(), # 最后使用人 **attribute_drug, } result.append(data) return dict(count=count, data=result, attribute_key=list(attribute_key.keys())) async def report_put_in_drug(request: Request, keyword): """ 入库统计报表 查询所有入库流转记录,根据药剂字典表分组后统计数量 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size archive_id = request.state.archive_id archive_obj = await Archive.get_or_none(id=archive_id) archive_name = archive_obj.name if archive_obj else "" if archive_name == "耗材": # query = QuerySet(Drug).filter(state=DrugStateEnum.IN) query = QuerySet(DrugUseLog).filter(state=DrugUseStateEnum.IN) else: query = QuerySet(DrugUseLog).filter(state=DrugUseStateEnum.IN) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") # if not keyword.stime and not keyword.etime: # stime = datetime.now() - timedelta(days=365) # etime = datetime.now() + timedelta(days=1) # query = query.filter(created_at__gte=stime, created_at__lte=etime) cabinets_ids = [] if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) # 根据终端筛选 elif setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) if keyword.drug_name or keyword.spec or keyword.dictionary_id: dictionary_ids = await get_dictionary_ids(keyword.drug_name, keyword.spec, keyword.dictionary_id) if not dictionary_ids: return dict(count=0, data=[], attribute_key=[]) query = query.filter(drug__dictionary__id__in=dictionary_ids) if keyword.report_ids: query = query.filter(drug__dictionary__id__in=keyword.report_ids) if keyword.cas_code: query = query.filter(Q(drug__fill_json_content__contains={"cas": keyword.cas_code}) | Q(drug__fill_json_content__contains={"cas_code": keyword.cas_code})) query = query.annotate(count=Count(1)) if keyword.custom_num: query = query.filter(count=keyword.custom_num) query = query.group_by("drug__dictionary__id") if page_no: offset = (page_no - 1) * page_size count = await query.values("drug__dictionary__id", "drug__template__id", "count") count = len(count) if count else 0 data_list = await (query.limit(page_size).offset(offset) .values("drug__dictionary__id", "drug__template__id","count")) else: data_list = await query.values("drug__dictionary__id", "drug__template__id", "count") count = len(data_list) if data_list else 0 data = list() attribute_key = {} for i in data_list: dictionary_obj = await Dictionary.get_or_none(id=i.get("drug__dictionary__id")) if not dictionary_obj: continue template_obj = await Template.get(id=i.get("drug__template__id")) drug_obj = await Drug.filter(dictionary=i.get("drug__dictionary__id")).first() parse_fill_json_content = await drug_obj.parse_fill_json_content() drug_info = await dictionary_obj.attribute_dictionary_info(template_obj) print("drug_info", drug_info) json_data = {} for n in parse_fill_json_content: json_data={ "name":drug_info.get("试剂名称") if archive_name != "耗材" else drug_info.get("耗材名称"), "purity":drug_info.get("试剂纯度"), "speci":drug_info.get("试剂规格"), "count":i.get("count"), "expired_at":drug_obj.expired_at, "manufacturer":parse_fill_json_content['厂商'] if '厂商' in parse_fill_json_content else '', "distribution ":parse_fill_json_content['经销单位'] if '经销单位' in parse_fill_json_content else '', "storage_at":drug_obj.storage_at } data.append({ "parse_fill_json_content":json_data, "drug_info": drug_info, "cas_code": drug_obj.attribute("cas_code") if drug_obj.attribute("cas_code") else drug_obj.attribute("cas"), "count": i.get("count"), "dictionary_id": i.get("drug__dictionary__id"), **drug_info }) attribute_key = drug_info return dict(count=count, data=data, attribute_key=list(attribute_key.keys())) async def report_take_out_drug(request: Request, keyword): """ 出库信息汇总 查询所有出库流转记录,根据药剂字典表分组后统计数量 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size archive_id = request.state.archive_id query = QuerySet(DrugUseLog).filter(state=DrugUseStateEnum.TAKE) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") cabinets_ids = [] if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) # 根据终端筛选 elif setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() if cabinets_ids: query = query.filter(cabinet_id__in=cabinets_ids) if keyword.drug_name or keyword.spec or keyword.dictionary_id: dictionary_ids = await get_dictionary_ids(keyword.drug_name, keyword.spec, keyword.dictionary_id) if not dictionary_ids: return dict(count=0, data=[], attribute_key=[]) query = query.filter(drug__dictionary__id__in=dictionary_ids) if keyword.report_ids: query = query.filter(drug__dictionary__id__in=keyword.report_ids) if keyword.cas_code: query = query.filter(Q(drug__fill_json_content__contains={"cas": keyword.cas_code}) | Q(drug__fill_json_content__contains={"cas_code": keyword.cas_code})) query = query.annotate(count=Count(1)) if keyword.custom_num: query = query.filter(count=keyword.custom_num) query = query.group_by("drug__dictionary__id") if page_no: offset = (page_no - 1) * page_size count = await query.values("drug__dictionary__id", "drug__template__id", "count") count = len(count) if count else 0 data_list = await (query.limit(page_size).offset(offset) .values("drug__dictionary__id", "drug__template__id","count")) else: data_list = await query.values("drug__dictionary__id", "drug__template__id", "count") count = len(data_list) if data_list else 0 data = list() attribute_key = {} for i in data_list: dictionary_obj = await Dictionary.get_or_none(id=i.get("drug__dictionary__id")) if not dictionary_obj: continue template_obj = await Template.get(id=i.get("drug__template__id")) drug_obj = await Drug.filter(dictionary=i.get("drug__dictionary__id")).first() drug_info = await dictionary_obj.attribute_dictionary_info(template_obj) data.append({ "drug_info": drug_info, "cas_code": drug_obj.attribute("cas_code") if drug_obj.attribute("cas_code") else drug_obj.attribute("cas"), "count": i.get("count"), "dictionary_id": i.get("drug__dictionary__id"), **drug_info }) attribute_key = drug_info return dict(count=count, data=data, attribute_key=list(attribute_key.keys())) async def get_dictionary_ids(drug_name: str | None, spec: str | None, dictionary_id: str | None): dict_query = QuerySet(Dictionary).filter() if drug_name or spec: if drug_name: dict_query = dict_query.filter(k1__icontains=drug_name) if spec: dict_query = dict_query.filter(k2=spec) if dictionary_id: dict_query = dict_query.filter(id=dictionary_id) dictionary_ids = await dict_query.filter().all().values_list("id", flat=True) return dictionary_ids async def report_remain_drug(request: Request, keyword): """ 库存信息汇总(原 库存量统计) 所有在库与出库药剂数量统计 排序,根据瓶数降序排列 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size archive_id = request.state.archive_id cabinets_ids = list() if keyword.cabinet_ids: cabinets_ids = keyword.cabinet_ids else: if archive_id: cabinets_ids = await parse_archive_cabinet_ids(archive_id, []) # 根据终端筛选 elif setting.TERMINAL_ID: cabinets_ids = await parse_cabinet_ids() drug_query = QuerySet(Drug).filter(state__in=[DrugStateEnum.IN, DrugStateEnum.OUT]) if keyword.drug_name or keyword.spec or keyword.dictionary_id: dictionary_ids = await get_dictionary_ids(keyword.drug_name, keyword.spec, keyword.dictionary_id) if not dictionary_ids: return dict(count=0, data=[], attribute_key=[]) drug_query = drug_query.filter(dictionary_id__in=dictionary_ids) if keyword.report_ids: drug_query = drug_query.filter(dictionary_id__in=keyword.report_ids) if cabinets_ids: drug_query = drug_query.filter(cabinet_id__in=cabinets_ids) # if keyword.position: # drug_query = drug_query.filter(position=keyword.position) if keyword.cas_code: drug_query = drug_query.filter(Q(fill_json_content__contains={"cas": keyword.cas_code}) | Q(fill_json_content__contains={"cas_code": keyword.cas_code})) if keyword.custom_num: drug_query = drug_query.filter(count=keyword.custom_num) drug_counts = await drug_query.prefetch_related("dictionary").annotate(count=Count('id')).group_by( 'dictionary_id').order_by("-count").values( "dictionary_id", "count", "template_id") offset = (page_no - 1) * page_size count = len(drug_counts) if page_no: drug_offset_counts = drug_counts[offset: offset + page_size] else: drug_offset_counts = drug_counts data = list() template_dict = {} attribute_key = {} for i in drug_offset_counts: dictionary_id = i.get("dictionary_id") dictionary_obj = await Dictionary.get(id=dictionary_id) # 避免多次重复查询模板信息 template_id = i.get("template_id") template_obj = template_dict.get(template_id) if template_obj is None: template_obj = await Template.get(id=template_id) template_dict[template_id] = template_obj drug_info = await dictionary_obj.attribute_dictionary_info(template_obj) drug_objs = await Drug.filter(dictionary_id = dictionary_id).all() drug_obj = drug_objs[0] total_count = sum([int(drug_obj.attribute("total_count")) for drug_obj in drug_objs if drug_obj.attribute("total_count")]) use_count = sum([drug_obj.total_use_weight for drug_obj in drug_objs if drug_obj.total_use_weight]) remain_count = total_count - use_count data.append({ "drug_info": drug_info, "cas_code": drug_obj.attribute("cas_code") if drug_obj.attribute("cas_code") else drug_obj.attribute("cas"), "count": i.get("count"), "dictionary_id": str(i.get("dictionary_id")), "remain_count": remain_count, **drug_info }) attribute_key = drug_info return dict(count=count, data=data, attribute_key=list(attribute_key.keys())) async def report_dosage_drug(request: Request, keyword): """ 药剂用量报表 :param request: :param keyword: :return: """ page_no = keyword.page_no page_size = keyword.page_size query = QuerySet(Dictionary).filter() # 字典按大类划分 archive_id = request.state.archive_id if keyword.drug_name or keyword.spec: if keyword.drug_name: query = query.filter(k1__icontains=keyword.drug_name) if keyword.spec: query = query.filter(k2=keyword.spec) elif keyword.dictionary_id: query = query.filter(id=keyword.dictionary_id) elif archive_id: query = query.filter(archive_id=archive_id) if keyword.report_ids: query = query.filter(id__in=keyword.report_ids) dictionary_objs = await query.all() data = list() info = "" attribute_key = {} query = QuerySet(DrugUseLog) if keyword.stime: query = query.filter(created_at__gte=f"{keyword.stime} 00:00:00") if keyword.etime: query = query.filter(created_at__lte=f"{keyword.etime} 23:59:59") if keyword.cas_code: query = query.filter(Q(drug__fill_json_content__contains={"cas": keyword.cas_code}) | Q(drug__fill_json_content__contains={"cas_code": keyword.cas_code})) for dictionary_obj in dictionary_objs: drug_use_log_objs = await query.filter(drug__dictionary=dictionary_obj).prefetch_related( 'drug') use_num = sum([1 for i in drug_use_log_objs if i.use_weight]) total_use_weight = sum([i.use_weight for i in drug_use_log_objs if i.use_weight]) if not total_use_weight: continue if keyword.custom_num and keyword.custom_num != use_num: continue drug_info = {} if drug_use_log_objs: template_obj = await drug_use_log_objs[0].drug.template drug_info = await dictionary_obj.attribute_dictionary_info(template_obj) drug = await Drug.filter(dictionary_id=dictionary_obj.id).first() if total_use_weight > 1000: weight_str = f"{milligram_to_gram(total_use_weight)}g" else: weight_str = f"{total_use_weight}mg" density = drug.attribute("density") # 密度 if density: volume = gram_to_milliliter(milligram_to_gram(total_use_weight), density) if not volume: print(f"密度格式错误:{density}") info += f"密度格式错误:{density} " weight_str = f"{weight_str}" else: weight_str = f"{weight_str}({volume}ml)" data.append({ "total_use_weight": weight_str, "use_num": use_num, "cas_code": drug.attribute("cas_code") if drug.attribute("cas_code") else drug.attribute("cas"), "drug_info": drug_info, "dictionary_id": dictionary_obj.id, **drug_info }) attribute_key = drug_info offset = (page_no - 1) * page_size count = len(data) if page_no: result = data[offset: offset + page_size] else: result = data desc = "成功" if not info else info return dict(desc=desc, count=count, data=result, attribute_key=list(attribute_key.keys())) async def report_expire_drug(request: Request, keyword): """ 药剂过期报表 :param request: :param keyword: :return: """ # result = await get_already_expired(**{"drug_name": keyword.drug_name}) result = await get_already_expired() attribute_key = {} if result: drug_id = result[0].get("drug_id") drug_obj = await Drug.filter(id=drug_id).prefetch_related("dictionary", "template").first() attribute_key = await drug_obj.dictionary.attribute_dictionary_info(drug_obj.template) return dict(data=result, attribute_key=list(attribute_key.keys())) async def report_cabinet_environmental(request: Request, keyword): """ 环境温度记录 :param request: :param keyword: :return: """ page_no = keyword.get("page_no") page_size = keyword.get("page_size") cabinet_id = keyword.get("cabinet_id") stime = keyword.get("stime") etime = keyword.get("etime") offset = (page_no - 1) * page_size query = QuerySet(EnvironmentLogs).filter() if setting.TERMINAL_ID: query = query.filter(cabinet__terminal=setting.TERMINAL_ID) # 都为空则不显示 query = query.filter( Q(left_temperature__isnull=False) | Q(right_temperature__isnull=False) | Q(voc__isnull=False) | Q( humidity__isnull=False)) if cabinet_id: query = query.filter(cabinet_id=cabinet_id) if stime: query = query.filter(created_at__gte=f"{stime} 00:00:00") if etime: query = query.filter(created_at__lte=f"{etime} 23:59:59") if not stime and not etime: stime = datetime.now() - timedelta(days=30) etime = datetime.now() query = query.filter(created_at__gte=stime, created_at__lte=etime) count = await query.count() if page_no: en_log_objs = await query.prefetch_related("cabinet").limit(page_size).offset(offset).order_by("-created_at") else: en_log_objs = await query.prefetch_related("cabinet").order_by("-created_at") result = list() for en_log_obj in en_log_objs: a = [en_log_obj.left_temperature, en_log_obj.right_temperature] true_values = [str(item) for item in a if item] temperature = ','.join(true_values) if len(true_values) == 2 else (true_values[0] if len(true_values) == 1 else "-") result.append({ **jsonable_encoder(en_log_obj), "cabinet_label": en_log_obj.cabinet.label, "temperature": temperature, "created_at": en_log_obj.created_at.strftime("%Y-%m-%d %H:%M:%S"), }) return dict(desc="成功", count=count, data=result, attribute_key=[])