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.

1117 lines
46 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.

#!/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=[])