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.
 
 
 
 
 

473 lines
22 KiB

# -*- coding: utf-8 -*-
"""
api.stock
~~~~~~~~~~~~~~
有关进出库的接口.
:copyright: 云南新八达科技有限公司.
:author: 李进才.
"""
import gevent
from diff.stock import getDiffStockList
from utils import instockHelper
from utils.PageHepler import db_page, entityDictToStringDict, db_page_entity
from utils.apiDoc import *
from models.stockListModel import *
from models.InStockModel import *
from utils.configOperatingTypeHelper import GetOperatingTypeInStock, GetOperatingTypeDelete, GetOperatingTypeUpdate, \
GetOperatingTypeEdit
from utils.entryHelper import get_entry_list
from utils.listHelper import *
from utils.BatchCode import *
from models.reagentTypeList import *
from pypinyin import lazy_pinyin, Style
from io import BytesIO
import pandas as pd
from utils.nativeDbHelper import HisMssqlConnect
from utils.outStockHelper import *
from sqlalchemy import or_, func
from utils.ReagentTypeListSort import *
from utils.pandasHelper import null_value
@stock.route('/list')
class StockList(Resource):
@staticmethod
def post():
"""
get stock info list
:return: stock list
"""
data = request.args
filterObject = getDiffStockList()
if data.get('query') is not None and data.get('query') != '':
filterObject = filterObject.filter(or_(ReagtStock.PinYinCode.contains(data['query']),
ReagtStock.Position.contains(data['query']),
ReagtReagent.Name.contains(data['query']),
ReagtStock.Code.contains(data['query'])))
if data.get('groupName') is not None and data.get('groupName') != '':
filterObject = filterObject.filter(ReagtReagent.GroupName == data['groupName'])
if data.get('reportItemName') is not None and data.get('reportItemName') != '':
filterObject = filterObject.filter(ReagtReagent.ReportItem == data.get('reportItemName'))
data_list = db_page(filterObject, ReagtStock.InTime, data, 10)
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': filterObject.count(), 'list': data_list}, None)
@stock.route('/add')
class StockAdd(Resource):
"""
试剂耗材入库
"""
@staticmethod
@stock.doc(body=[in_stock_model])
def post():
token = request.headers.get('X-Token')
batchCode = GetBatchCode()
inStockTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
for item in request.json['inStockData']:
data = Dict2Obj(item)
instockHelper.in_stock(data, batchCode, inStockTime, token, request.json)
try:
db.session.commit()
except gevent.Timeout:
db.session.invalidate()
raise
return SuccessResponse(ResultCode.ERROR, None, None)
except Exception:
db.session.rollback()
raise
return SuccessResponse(ResultCode.ERROR, None, None)
return SuccessResponse(ResultCode.SUCCESS,
{'inStockBatchCode': batchCode, 'verifyPeople': verify_jwt_username(token)}, None)
@stock.route('/hisOutCodeList')
class HisOutCodeList(Resource):
"""
his出库单列表
"""
@staticmethod
def get():
reagent_int_int_code = db.session.query(ReagtReceipt.ReceiptCode.label('ReceiptCode')) \
.filter(ReagtReceipt.ReceiptCode.contains('E')) \
.group_by(ReagtReceipt.ReceiptCode).all()
reagent_int_int_code_string = ','.join(F'\'{str(code)[2:-2]}' for code in reagent_int_int_code)
if reagent_int_int_code_string is '':
his_out_list_code = HisMssqlConnect() \
.query("LIS_OutSheet_CL", F"select 出库单号,出库日期 from LIS_OutSheet_CL(nolock) "
F"where 出库名称 = '检验科' "
F"group by 出库单号,出库日期 "
F"ORDER BY 出库日期 DESC", cols=['出库单号', '出库日期']) \
.drop_duplicates()
else:
his_out_list_code = HisMssqlConnect() \
.query("LIS_OutSheet_CL", F"select 出库单号,出库日期 from LIS_OutSheet_CL(nolock) "
F"where 出库名称 = '检验科' "
F"and 出库单号 not in ({reagent_int_int_code_string}) "
F"group by 出库单号,出库日期 "
F"ORDER BY 出库日期 DESC", cols=['出库单号', '出库日期']) \
.drop_duplicates()
if request.args.get('query') is not None:
his_out_list_code = HisMssqlConnect() \
.query("LIS_OutSheet_CL",
F"select * from LIS_OutSheet_CL(nolock) where "
F"出库名称 = '检验科' and 出库单号 like '%{str.strip(request.args.get('query'))}%'") \
.drop_duplicates()
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': len(his_out_list_code),
'list': dataFrame_paginate(his_out_list_code,
request.args.get('pageNumber'), 10, 10)
.to_dict()},
None)
@stock.route('/hisOutList')
class HisOutList(Resource):
"""
出库单对应的试剂或者耗材列表
"""
@staticmethod
def get():
his_out_list = HisMssqlConnect() \
.query("LIS_OutSheet_CL",
F"select * from LIS_OutSheet_CL(nolock) where 出库名称 = '检验科' and 出库单号='{request.args.get('outCode')}'")
his_out_list_page = dataFrame_paginate(his_out_list, request.args.get('pageNumber'), 10, 10).to_dict()
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': len(his_out_list),
'list': his_out_list_page}, None)
@stock.route('/hisListExport')
class HisListExport(Resource):
"""
his出库的文件下载
"""
@staticmethod
def get():
if request.args.get('outCode') is not None:
his_out_list = HisMssqlConnect() \
.query("LIS_OutSheet_CL",
F"select * from LIS_OutSheet_CL(nolock) "
F"where 出库名称 = '检验科' and 出库单号='{request.args.get('outCode')}'")
else:
reagent_int_int_code = db.session.query(ReagtReceipt.ReceiptCode.label('ReceiptCode')) \
.filter(ReagtReceipt.ReceiptCode.contains('E')) \
.group_by(ReagtReceipt.ReceiptCode).all()
reagent_int_int_code_string = ','.join(F'\'{str(code)[2:-2]}' for code in reagent_int_int_code)
his_out_list = HisMssqlConnect() \
.query("LIS_OutSheet_CL",
F"select * from LIS_OutSheet_CL(nolock) "
F"where 出库名称 = '检验科' and 出库单号 not in ({reagent_int_int_code_string})"
F"ORDER BY 出库日期 DESC")
his_out_list.drop(his_out_list.columns[[i for i in range(1, 5)]], axis=1, inplace=True)
bio = BytesIO()
his_out_list.style.applymap(null_value, subset=['耗材名称', '耗材规格', '生产厂家',
'存放位置', '耗材类型', '最大单位',
'进价(元) 批发价(批发单位)', '售价(元) 零售价(批发单位)',
'最大库存量(大单位为主)', '出库数量(批发单位)',
'有效期']) \
.to_excel(bio, index=False, encoding='utf-8')
bio.seek(0)
fileByte = bio.getvalue()
bio.close()
return Response(fileByte, content_type='application/vnd.ms-excel')
@stock.route('/delete')
class Delete(Resource):
"""
删除试剂或者耗材
"""
@staticmethod
def get():
token = request.headers.get('X-Token')
data = request.args
app.logger.info(data)
delete_stock = ReagtStock.query.filter_by(StockId=int(data.get('StockId'))).first()
if 'E' in delete_stock.Code:
return SuccessResponse(ResultCode.NOT_ALLOW_DELETE_HIS_IN_STOCK_INTO, None, None)
db.session.delete(delete_stock)
LogAdd(token, GetOperatingTypeDelete(), data, delete_stock.Code, data.get('Name'),
list2String(lazy_pinyin(data.get('Name') + data.get('Specification'), style=Style.FIRST_LETTER)),
data.get('LastNumber'), data.get('Specification'), data.get('Position'),
reagentId=delete_stock.ReagentId)
db.session.commit()
return SuccessResponse(ResultCode.SUCCESS, None, None)
@stock.route('/receiptDelete')
class ReceiptDelete(Resource):
"""
从入库单删除整个入库信息
"""
@staticmethod
def get():
token = request.headers.get('X-Token')
data = request.args
app.logger.info(data)
delete_stock_list = ReagtStock.query.filter_by(Code=data.get('Code')).all()
delete_receipt = ReagtReceipt.query.filter_by(ReceiptCode=data.get('Code')).first()
db.session.delete(delete_receipt)
for delete_stock in delete_stock_list:
db.session.delete(delete_stock)
reagent = ReagtReagent.query.filter_by(ReagentId=delete_stock.ReagentId).first()
LogAdd(token, GetOperatingTypeDelete(), data, delete_stock.Code, reagent.Name,
list2String(lazy_pinyin(reagent.Name + reagent.Specification, style=Style.FIRST_LETTER)),
delete_stock.LastNumber, reagent.Specification, delete_stock.Position,
reagentId=delete_stock.ReagentId, remark='删除his入库信息')
db.session.commit()
return SuccessResponse(ResultCode.SUCCESS, None, None)
@stock.route('/typeList')
class TypeList(Resource):
"""
按照汇总分类列表
"""
@staticmethod
def post():
data = request.args
filterObject = ReagtReagent.query.join(ReagtStock,
ReagtStock.ReagentId == ReagtReagent.ReagentId).distinct().order_by(
ReagtReagent.ReagentId.desc())
if data.get('query') is not None:
filterObject = ReagtReagent.query.join(ReagtStock,
ReagtStock.ReagentId == ReagtReagent.ReagentId) \
.filter(or_(ReagtStock.PinYinCode.contains(data['query']), ReagtReagent.Name.contains(data['query']))) \
.distinct().order_by(ReagtReagent.ReagentId.desc())
reagentBasicsPaginate = filterObject.paginate(
int(data['pageNumber']), 10,
error_out=False)
reagentTypeList = []
if reagentBasicsPaginate.items is not None:
for reagent in reagentBasicsPaginate.items:
reagentType = ReagentTypeList(ReagentId=reagent.ReagentId, Name=reagent.Name,
Specification=reagent.Specification,
Maker=reagent.Maker, CertificationCode=reagent.CertificationCode,
UnitPrice=reagent.UnitPrice, SellingPrice=reagent.SellingPrice,
MaxValue=reagent.MaxValue, MinValue=reagent.MinValue,
TypeName=reagent.TypeName, hasChildren=True)
reagentTypeList.append(reagentType.value())
return SuccessResponse(ResultCode.SUCCESS, {"totalNumber": filterObject.count(),
"list": ReagentTypeSort(reagentTypeList)}, None)
@stock.route('/typeInfo')
class TypeInfo(Resource):
"""
汇总分类下的子信息
"""
@staticmethod
def get():
data = request.args
reagentStockInfo = ReagtStock.query.filter_by(ReagentId=data['ReagentId']).all()
return SuccessResponse(ResultCode.SUCCESS, reagentStockInfo, None)
@stock.route('/outStockList')
class OutStockList(Resource):
"""
出库列表
"""
@staticmethod
def get():
data = request.args
outStockReagentFilter = db.session.query(ReagtReagent.Name.label('Name'),
ReagtReagent.Specification.label('Specification'),
ReagtStock.Position.label('Position'),
ReagtReagent.Unit.label('Unit'),
ReagtReagent.SmallestUnit.label('SmallestUnit'),
ReagtReagent.Ratio.label('Ratio'),
ReagtStock.ProductionBatch.label('ProductionBatch'),
func.sum(ReagtStock.LastNumber).label('TotalNumber'),
func.sum(ReagtStock.MinNumberUnit).label('MinNumberUnit')). \
join(ReagtReagent, ReagtStock.ReagentId == ReagtReagent.ReagentId). \
group_by(ReagtReagent.Name, ReagtStock.ReagentId, ReagtStock.Position, ReagtReagent.Specification,
ReagtReagent.Unit, ReagtReagent.SmallestUnit, ReagtReagent.Ratio, ReagtStock.ProductionBatch)
if data.get('query') is not None and data.get('query') != '':
outStockReagentFilter = outStockReagentFilter.filter(
or_(ReagtReagent.Name.contains(data['query']), ReagtStock.Position.contains(data['query']),
ReagtReagent.Specification.contains(data['query']), ReagtStock.PinYinCode.contains(data['query'])))
if data.get('groupName') is not None and data.get('groupName') != '':
outStockReagentFilter = outStockReagentFilter.filter(ReagtReagent.GroupName == data.get('groupName'))
if data.get('reportItemName') is not None and data.get('reportItemName') != '':
outStockReagentFilter = outStockReagentFilter.filter(ReagtReagent.ReportItem == data.get('reportItemName'))
outStockReagentPage = outStockReagentFilter.order_by(ReagtStock.Position.desc()).paginate(
int(data['pageNumber']), 10,
error_out=False)
resultList = [dict(zip(result.keys(), result)) for result in outStockReagentPage.items]
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': outStockReagentFilter.count(),
'list': resultList}, None)
@stock.route('/outStock')
class OutStock(Resource):
"""
出库试剂或者耗材
"""
@staticmethod
def post():
token = request.headers.get('X-Token')
for item in request.json['outStockData']:
priorityDelivery(item, 1, token, request.json)
return SuccessResponse(ResultCode.SUCCESS,
{'outStockBatchCode': GetBatchCode(), 'verifyPeople': verify_jwt_username(token)}, None)
@stock.route('/update')
class Update(Resource):
"""
调整库存信息
"""
@staticmethod
def post():
token = request.headers.get('X-Token')
reagent_stock = ReagtStock.query.filter_by(StockId=request.json.get('StockId')).first()
data = {'Remark': '库存数量调整,大单位剩余数量由' + str(reagent_stock.LastNumber) + '调整为' +
str(request.json.get('ChangeNumber')) + '小单位数量由' + str(
reagent_stock.MinNumberUnit) + '调整为' +
str(request.json.get('ChangeMinUnitNumber'))}
if request.json.get('ChangeNumber') is 0 and request.json.get('ChangeMinUnitNumber') is 0:
db.session.delete(reagent_stock)
db.session.commit()
else:
reagent_stock.LastNumber = request.json.get('ChangeNumber')
reagent_stock.MinNumberUnit = request.json.get('ChangeMinUnitNumber')
db.session.commit()
reagent_reagent = ReagtReagent.query.filter_by(ReagentId=reagent_stock.ReagentId).first()
LogAdd(token, GetOperatingTypeUpdate(), data, reagent_stock.Code, reagent_reagent.Name,
list2String(lazy_pinyin(reagent_reagent.Name + reagent_reagent.Specification, style=Style.FIRST_LETTER)),
request.json.get('ChangeNumber'), reagent_reagent.Specification, reagent_stock.Position)
db.session.commit()
return SuccessResponse(ResultCode.SUCCESS, None, None)
@stock.route('/barCode')
class BarCode(Resource):
"""
条码出库信息,根据条码查询当前试剂或者耗材信息
"""
@staticmethod
def get():
data = request.args
filterObject = getDiffStockList().filter(ReagtStock.BarCode == data.get('barCode'))
return SuccessResponse(ResultCode.SUCCESS, db_page(filterObject, ReagtStock.InTime, data, 1)
, None)
@stock.route('/barCodeHistory')
class BarCodeHistory(Resource):
"""
条码出库历史
"""
@staticmethod
def get():
data = request.args
filterObject = db.session.query(ReagtLog.OperatingTime,
ReagtLog.Code,
ReagtLog.BarCode,
ReagtLog.LogId,
ReagtLog.OperatingPeople,
ReagtLog.ReagentName,
ReagtLog.ReagentNumber,
ReagtLog.ReagentPosition,
ReagtLog.ReagentSpecification,
ReagtLog.Remark).filter(ReagtLog.OperatingType == 'OutStock')
return SuccessResponse(ResultCode.SUCCESS, db_page(filterObject, ReagtLog.OperatingTime, data, 5), None)
@stock.route('/barCodeOutStock')
class BarCodeOutStock(Resource):
"""
条码出库
"""
@staticmethod
def get():
date = request.args
outStockData = ReagtStock.query.filter_by(BarCode=date.get('barCode')).first()
if outStockData.LastNumber > date.get('outNumber'):
outStockData.LastNumber -= date.get('outNumber')
else:
db.session.delete(outStockData)
db.session.commit()
@stock.route('/editStock')
class EditStock(Resource):
"""
编辑库存
"""
@staticmethod
def post():
token = request.headers.get('X-Token')
log_info = ''
current_stock = ReagtStock.query.filter_by(StockId=request.json.get('StockId')).first()
current_reagent = ReagtReagent.query.filter_by(ReagentId=current_stock.ReagentId).first()
if current_stock.ProductionBatch != request.json.get('ProductionBatch'):
log_info += '将生产批次号从' + str(current_stock.ProductionBatch) + '修改为' + str(
request.json.get('ProductionBatch'))
current_stock.ProductionBatch = request.json.get('ProductionBatch')
if current_stock.Position != request.json.get('Position'):
log_info += '将耗材位置信息从' + str(current_stock.Position) + '修改为' + str(request.json.get('Position'))
current_stock.Position = request.json.get('Position')
data = {'Remark': log_info}
LogAdd(token, GetOperatingTypeEdit(), data, current_stock.Code, current_reagent.Name,
current_reagent.PinYinCode, 0, current_reagent.Specification,
current_stock.Position)
db.session.commit()
return SuccessResponse(ResultCode.SUCCESS, None, None)
@stock.route('/noGroupList')
class NoGroupList(Resource):
@staticmethod
def post():
"""
get no group stock info list
:return: no group stock list
"""
data = request.args
filterObject = ReagtReagent.query.filter(
or_(ReagtReagent.GroupName == None, ReagtReagent.GroupName == '')).filter(ReagtReagent.Using == True)
if data.get('query') is not None and data.get('query') != '':
filterObject = ReagtReagent.query.filter(or_(
ReagtReagent.Name.contains(data['query']),
ReagtReagent.PinYinCode.contains(data['query']))) \
.filter(ReagtReagent.GroupName == None).filter(ReagtReagent.Using == True)
if data.get('groupName') is not None and data.get('groupName') != '':
filterObject = ReagtReagent.query.filter(ReagtReagent.GroupName == data.get('groupName')).filter(ReagtReagent.Using == True)
data_list = db_page_entity(filterObject, data, 10)
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': filterObject.count(), 'list': data_list}, None)
@stock.route('/setGroup')
class SetGroup(Resource):
@staticmethod
def post():
for item in request.json['groupData']:
item = Dict2Obj(item)
reagent_info = ReagtReagent.query.filter_by(ReagentId=item.ReagentId).first()
reagent_all = ReagtReagent.query.filter_by(Name=item.Name).all()
for reagent_item in reagent_all:
reagent_item.GroupName = request.json['groupName']
reagent_item.ReportItem = request.json['reportName']
reagent_info.GroupName = request.json['groupName']
reagent_info.ReportItem = request.json['reportName']
db.session.commit()
return SuccessResponse(ResultCode.SUCCESS, None, None)