parent
720ec5be6b
commit
3419abc974
327 changed files with 52049 additions and 0 deletions
Binary file not shown.
@ -0,0 +1,8 @@ |
||||
# Default ignored files |
||||
/shelf/ |
||||
/workspace.xml |
||||
# Datasource local storage ignored files |
||||
/dataSources/ |
||||
/dataSources.local.xml |
||||
# Editor-based HTTP Client requests |
||||
/httpRequests/ |
@ -0,0 +1,12 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<module type="PYTHON_MODULE" version="4"> |
||||
<component name="NewModuleRootManager"> |
||||
<content url="file://$MODULE_DIR$" /> |
||||
<orderEntry type="jdk" jdkName="Python 3.7 (code)" jdkType="Python SDK" /> |
||||
<orderEntry type="sourceFolder" forTests="false" /> |
||||
</component> |
||||
<component name="PyDocumentationSettings"> |
||||
<option name="format" value="PLAIN" /> |
||||
<option name="myDocStringFormat" value="Plain" /> |
||||
</component> |
||||
</module> |
@ -0,0 +1,14 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="PublishConfigData" serverName="ubuntu@www.summerlost.com:22" remoteFilesAllowedToDisappearOnAutoupload="false"> |
||||
<serverData> |
||||
<paths name="ubuntu@www.summerlost.com:22"> |
||||
<serverdata> |
||||
<mappings> |
||||
<mapping deploy="/docker/python3.7/" local="$PROJECT_DIR$" web="/" /> |
||||
</mappings> |
||||
</serverdata> |
||||
</paths> |
||||
</serverData> |
||||
</component> |
||||
</project> |
@ -0,0 +1,6 @@ |
||||
<component name="InspectionProjectProfileManager"> |
||||
<settings> |
||||
<option name="USE_PROJECT_PROFILE" value="false" /> |
||||
<version value="1.0" /> |
||||
</settings> |
||||
</component> |
@ -0,0 +1,7 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="Black"> |
||||
<option name="sdkName" value="Python 3.7 (code)" /> |
||||
</component> |
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (code)" project-jdk-type="Python SDK" /> |
||||
</project> |
@ -0,0 +1,8 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="ProjectModuleManager"> |
||||
<modules> |
||||
<module fileurl="file://$PROJECT_DIR$/.idea/code.iml" filepath="$PROJECT_DIR$/.idea/code.iml" /> |
||||
</modules> |
||||
</component> |
||||
</project> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="SqlDialectMappings"> |
||||
<file url="file://$PROJECT_DIR$/api/stock.py" dialect="GenericSQL" /> |
||||
</component> |
||||
</project> |
@ -0,0 +1,8 @@ |
||||
import os |
||||
import pkgutil |
||||
|
||||
pkg_path = os.path.dirname(__file__) |
||||
pkg_name = os.path.basename(pkg_path) |
||||
|
||||
for _, file, _ in pkgutil.iter_modules([pkg_path]): |
||||
__import__(pkg_name + '.' + file) |
@ -0,0 +1,53 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
api.user |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
有关用户操作的接口. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from sqlalchemy import func, or_ |
||||
|
||||
from utils.apiDoc import * |
||||
from utils.PageHepler import * |
||||
from utils.configOperatingTypeHelper import GetOperatingTypeOutStock |
||||
|
||||
|
||||
@accounting.route('/instrumentList') |
||||
class InstrumentList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
dictFilter = db.session.query(DictInstrument.InsName.label('InsName'), |
||||
func.count(RptCheckresult.SampleCode).label('orderNumber')) \ |
||||
.join(RptCheckresult, func.substring(RptCheckresult.SampleCode, 1, 2) == DictInstrument.SampleCode) \ |
||||
.filter(RptCheckresult.TestDate >= request.args.get('startTime')) \ |
||||
.filter(RptCheckresult.TestDate <= request.args.get('endTime')) \ |
||||
.group_by(DictInstrument.InsName) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'list': db_page(dictFilter, |
||||
DictInstrument.InsName, |
||||
request.args, 6), |
||||
'totalNumber': dictFilter.count()}, None) |
||||
|
||||
|
||||
@accounting.route('/reagentOutList') |
||||
class ReagentOutList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
query = request.args.get('query') |
||||
reagent_out_filter = db.session.query(ReagtLog.ReagentName, |
||||
ReagtLog.ReagentSpecification, |
||||
func.sum(ReagtLog.ReagentNumber).label('ReagentNumber'), |
||||
func.sum(ReagtLog.OperateMinNumber).label('OperateMinNumber'))\ |
||||
.filter(ReagtLog.OperatingType == GetOperatingTypeOutStock()) \ |
||||
.filter(ReagtLog.OperatingTime >= request.args.get('startTime')) \ |
||||
.filter(ReagtLog.OperatingTime <= request.args.get('endTime')) \ |
||||
.filter(or_(ReagtLog.ReagentName.contains(query), |
||||
ReagtLog.PinYinCode.contains(query), |
||||
ReagtLog.ReagentPosition.contains(query)))\ |
||||
.group_by(ReagtLog.ReagentName, ReagtLog.ReagentSpecification) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'list': db_page(reagent_out_filter, |
||||
ReagtLog.ReagentName, |
||||
request.args, 6), |
||||
'totalNumber': reagent_out_filter.count()}, None) |
@ -0,0 +1,143 @@ |
||||
from sqlalchemy import or_ |
||||
|
||||
from utils.PageHepler import db_page |
||||
from utils.apiDoc import * |
||||
from utils.configOperatingTypeHelper import GetApproveTypeApproving, GetApproveTypeApproved, GetApproveTypeOverrule |
||||
import pandas as pd |
||||
|
||||
|
||||
@approve.route('/add') |
||||
class ApproveAdd(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
approve_people = verify_jwt_username(request.headers.get('X-Token')) |
||||
remark = request.json['remark'] |
||||
approve_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
||||
approve_status = ReagtApproveStatus.query.filter_by(StatusCode=GetApproveTypeApproving()).first().StatusId |
||||
for item in request.json['approveList']: |
||||
data = Dict2Obj(item) |
||||
reagent_approve = ReagtApprove(ApproveName=data.Name, |
||||
Specification=data.Specification, |
||||
Maker=data.Maker if 'Maker' in item.keys() else "", |
||||
Number=data.InputNumber, |
||||
ApprovePeople=approve_people, |
||||
ApproveTime=approve_time, |
||||
Unit=data.Unit, |
||||
ApproveStatus=approve_status, |
||||
Remark=remark) |
||||
db.session.add(reagent_approve) |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@approve.route('/list') |
||||
class ApproveList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
approve_status = ReagtApproveStatus.query.filter_by(StatusCode=request.args.get('status')).first().StatusId |
||||
approve_filter = db.session.query(ReagtApprove.ApproveName, |
||||
ReagtApprove.ApproveId, |
||||
ReagtApprove.ApproveTime, |
||||
ReagtApprove.Maker, |
||||
ReagtApprove.Specification, |
||||
ReagtApprove.Number, |
||||
ReagtApprove.Unit, |
||||
ReagtApprove.ApproveTime, |
||||
ReagtApprove.ApprovePeople, |
||||
ReagtApproveStatus.StatusCode, |
||||
ReagtApprove.Verifier, |
||||
ReagtApprove.VerifyTime) \ |
||||
.join(ReagtApproveStatus, ReagtApproveStatus.StatusId == ReagtApprove.ApproveStatus).filter( |
||||
ReagtApprove.ApproveStatus == approve_status) |
||||
data_list = db_page(approve_filter, ReagtApprove.ApproveTime, request.args, 6) |
||||
if request.args.get('pageSize') is not None: |
||||
data_list = db_page(approve_filter, ReagtApprove.ApproveTime, request.args, |
||||
int(request.args.get('pageSize'))) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': approve_filter.count(), |
||||
'list': data_list}, None) |
||||
|
||||
|
||||
@approve.route('/agree') |
||||
class ApproveAgree(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
people = verify_jwt_username(request.headers.get('X-Token')) |
||||
approve_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
||||
Name, Specification, Maker, Number, Unit, ApprovePeople, Checker, Purchase, Leader, ApproveTime = [], [], [], [], [], \ |
||||
[], [], [], [], [] |
||||
approve_status = ReagtApproveStatus.query.filter_by(StatusCode=GetApproveTypeApproved()).first().StatusId |
||||
for item in request.json['approveList']: |
||||
data = Dict2Obj(item) |
||||
approve_entity = ReagtApprove.query.filter_by(ApproveId=data.ApproveId).first() |
||||
Name.append(approve_entity.ApproveName) |
||||
ApprovePeople.append(approve_entity.ApprovePeople) |
||||
Specification.append(approve_entity.Specification) |
||||
Maker.append(approve_entity.Maker) |
||||
ApproveTime.append(approve_entity.ApproveTime) |
||||
Number.append(approve_entity.Number) |
||||
Unit.append(approve_entity.Unit) |
||||
Purchase.append('') |
||||
Leader.append('') |
||||
Checker.append('') |
||||
approve_entity.ApproveStatus = approve_status |
||||
approve_entity.Verifier = people |
||||
approve_entity.VerifyTime = approve_time |
||||
db.session.commit() |
||||
dit = {'耗材名': Name, '耗材规格': Specification, '生产厂家': Maker, '欲购数量': Number, '耗材单位': Unit, |
||||
'申请人': ApprovePeople, '申请时间': ApproveTime, '审核人': Checker, '采购人': Purchase, '分管领导': Leader} |
||||
writer = pd.ExcelWriter('./file/'+approve_time.replace(':', '-')+'.xlsx') |
||||
df = pd.DataFrame(dit) |
||||
# columns参数用于指定生成的excel中列的顺序 |
||||
df.to_excel(writer, columns=['耗材名', '耗材规格', '生产厂家', '欲购数量', '耗材单位', '申请人', '申请时间', '审核人', '采购人', '分管领导'], index=False, encoding='utf-8', |
||||
sheet_name='欲购耗材清单') |
||||
writer.save() |
||||
return SuccessResponse(ResultCode.SUCCESS, approve_time.replace(':', '-'), None) |
||||
|
||||
|
||||
@approve.route('/delete') |
||||
class ApproveDelete(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
db.session.delete(ReagtApprove.query.filter_by(ApproveId=request.args.get('ApproveId')).first()) |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@approve.route('/overrule') |
||||
class ApproveOverrule(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
approve_status = ReagtApproveStatus.query.filter_by(StatusCode=GetApproveTypeOverrule()).first().StatusId |
||||
approve_entity = ReagtApprove.query.filter_by(ApproveId=request.args.get('ApproveId')).first() |
||||
approve_entity.ApproveStatus = approve_status |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@approve.route('/time') |
||||
class ApproveTime(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
approve_filter = db.session.query(ReagtApprove.VerifyTime).group_by(ReagtApprove.VerifyTime).distinct() |
||||
result_data = db_page(approve_filter, ReagtApprove.VerifyTime, request.args, 6) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': approve_filter.count(), |
||||
'list': result_data}, None) |
||||
|
||||
|
||||
@approve.route('/submitList') |
||||
class SubmitList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
inventoryListFilter = db.session.query(ReagtReagent.Name, ReagtReagent.Specification). \ |
||||
filter(ReagtReagent.Using == True). \ |
||||
group_by(ReagtReagent.Name, ReagtReagent.Specification).distinct() |
||||
if request.args.get('query') is not None and request.args.get('query') != '': |
||||
inventoryListFilter = db.session.query(ReagtReagent.Name, ReagtReagent.Specification). \ |
||||
group_by(ReagtReagent.Name, ReagtReagent.Specification). \ |
||||
filter(ReagtReagent.Using == True). \ |
||||
filter(or_(ReagtReagent.Name.contains(request.args.get('query')), ReagtReagent.Specification |
||||
.contains(request.args.get('query')), |
||||
ReagtReagent.PinYinCode.contains(request.args.get('query')))).distinct() |
||||
result_data = db_page(inventoryListFilter, ReagtReagent.Name, request.args, 10) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': inventoryListFilter.count(), |
||||
'list': result_data}, None) |
@ -0,0 +1,14 @@ |
||||
from utils.apiDoc import * |
||||
|
||||
|
||||
@authority.route('/director') |
||||
class AuthorityDirector(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
user_name = verify_jwt_username(request.headers.get('X-Token')) |
||||
director = db.session.query(DictUser.UserName).join(DictCommon, DictUser.RightCode == DictCommon.ItemCode).\ |
||||
filter(DictCommon.ItemName == '主任').first() |
||||
if director.UserName == user_name: |
||||
return SuccessResponse(ResultCode.SUCCESS, True, None) |
||||
else: |
||||
return SuccessResponse(ResultCode.SUCCESS, False, None) |
@ -0,0 +1,113 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
api.bai |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
有关报损的接口. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
import pandas as pd |
||||
from diff.stock import getDiffStockList |
||||
from utils.PageHepler import db_page, db_page_entity |
||||
from utils.apiDoc import * |
||||
from utils.configOperatingTypeHelper import GetOperatingTypeScrap |
||||
from utils.outStockHelper import * |
||||
from utils.scrapHelper import scrap_ |
||||
|
||||
|
||||
@bad.route('/upload') |
||||
class BadUpload(Resource): |
||||
""" |
||||
报损 |
||||
""" |
||||
|
||||
@staticmethod |
||||
def post(): |
||||
token = request.headers.get('X-Token') |
||||
data = request.json |
||||
app.logger.info(data) |
||||
reagentStock = ReagtStock.query.filter_by(StockId=data['StockId']).first() |
||||
reagentReagent = ReagtReagent.query.filter_by(ReagentId=reagentStock.ReagentId).first() |
||||
if data['OutStockNumber'] > reagentStock.LastNumber: |
||||
return BadResponse(ResultCode.PARAM_IS_INVALID, None, None) |
||||
if data['OutStockNumber'] < reagentStock.LastNumber or (data['OutStockNumber'] == reagentStock.LastNumber and |
||||
reagentStock.MinNumberUnit > data['OutStockNumber'] * |
||||
reagentReagent.Ratio + data['MinNumberUnit']): |
||||
LogAdd(token, GetOperatingTypeBad(), data, data['Code'], data['Name'], reagentStock.PinYinCode, |
||||
data['OutStockNumber'], data['Specification'], data['Position'], operateMinNumber= |
||||
data['MinNumberUnit'],reagentId=reagentReagent.ReagentId) |
||||
reagentStock.LastNumber -= data['OutStockNumber'] |
||||
reagentStock.MinNumberUnit -= data['OutStockNumber'] * reagentReagent.Ratio |
||||
reagentStock.MinNumberUnit -= data['MinNumberUnit'] |
||||
db.session.commit() |
||||
elif data['OutStockNumber'] == reagentStock.LastNumber: |
||||
LogAdd(token, GetOperatingTypeBad(), data, data['Code'], data['Name'], reagentStock.PinYinCode, |
||||
data['OutStockNumber'], data['Specification'], data['Position'], operateMinNumber= |
||||
data['MinNumberUnit'], reagentId=reagentStock.ReagentId) |
||||
db.session.delete(reagentStock) |
||||
db.session.delete(reagentStock) |
||||
db.session.commit() |
||||
reagentBad = ReagtBad(VerifyTime=datetime.now().strftime("%Y-%m-%d %H:%M"), Number=data['OutStockNumber'], |
||||
VerifyPeople=verify_jwt_username(token), Code=data['Code'], Remark=data['Remark']) |
||||
db.session.add(reagentBad) |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@bad.route('/scrap') |
||||
class Scrap(Resource): |
||||
""" |
||||
报废单个试剂 |
||||
""" |
||||
|
||||
@staticmethod |
||||
def get(): |
||||
token = request.headers.get('X-Token') |
||||
scrap_(request.args.get('StockId'), request.args.get('scrapNumber'), token, request.args) |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@bad.route('/scrapExpirationList') |
||||
class ScrapExpirationList(Resource): |
||||
""" |
||||
过期待报废药品列表 |
||||
""" |
||||
|
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
filterObject = getDiffStockList() |
||||
filterObject = filterObject.filter(ReagtStock.Expiration < datetime.now()) |
||||
data_list = db_page(filterObject, ReagtStock.Expiration, data, 3) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': filterObject.count(), 'list': data_list}, None) |
||||
|
||||
|
||||
@bad.route('/scrapExpiration') |
||||
class ScrapExpiration(Resource): |
||||
""" |
||||
一键报废过期药品 |
||||
""" |
||||
|
||||
@staticmethod |
||||
def get(): |
||||
token = request.headers.get('X-Token') |
||||
for expiration in ReagtStock.query.filter(ReagtStock.Expiration < datetime.now()).all(): |
||||
scrap_(expiration.StockId, expiration.LastNumber, token, request.args) |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@bad.route('/scrapList') |
||||
class ScrapList(Resource): |
||||
""" |
||||
报废单 数据 |
||||
""" |
||||
@staticmethod |
||||
def get(): |
||||
scrap_list = ReagtLog.query.filter(ReagtLog.OperatingType == GetOperatingTypeScrap()). \ |
||||
filter(ReagtLog.OperatingTime > request.args.get('startTime')). \ |
||||
filter(ReagtLog.OperatingTime < request.args.get('endTime')) |
||||
return SuccessResponse(ResultCode.SUCCESS, |
||||
{'list': db_page_entity(scrap_list, |
||||
request.args, scrap_list.count())}, None) |
@ -0,0 +1,86 @@ |
||||
""" |
||||
api.basic |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
有关基础字典的接口. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from pypinyin import lazy_pinyin, Style |
||||
|
||||
from utils.apiDoc import * |
||||
from utils.basicHelper import get_basic_entry_list |
||||
from utils.configOperatingTypeHelper import GetOperatingTypeBasicEntryClose, GetOperatingTypeBasicEntryOpen, \ |
||||
GetOperatingTypeBasicReagentClose, GetOperatingTypeBasicReagentOpen |
||||
from utils.listHelper import list2String |
||||
from utils.logHelper import LogAdd |
||||
|
||||
|
||||
@basic.route('/basicReagent') |
||||
class BasicReagent(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return get_basic_entry_list(ReagtReagent, request.args, ReagtReagent.Using.desc()) |
||||
|
||||
|
||||
@basic.route('/basicEntry') |
||||
class BasicEntry(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return get_basic_entry_list(ReagtEntry, request.args, ReagtEntry.Using.desc()) |
||||
|
||||
|
||||
@basic.route('/disableReagent') |
||||
class DisableReagent(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
token = request.headers.get('X-Token') |
||||
data = request.args |
||||
if len(ReagtStock.query.filter_by(ReagentId=int(data.get('ReagentId'))).all()) > 0: |
||||
return SuccessResponse(ResultCode.BASIC_INFO_IS_USING, None, None) |
||||
disable_reagent = ReagtReagent.query.filter_by(ReagentId=int(data.get('ReagentId'))).first() |
||||
disable_reagent.Using = not disable_reagent.Using |
||||
LogAdd(token, |
||||
GetOperatingTypeBasicReagentClose() if disable_reagent.Using else GetOperatingTypeBasicReagentOpen(), |
||||
data, None, data.get('Name'), |
||||
list2String(lazy_pinyin(disable_reagent.Name + disable_reagent.Specification, style=Style.FIRST_LETTER)), |
||||
'', disable_reagent.Specification, '', remark=F'{"停用" if disable_reagent.Using else "启用"}基础信息(库存盘点)') |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@basic.route('/disableEntry') |
||||
class DisableEntry(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
token = request.headers.get('X-Token') |
||||
data = request.args |
||||
disable_entry = ReagtEntry.query.filter_by(EntryId=int(data.get('EntryId'))).first() |
||||
disable_entry.Using = not disable_entry.Using |
||||
LogAdd(token, |
||||
GetOperatingTypeBasicEntryClose() if disable_entry.Using else GetOperatingTypeBasicEntryOpen(), |
||||
data, None, disable_entry.Name, |
||||
list2String(lazy_pinyin(disable_entry.Name + disable_entry.Specification, style=Style.FIRST_LETTER)), |
||||
disable_entry.Number, disable_entry.Specification, disable_entry.Position, |
||||
remark=F'{"停用" if disable_entry.Using else "启用"}基础信息(入库提示)') |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@basic.route('/groupBind') |
||||
class GroupBind(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
for item in request.json['reagentData']: |
||||
entity = Dict2Obj(item) |
||||
reagent_reagent = ReagtReagent.query.filter_by(ReagentId=entity.ReagentId).first() |
||||
reagent_reagent.GroupName = request.json.get('groupName') |
||||
reagent_reagent.ReportItemName = request.json.get('reportItemName') |
||||
reagent_reagent.ReportItemCode = request.json.get('reportItemCode') |
||||
reagent_reagent.ReagentMark = entity.ReagentMark |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
|
@ -0,0 +1,156 @@ |
||||
from pypinyin import lazy_pinyin, Style |
||||
from sqlalchemy import or_ |
||||
|
||||
from utils.BatchCode import GetGroupCode |
||||
from utils.apiDoc import * |
||||
from utils.dictionaryHelper import * |
||||
from utils.listHelper import list2String |
||||
|
||||
|
||||
@dictionary.route('/positionList') |
||||
class PositionList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return GetList(ReagtPosition, ReagtPosition.PositionId, ReagtPosition.Position, |
||||
ReagtPosition.PositionCode, request.args) |
||||
|
||||
|
||||
@dictionary.route('/positionChange') |
||||
class PositionChange(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
return StatusChange(ReagtPosition, request.args['PositionId'], |
||||
request.args, ReagtPosition.PositionId, ReagtStock.Position, request.args['Position']) |
||||
|
||||
|
||||
@dictionary.route('/positionAdd') |
||||
class PositionAdd(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
data = Dict2Obj(request.json) |
||||
return DictionaryAdd(ReagtPosition.query.filter_by(Position=data.Position).first(), |
||||
ReagtPosition(Position=data.Position, Using=data.Using, |
||||
PositionCode=list2String(lazy_pinyin(data.Position, |
||||
style=Style.FIRST_LETTER)))) |
||||
|
||||
|
||||
# @dictionary.route('/positionEdit') |
||||
# class PositionEdit(Resource): |
||||
# @staticmethod |
||||
# def post(): |
||||
# if ReagtPosition.query.filter_by(Position=request.args['Position']).first() is not None: |
||||
# return SuccessResponse(ResultCode.DATA_ALREADY_EXISTED, None, None) |
||||
# positionEntity = ReagtPosition.query.filter_by(PositionId=request.args['PositionId']).first() |
||||
# db.session.query(ReagtStock).filter(ReagtStock.Position == positionEntity.Position)\ |
||||
# .update({ReagtStock.Position: request.args['Position']}) |
||||
# positionEntity.Position = request.args['Position'] |
||||
# db.session.commit() |
||||
# return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@dictionary.route('/supplierList') |
||||
class SupplierList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return GetList(ReagtSupplier, ReagtSupplier.SupplierId, ReagtSupplier.SupplierName, |
||||
ReagtSupplier.SupplierCode, request.args) |
||||
|
||||
|
||||
@dictionary.route('/supplierChange') |
||||
class SupplierChange(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
return StatusChange(ReagtSupplier, request.args['SupplierId'], |
||||
request.args, ReagtSupplier.SupplierId, ReagtStock.SupplierName, |
||||
request.args['SupplierName']) |
||||
|
||||
|
||||
@dictionary.route('/supplierAdd') |
||||
class SupplierAdd(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
data = Dict2Obj(request.json) |
||||
return DictionaryAdd(ReagtSupplier.query.filter_by(SupplierName=data.SupplierName).first(), |
||||
ReagtSupplier(SupplierName=data.SupplierName, Using=data.Using, |
||||
SupplierCode=list2String(lazy_pinyin(data.SupplierName, |
||||
style=Style.FIRST_LETTER)))) |
||||
|
||||
|
||||
@dictionary.route('/groupAdd') |
||||
class GroupAdd(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
data = Dict2Obj(request.json) |
||||
return DictionaryAdd(ReagtGroup.query.filter_by(GroupName=data.GroupName).first(), |
||||
ReagtGroup(GroupName=data.GroupName, GroupCode=GetGroupCode())) |
||||
|
||||
|
||||
@dictionary.route('/groupDelete') |
||||
class GroupDelete(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
data = Dict2Obj(request.json) |
||||
reagent = ReagtReagent.query.filter_by(GroupName=data.GroupName).all() |
||||
if len(reagent) > 0: |
||||
return BadResponse(ResultCode.GROUP_INFO_IS_USING, None, None) |
||||
group = ReagtGroup.query.filter_by(GroupName=data.GroupName).first() |
||||
db.session.delete(group) |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
@dictionary.route('/groupList') |
||||
class GroupList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return GetList(ReagtGroup, ReagtGroup.GroupId, ReagtGroup.GroupName, ReagtGroup.GroupCode, |
||||
request.args, is_all=True) |
||||
|
||||
|
||||
@dictionary.route('/reportItemList') |
||||
class ReportItemList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
reportItem = db.session.query(ReagtReagent.ReportItem).group_by(ReagtReagent.ReportItem)\ |
||||
.filter(ReagtReagent.ReportItem != None).all() |
||||
list_result = [] |
||||
for item in reportItem: |
||||
list_result.append(item[0]) |
||||
return SuccessResponse(ResultCode.SUCCESS, list_result, None) |
||||
|
||||
|
||||
@dictionary.route('/groupReagent') |
||||
class GroupReagent(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
filter_item = ReagtReagent.query.filter(ReagtReagent.GroupName == data['groupName'])\ |
||||
.order_by(ReagtReagent.ReagentId.desc()) |
||||
if data.get('query') is not None: |
||||
filter_item = ReagtReagent.query.filter( |
||||
or_(ReagtReagent.Name.contains(data['query']), |
||||
ReagtReagent.PinYinCode.contains(data['query']))) \ |
||||
.filter(ReagtReagent.GroupName == data['groupName']) \ |
||||
.order_by(ReagtReagent.ReagentId.desc()) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': filter_item.count(), |
||||
'list': db_page_entity(filter_item, data, 10)}, None) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# @dictionary.route('/supplierEdit') |
||||
# class SupplierEdit(Resource): |
||||
# @staticmethod |
||||
# def post(): |
||||
# if ReagtSupplier.query.filter_by(SupplierName=request.args['SupplierName']).first() is not None: |
||||
# return SuccessResponse(ResultCode.DATA_ALREADY_EXISTED, None, None) |
||||
# supplierEntity = ReagtSupplier.query.filter_by(SupplierId=request.args['SupplierId']).first() |
||||
# db.session.query(ReagtStock).filter(ReagtStock.SupplierName == supplierEntity.SupplierName)\ |
||||
# .update({ReagtStock.SupplierName: request.args['SupplierName']}) |
||||
# supplierEntity.SupplierName = request.args['SupplierName'] |
||||
# db.session.commit() |
||||
# return SuccessResponse(ResultCode.SUCCESS, None, None) |
@ -0,0 +1,199 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
api.entry |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
有关进出库的接口. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from sqlalchemy import or_, func |
||||
import datetime |
||||
|
||||
from utils.PageHepler import db_page |
||||
from utils.apiDoc import * |
||||
from utils.dictionaryHelper import GetList |
||||
from utils.entryHelper import get_entry_list |
||||
import pandas as pd |
||||
|
||||
|
||||
@entry.route('/all') |
||||
class EntryAll(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
data = request.args |
||||
if data.get('query') is None: |
||||
return SuccessResponse(ResultCode.SOURCE_DATA_NONE, None, None) |
||||
reagentQuery = db.session.query(ReagtEntry.Name, |
||||
ReagtEntry.Specification, |
||||
ReagtEntry.Maker, |
||||
ReagtEntry.Unit, |
||||
ReagtEntry.CertificationCode, |
||||
ReagtEntry.Number, |
||||
ReagtEntry.Ratio, |
||||
ReagtEntry.SmallestUnit, |
||||
ReagtEntry.UnitPrice, |
||||
ReagtEntry.SellingPrice, |
||||
ReagtEntry.ProductionBatch, |
||||
ReagtEntry.MinValue, |
||||
ReagtEntry.MaxValue, |
||||
ReagtEntry.SupplierName, |
||||
ReagtEntry.TypeName, |
||||
ReagtEntry.Position, |
||||
ReagtEntry.EntryId).filter( |
||||
or_(ReagtEntry.Name.contains(data['query']), ReagtEntry.PinYinCode |
||||
.contains(data['query']))) \ |
||||
.filter(ReagtEntry.Using == True) |
||||
return SuccessResponse(ResultCode.SUCCESS, |
||||
{'list': db_page(reagentQuery, ReagtEntry.EntryId, data, 6), |
||||
'totalNumber': reagentQuery.count()}, |
||||
None) |
||||
|
||||
|
||||
@entry.route('/expiration') |
||||
class EntryExpiration(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
expirationReagentFilter = db.session.query(ReagtReagent.Name, ReagtStock.Expiration, |
||||
ReagtReagent.Specification, ReagtStock.Code, |
||||
ReagtStock.Position). \ |
||||
join(ReagtReagent, ReagtStock.ReagentId == ReagtReagent.ReagentId). \ |
||||
filter(ReagtStock.Expiration > datetime.now()). \ |
||||
filter(ReagtStock.Expiration < (datetime.now() + timedelta(days=10))). \ |
||||
order_by(ReagtStock.InTime.desc()) |
||||
expirationReagentPaginate = expirationReagentFilter.paginate(int(data['pageNumber']), 8, |
||||
error_out=False) |
||||
resultList = [dict(zip(result.keys(), result)) for result in expirationReagentPaginate.items] |
||||
return SuccessResponse(ResultCode.SUCCESS, {'list': resultList, |
||||
'totalNumber': expirationReagentFilter.count()}, |
||||
None) |
||||
|
||||
|
||||
@entry.route('/expirationExport') |
||||
class EntryExpirationExport(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
timestamp = datetime.now().timestamp() |
||||
expirationReagentFilter = db.session.query(ReagtReagent.Name, ReagtStock.Expiration, |
||||
ReagtStock.LastNumber, |
||||
ReagtReagent.Unit, |
||||
ReagtStock.MinNumberUnit, |
||||
ReagtReagent.SmallestUnit, |
||||
ReagtStock.SupplierName, |
||||
ReagtReagent.UnitPrice, |
||||
ReagtReagent.Maker, |
||||
ReagtStock.ProductionBatch, |
||||
ReagtReagent.MinValue, |
||||
ReagtReagent.MaxValue, |
||||
ReagtReagent.Specification, ReagtStock.Code, |
||||
ReagtStock.Position). \ |
||||
join(ReagtReagent, ReagtStock.ReagentId == ReagtReagent.ReagentId). \ |
||||
filter(ReagtStock.Expiration <= datetime.now()). \ |
||||
order_by(ReagtStock.InTime.desc()) |
||||
Name, Specification, LastNumber, Unit, MinNumberUnit, \ |
||||
SmallestUnit, SupplierName, UnitPrice, \ |
||||
Maker, ProductionBatch, Expiration, MaxValue, MinValue = [], [], [], [], [], [], [], [], [], [], [], [], [] |
||||
for item in expirationReagentFilter: |
||||
Name.append(item.Name) |
||||
Specification.append(item.Specification) |
||||
LastNumber.append(item.LastNumber) |
||||
Unit.append(item.Unit) |
||||
MinNumberUnit.append(item.MinNumberUnit) |
||||
SmallestUnit.append(item.SmallestUnit) |
||||
SupplierName.append(item.SupplierName) |
||||
UnitPrice.append(item.UnitPrice) |
||||
Maker.append(item.Maker) |
||||
ProductionBatch.append(item.ProductionBatch) |
||||
Expiration.append(item.Expiration) |
||||
MaxValue.append(item.MaxValue) |
||||
MinValue.append(item.MinValue) |
||||
dit = {'耗材名称': Name, '规格': Specification, '数量(大单位)': LastNumber, '大单位': Unit, |
||||
'数量(小单位)': MinNumberUnit, '小单位': SmallestUnit, '供应商': SupplierName, '单价': UnitPrice, |
||||
'生产厂家': Maker, '产品批号': ProductionBatch, '效期': Expiration, '最大库存数量': MaxValue, |
||||
'最小库存数量': MinValue} |
||||
writer = pd.ExcelWriter('./file/' + '过期耗材汇总表' + str(timestamp).replace('.', '-') + '.xlsx') |
||||
df = pd.DataFrame(dit) |
||||
# columns参数用于指定生成的excel中列的顺序 |
||||
df.to_excel(writer, columns=['耗材名称', '规格', '数量(大单位)', '大单位', '数量(小单位)', '小单位', |
||||
'供应商', '单价', '生产厂家', '产品批号', '效期', '最大库存数量', |
||||
'最小库存数量'], index=False, encoding='utf-8', |
||||
sheet_name='过期耗材汇总表') |
||||
writer.save() |
||||
return SuccessResponse(ResultCode.SUCCESS, '过期耗材汇总表' + str(timestamp).replace('.', '-'), None) |
||||
|
||||
|
||||
@entry.route('/bottomLimit') |
||||
class BottomLimit(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
bottomLimitFilter = db.session.query(ReagtReagent.Name, ReagtReagent.Specification, |
||||
ReagtReagent.MinValue, |
||||
func.sum(func.coalesce(ReagtStock.LastNumber, 0)).label('AllLastNumber')). \ |
||||
join(ReagtStock, ReagtStock.ReagentId == ReagtReagent.ReagentId, isouter=True). \ |
||||
filter(ReagtReagent.Using == True). \ |
||||
group_by(ReagtReagent.Name, ReagtReagent.Specification, ReagtReagent.MinValue).subquery() |
||||
bottomLimitFilter = db.session.query(bottomLimitFilter.c.Name, bottomLimitFilter.c.Specification, |
||||
bottomLimitFilter.c.MinValue, |
||||
bottomLimitFilter.c.AllLastNumber, |
||||
(bottomLimitFilter.c.MinValue - bottomLimitFilter.c.AllLastNumber).label( |
||||
'Difference') |
||||
). \ |
||||
filter(bottomLimitFilter.c.AllLastNumber < bottomLimitFilter.c.MinValue). \ |
||||
order_by((bottomLimitFilter.c.MinValue - bottomLimitFilter.c.AllLastNumber)) |
||||
bottomLimitPaginate = bottomLimitFilter.paginate(int(request.args['pageNumber']), 8, error_out=False) |
||||
resultList = [dict(zip(result.keys(), result)) for result in bottomLimitPaginate.items] |
||||
return SuccessResponse(ResultCode.SUCCESS, {'list': resultList, |
||||
'totalNumber': bottomLimitFilter.count()}, None) |
||||
|
||||
|
||||
@entry.route('/upperLimit') |
||||
class UpperLimit(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
upperLimitFilter = db.session.query(ReagtReagent.Name, ReagtReagent.Specification, |
||||
ReagtReagent.MaxValue, |
||||
func.sum(ReagtStock.LastNumber).label('AllLastNumber')). \ |
||||
join(ReagtReagent, ReagtStock.ReagentId == ReagtReagent.ReagentId). \ |
||||
group_by(ReagtReagent.Name, ReagtReagent.Specification, ReagtReagent.MaxValue).subquery() |
||||
upperLimitFilter = db.session.query(upperLimitFilter.c.Name, upperLimitFilter.c.Specification, |
||||
upperLimitFilter.c.MaxValue, |
||||
upperLimitFilter.c.AllLastNumber, |
||||
(upperLimitFilter.c.AllLastNumber - upperLimitFilter.c.MaxValue).label( |
||||
'Difference')). \ |
||||
filter(upperLimitFilter.c.AllLastNumber > upperLimitFilter.c.MaxValue). \ |
||||
order_by((upperLimitFilter.c.AllLastNumber - upperLimitFilter.c.MaxValue)) |
||||
upperLimitPaginate = upperLimitFilter.paginate(int(request.args['pageNumber']), 8, error_out=False) |
||||
app.logger.info(upperLimitPaginate.items) |
||||
resultList = [dict(zip(result.keys(), result)) for result in upperLimitPaginate.items] |
||||
return SuccessResponse(ResultCode.SUCCESS, {'list': resultList, |
||||
'totalNumber': upperLimitFilter.count()}, None) |
||||
|
||||
|
||||
@entry.route('/specification') |
||||
class Specification(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return get_entry_list(ReagtReagent.Specification, request.args) |
||||
|
||||
|
||||
@entry.route('/maker') |
||||
class Maker(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return get_entry_list(ReagtReagent.Maker, request.args) |
||||
|
||||
|
||||
@entry.route('/unit') |
||||
class Unit(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return get_entry_list(ReagtReagent.Unit, request.args) |
||||
|
||||
|
||||
@entry.route('/reagentType') |
||||
class ReagentType(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
return get_entry_list(ReagtReagent.TypeName, request.args) |
@ -0,0 +1,103 @@ |
||||
import random |
||||
import string |
||||
|
||||
import gevent |
||||
from flask import make_response, send_from_directory, current_app |
||||
from pypinyin import lazy_pinyin, Style |
||||
|
||||
from models.inStockExcel import InStockExcel |
||||
from utils import instockHelper |
||||
from utils.BatchCode import GetBatchCode |
||||
from utils.apiDoc import * |
||||
import os |
||||
import pandas as pd |
||||
|
||||
|
||||
filePath = './file/' |
||||
|
||||
|
||||
@file.route('/inStock') |
||||
class FileInStock(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
token = request.headers.get('X-Token') |
||||
inStockTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
||||
excelFile = request.files.get('files') |
||||
batchCode = GetBatchCode() |
||||
batch_code_list = [] |
||||
is_his_file = False |
||||
if not os.path.exists(filePath): |
||||
os.makedirs(filePath) |
||||
fileName = ''.join(random.choices(string.ascii_uppercase + |
||||
string.digits, k=16)) + \ |
||||
os.path.splitext(excelFile.filename)[-1] |
||||
excelFile.save(filePath + fileName) |
||||
df = pd.read_excel(filePath + fileName, sheet_name='Sheet1') |
||||
if df.keys()[0] == '出库单号': |
||||
is_his_file = True |
||||
df = pd.read_excel(filePath + fileName, sheet_name='Sheet1', |
||||
names=['Code', 'Name', 'Specification', 'SupplierName', 'Maker', 'CertificationCode', |
||||
'ProductionBatch', 'Position', 'TypeName', 'Unit', 'SmallestUnit', |
||||
'Ratio', 'UnitPrice', 'SellingPrice', 'MaxValue', 'MinValue', |
||||
'Number', 'Expiration']) |
||||
else: |
||||
df = pd.read_excel(filePath + fileName, sheet_name='Sheet1', |
||||
names=['Name', 'Specification', 'SupplierName', 'Maker', 'CertificationCode', |
||||
'ProductionBatch', 'Position', 'TypeName', 'Unit', 'SmallestUnit', |
||||
'Ratio', 'UnitPrice', 'SellingPrice', 'MaxValue', 'MinValue', |
||||
'Number', 'Expiration']) |
||||
# 文件转实体 |
||||
for index in df.index: |
||||
data = InStockExcel() |
||||
setattr(data, 'Name', str(df['Name'][index]).strip()) |
||||
setattr(data, 'Specification', str(df['Specification'][index])) |
||||
setattr(data, 'SupplierName', |
||||
'' if pd.isnull(df['SupplierName'][index]) else str(df['SupplierName'][index])) |
||||
setattr(data, 'Maker', str(df['Maker'][index])) |
||||
setattr(data, 'CertificationCode', |
||||
'' if pd.isnull(df['CertificationCode'][index]) else str(df['CertificationCode'][index])) |
||||
setattr(data, 'ProductionBatch', |
||||
'' if pd.isnull(df['ProductionBatch'][index]) else str(df['ProductionBatch'][index])) |
||||
setattr(data, 'Position', str(df['Position'][index])) |
||||
setattr(data, 'TypeName', str(df['TypeName'][index])) |
||||
setattr(data, 'Unit', str(df['Unit'][index])) |
||||
setattr(data, 'SmallestUnit', |
||||
None if pd.isnull(df['SmallestUnit'][index]) else str(df['SmallestUnit'][index])) |
||||
setattr(data, 'Ratio', |
||||
None if pd.isnull(df['Ratio'][index]) else int(df['Ratio'][index])) |
||||
setattr(data, 'UnitPrice', float(df['UnitPrice'][index])) |
||||
setattr(data, 'SellingPrice', float(df['SellingPrice'][index])) |
||||
setattr(data, 'MaxValue', int(df['MaxValue'][index])) |
||||
setattr(data, 'MinValue', int(df['MinValue'][index])) |
||||
setattr(data, 'Number', int(df['Number'][index])) |
||||
setattr(data, 'Expiration', str(df['Expiration'][index])) |
||||
if is_his_file: |
||||
batchCode = str(df['Code'][index]) |
||||
batch_code_list.append(batchCode) |
||||
# 入库信息写入 |
||||
instockHelper.in_stock(data, batchCode, inStockTime, token, request.json, remark='文件入库') |
||||
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) |
||||
os.remove(filePath + fileName) |
||||
return SuccessResponse(ResultCode.SUCCESS, None, fileName) |
||||
|
||||
|
||||
@file.route('/downloadInStock') |
||||
class DownloadInStock(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
uploads = os.path.join(os.path.abspath(os.path.dirname(current_app.root_path)), |
||||
app.config[request.args.get('path')]) |
||||
app.logger.info(uploads) |
||||
return send_from_directory(directory=uploads, filename=request.args.get('fileName')) |
@ -0,0 +1,83 @@ |
||||
from utils.PageHepler import db_page, db_page_entity |
||||
from utils.apiDoc import * |
||||
from sqlalchemy import or_ |
||||
|
||||
|
||||
@inventory.route('/list') |
||||
class InventoryList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
inventoryListFilter = db.session.query(ReagtReagent.Name, ReagtReagent.Specification). \ |
||||
join(ReagtStock, ReagtStock.ReagentId == ReagtReagent.ReagentId). \ |
||||
filter(ReagtReagent.Using == True). \ |
||||
group_by(ReagtReagent.Name, ReagtReagent.Specification).distinct() |
||||
if request.args.get('query') is not None and request.args.get('query') != '': |
||||
inventoryListFilter = db.session.query(ReagtReagent.Name, ReagtReagent.Specification). \ |
||||
join(ReagtStock, ReagtStock.ReagentId == ReagtReagent.ReagentId). \ |
||||
group_by(ReagtReagent.Name, ReagtReagent.Specification). \ |
||||
filter(ReagtReagent.Using == True). \ |
||||
filter(or_(ReagtReagent.Name.contains(request.args.get('query')), ReagtReagent.Specification |
||||
.contains(request.args.get('query')), |
||||
ReagtReagent.PinYinCode.contains(request.args.get('query')))).distinct() |
||||
result_data = db_page(inventoryListFilter, ReagtReagent.Name, request.args, 10) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': inventoryListFilter.count(), |
||||
'list': result_data}, None) |
||||
|
||||
|
||||
@inventory.route('/info') |
||||
class InventoryInfo(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
inventoryInfoFilter = db.session.query(ReagtStock.Code, |
||||
ReagtReagent.Name, |
||||
ReagtStock.Position, |
||||
ReagtStock.LastNumber, |
||||
ReagtReagent.TypeName, |
||||
ReagtStock.Number, |
||||
ReagtStock.InTime, |
||||
ReagtReagent.Specification, |
||||
ReagtStock.Expiration, |
||||
ReagtReagent.Maker, |
||||
ReagtStock.SupplierName, |
||||
ReagtReagent.CertificationCode, |
||||
ReagtStock.ProductionBatch, |
||||
ReagtReagent.UnitPrice, |
||||
ReagtReagent.SellingPrice, |
||||
ReagtStock.VerifyPeople, |
||||
ReagtReagent.Unit, |
||||
ReagtReagent.SmallestUnit, |
||||
ReagtReagent.Ratio, |
||||
ReagtStock.MinNumberUnit, |
||||
ReagtStock.StockId). \ |
||||
filter(ReagtReagent.Name == data.get('Name'), ReagtReagent.Specification == data.get('Specification')). \ |
||||
join(ReagtStock, ReagtStock.ReagentId == ReagtReagent.ReagentId) |
||||
result_data = db_page(inventoryInfoFilter, ReagtStock.InTime, data, 12) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': inventoryInfoFilter.count(), |
||||
'list': result_data}, None) |
||||
|
||||
|
||||
@inventory.route('/stockList') |
||||
class StockFile(Resource): |
||||
""" |
||||
库存盘点单 |
||||
""" |
||||
|
||||
@staticmethod |
||||
def get(): |
||||
inventoryListFilter = db.session.query(ReagtReagent.Name, |
||||
ReagtReagent.Specification, |
||||
ReagtStock.Position, |
||||
ReagtStock.LastNumber, |
||||
ReagtReagent.Unit, |
||||
ReagtStock.MinNumberUnit, |
||||
ReagtReagent.SmallestUnit, |
||||
ReagtReagent.Ratio, |
||||
ReagtReagent.Maker, |
||||
ReagtStock.ProductionBatch, |
||||
ReagtReagent.PinYinCode |
||||
). \ |
||||
join(ReagtStock, ReagtStock.ReagentId == ReagtReagent.ReagentId).order_by(ReagtReagent.PinYinCode) |
||||
return SuccessResponse(ResultCode.SUCCESS, |
||||
{'list': db_page(inventoryListFilter, ReagtStock.InTime, |
||||
request.args, inventoryListFilter.count())}, None) |
@ -0,0 +1,27 @@ |
||||
from sqlalchemy import or_ |
||||
from utils.PageHepler import db_page_entity |
||||
from utils.apiDoc import * |
||||
|
||||
|
||||
@log.route('/list') |
||||
class BadUpload(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
reagentLogFilter = ReagtLog.query.order_by(ReagtLog.OperatingTime.desc()) |
||||
if data.get('query') is not None: |
||||
reagentLogFilter = ReagtLog.query.join(ReagtOperatingType, |
||||
ReagtLog.OperatingType == ReagtOperatingType.OperatingCode). \ |
||||
filter(or_(ReagtLog.Code.contains(data['query']), |
||||
ReagtLog.OperatingPeople.contains((data['query'])), |
||||
ReagtLog.Remark.contains(data['query']), |
||||
ReagtOperatingType.OperatingName.contains(data['query']), |
||||
ReagtLog.ReagentName.contains(data['query']), |
||||
ReagtLog.ReagentPosition.contains(data['query']), |
||||
ReagtLog.ReagentSpecification.contains(data['query']))). \ |
||||
order_by(ReagtLog.OperatingTime.desc()) |
||||
if data.get('index') is not None: |
||||
reagentLogFilter = ReagtLog.query.filter_by(OperatingType=data['index']). \ |
||||
order_by(ReagtLog.OperatingTime.desc()) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': reagentLogFilter.count(), |
||||
'list': db_page_entity(reagentLogFilter, data, 13)}, None) |
@ -0,0 +1,210 @@ |
||||
from diff.stock import getDiffStockList |
||||
from utils.PageHepler import db_page |
||||
from sqlalchemy import func |
||||
from utils.apiDoc import * |
||||
from utils.configOperatingTypeHelper import * |
||||
from utils.statisticsHelper import export_diff, get_complete_number, get_complete_current_type_number |
||||
from openpyxl import Workbook |
||||
from openpyxl.styles import Alignment, Border, Side, Font |
||||
import pandas as pd |
||||
|
||||
|
||||
def alignment_merge(ws, area, value, isAlignment=True): |
||||
name_area = ws[area] |
||||
ws.merge_cells(area) |
||||
if isAlignment: |
||||
name_area[0][0].alignment = Alignment(horizontal='center', vertical='center') |
||||
name_area[0][0].value = value |
||||
|
||||
|
||||
@statistics.route('/log') |
||||
class StatisticsInStock(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
if request.args.get('type') is None: |
||||
return BadResponse(ResultCode.PARAM_IS_INVALID, None, None) |
||||
outStockReagentFilter = db.session.query( |
||||
(ReagtLog.ReagentName + ReagtLog.ReagentSpecification).label('TotalName'), |
||||
func.sum(ReagtLog.ReagentNumber).label('TotalNumber')). \ |
||||
group_by(ReagtLog.ReagentName, ReagtLog.ReagentSpecification).filter( |
||||
ReagtLog.OperatingType == GetOperatingTypeUseName(request.args['type'])).filter( |
||||
ReagtLog.OperatingTime < datetime.now()). \ |
||||
filter(ReagtLog.OperatingTime > (datetime.now() - timedelta(days=10))).order_by( |
||||
func.sum(ReagtLog.ReagentNumber)).all() |
||||
if request.args.get('startTime') is not None and request.args.get('endTime') is not None: |
||||
outStockReagentFilter = db.session.query( |
||||
(ReagtLog.ReagentName + ReagtLog.ReagentSpecification).label('TotalName'), |
||||
func.sum(ReagtLog.ReagentNumber).label('TotalNumber')). \ |
||||
group_by(ReagtLog.ReagentName, ReagtLog.ReagentSpecification).filter( |
||||
ReagtLog.OperatingType == GetOperatingTypeUseName(request.args['type'])).filter( |
||||
ReagtLog.OperatingTime < request.args['endTime']). \ |
||||
filter(ReagtLog.OperatingTime > request.args['startTime']).order_by( |
||||
func.sum(ReagtLog.ReagentNumber)).all() |
||||
return SuccessResponse(ResultCode.SUCCESS, outStockReagentFilter, None) |
||||
|
||||
|
||||
@statistics.route('/list') |
||||
class StatisticsList(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
reagentLogFilter = export_diff(data) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': reagentLogFilter.count(), |
||||
'list': db_page(reagentLogFilter, ReagtLog.OperatingTime, |
||||
data, 13)}, None) |
||||
|
||||
|
||||
@statistics.route('/export') |
||||
class StatisticsExport(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
timestamp = datetime.now().timestamp() |
||||
reagentLogFilter = export_diff(data) |
||||
ReagentName, ReagentSpecification, ReagentNumber, \ |
||||
Unit, OperateMinNumber, UnitPrice, SmallestUnit, ReagentPosition, \ |
||||
ProductionBatch, Maker, Expiration, Code, OperatingTime, \ |
||||
OperatingPeople, SupplierName, Remark = [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [] |
||||
for item in reagentLogFilter: |
||||
ReagentName.append(item.ReagentName) |
||||
ReagentSpecification.append(item.ReagentSpecification) |
||||
ReagentNumber.append(item.ReagentNumber) |
||||
Unit.append(item.Unit) |
||||
UnitPrice.append(item.UnitPrice) |
||||
Maker.append(item.Maker) |
||||
OperateMinNumber.append(item.OperateMinNumber) |
||||
SmallestUnit.append(item.SmallestUnit) |
||||
ReagentPosition.append(item.ReagentPosition) |
||||
ProductionBatch.append(item.ProductionBatch) |
||||
Expiration.append(item.Expiration) |
||||
Code.append(item.Code) |
||||
OperatingTime.append(item.OperatingTime) |
||||
OperatingPeople.append(item.OperatingPeople) |
||||
SupplierName.append(item.SupplierName) |
||||
Remark.append(item.Remark) |
||||
dit = {'耗材名称': ReagentName, '规格': ReagentSpecification, '数量(大单位)': ReagentNumber, '大单位': Unit, |
||||
'数量(小单位)': OperateMinNumber, '小单位': SmallestUnit, '供应商': SupplierName, '单价': UnitPrice, |
||||
'生产厂家': Maker, '产品批号': ProductionBatch, '效期': Expiration, '操作时间': OperatingTime, |
||||
'入库批号': Code, '操作员': OperatingPeople} |
||||
writer = pd.ExcelWriter('./file/' + data.get('title') + str(timestamp).replace('.', '-') + '.xlsx') |
||||
df = pd.DataFrame(dit) |
||||
# columns参数用于指定生成的excel中列的顺序 |
||||
df.to_excel(writer, columns=['耗材名称', '规格', '数量(大单位)', '大单位', '数量(小单位)', '小单位', |
||||
'供应商', '单价', '生产厂家', '产品批号', '效期', '操作时间', |
||||
'入库批号', '操作员'], index=False, encoding='utf-8', |
||||
sheet_name=data.get('title')) |
||||
writer.save() |
||||
return SuccessResponse(ResultCode.SUCCESS, data.get('title') + str(timestamp).replace('.', '-'), None) |
||||
|
||||
|
||||
@statistics.route('/complete') |
||||
class StatisticsComplete(Resource): |
||||
@staticmethod |
||||
def get(): |
||||
data = request.args |
||||
start_date = data.get('startDate') if data.get('startDate') is not None else (datetime.now() - |
||||
timedelta(days=10)) |
||||
end_data = data.get('endDate') if data.get('endDate') is not None else datetime.now() |
||||
timestamp = datetime.now().timestamp() |
||||
wb = Workbook() |
||||
ws = wb.active |
||||
ws.title = '试剂与耗材统计汇总表' |
||||
alignment = Alignment(horizontal='center', vertical='center') |
||||
|
||||
border = Border(left=Side(border_style='thin', color='000000'), |
||||
right=Side(border_style='thin', color='000000'), |
||||
top=Side(border_style='thin', color='000000'), |
||||
bottom=Side(border_style='thin', color='000000')) |
||||
|
||||
title_area = ws['A1:AH1'] |
||||
ws.merge_cells('A1:AH1') |
||||
title_area[0][0].alignment = alignment |
||||
title_area[0][0].value = '按试剂名称分类出入数汇总表' |
||||
title_area[0][0].font = Font(name='黑体', bold=True, size=16) |
||||
|
||||
alignment_merge(ws, 'A2:AH2', '统计日期:' + str(start_date) + '至' + str(end_data), |
||||
isAlignment=False) |
||||
alignment_merge(ws, 'A3:A4', '耗材名称') |
||||
alignment_merge(ws, 'B3:B4', '规格') |
||||
alignment_merge(ws, 'C3:C4', '生产厂家') |
||||
alignment_merge(ws, 'D3:D4', '批准文号') |
||||
alignment_merge(ws, 'E3:E4', '生产批号') |
||||
alignment_merge(ws, 'F3:F4', '耗材类型') |
||||
alignment_merge(ws, 'G3:G4', '进货价') |
||||
alignment_merge(ws, 'H3:H4', '销售价') |
||||
alignment_merge(ws, 'I3:I4', '有效期') |
||||
alignment_merge(ws, 'J3:N3', '上期结存') |
||||
alignment_merge(ws, 'O3:S3', '本期进向汇总') |
||||
alignment_merge(ws, 'T3:X3', '本期出向汇总') |
||||
alignment_merge(ws, 'Y3:AC3', '本期调整数合计(报损、报废合计)') |
||||
alignment_merge(ws, 'AD3:AH3', '本期余额') |
||||
ws['J4'] = '数量' |
||||
ws['K4'] = '大单位' |
||||
ws['L4'] = '数量' |
||||
ws['M4'] = '小单位' |
||||
ws['N4'] = '数量描述' |
||||
ws['O4'] = '数量' |
||||
ws['P4'] = '大单位' |
||||
ws['Q4'] = '数量' |
||||
ws['R4'] = '小单位' |
||||
ws['S4'] = '数量描述' |
||||
ws['T4'] = '数量' |
||||
ws['U4'] = '大单位' |
||||
ws['V4'] = '数量' |
||||
ws['W4'] = '小单位' |
||||
ws['X4'] = '数量描述' |
||||
ws['Y4'] = '数量' |
||||
ws['Z4'] = '大单位' |
||||
ws['AA4'] = '数量' |
||||
ws['AB4'] = '小单位' |
||||
ws['AC4'] = '数量描述' |
||||
ws['AD4'] = '数量' |
||||
ws['AE4'] = '大单位' |
||||
ws['AF4'] = '数量' |
||||
ws['AG4'] = '小单位' |
||||
ws['AH4'] = '数量描述' |
||||
title_area = ws['A1:AH4'] |
||||
for row in title_area: |
||||
for cell in row: |
||||
cell.border = border |
||||
|
||||
filterObject = getDiffStockList() |
||||
reagent_stock = filterObject.filter(ReagtStock.Using).order_by(ReagtStock.PinYinCode).all() |
||||
reagent_id_list = [] |
||||
index = 0 |
||||
for reagent in reagent_stock: |
||||
if reagent.ReagentId in reagent_id_list: |
||||
continue |
||||
reagent_log_before = ReagtLog.query.filter_by(ReagentId=reagent.ReagentId) \ |
||||
.filter(ReagtLog.OperatingTime < start_date) \ |
||||
.order_by(ReagtLog.OperatingTime.desc()).all() |
||||
excel_cell = [reagent.Name, reagent.Specification, reagent.Maker, reagent.CertificationCode, |
||||
reagent.ProductionBatch, |
||||
reagent.TypeName, str(reagent.UnitPrice), str(reagent.SellingPrice), str(reagent.Expiration)] |
||||
get_complete_number(reagent_log_before, reagent, excel_cell) |
||||
reagent_log_current_in_stock = (ReagtLog.query.filter_by(ReagentId=reagent.ReagentId, |
||||
OperatingType=GetOperatingTypeInStock()) |
||||
.filter(ReagtLog.OperatingTime > start_date) |
||||
.order_by(ReagtLog.OperatingTime).all()) |
||||
get_complete_number(reagent_log_current_in_stock, reagent, excel_cell) |
||||
get_complete_current_type_number(start_date, reagent, excel_cell, GetOperatingTypeOutStock()) |
||||
get_complete_current_type_number(start_date, reagent, excel_cell, GetOperatingTypeBad(), |
||||
GetOperatingTypeScrap()) |
||||
|
||||
excel_cell.append(str(reagent.LastNumber)) |
||||
excel_cell.append(reagent.Unit) |
||||
excel_cell.append(str(reagent.MinNumberUnit)) |
||||
excel_cell.append(reagent.SmallestUnit) |
||||
excel_cell.append(str(reagent.LastNumber) + reagent.Unit + str(reagent.MinNumberUnit) + |
||||
reagent.SmallestUnit) |
||||
ws._current_row = 4 + index |
||||
ws.append(excel_cell) |
||||
reagent_id_list.append(reagent.ReagentId) |
||||
index += 1 |
||||
for row in ws.rows: |
||||
for cell in row: |
||||
cell.border = border |
||||
|
||||
wb.save('./file/' + '按试剂名称分类出入数汇总表' + str(timestamp).replace('.', '-') + '.xlsx') |
||||
return SuccessResponse(ResultCode.SUCCESS, '按试剂名称分类出入数汇总表' + str(timestamp).replace('.', '-'), |
||||
None) |
@ -0,0 +1,58 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
api.user |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
有关用户操作的接口. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from utils.PageHepler import singleEntityToJson |
||||
from utils.apiDoc import * |
||||
|
||||
|
||||
# 接口路由 |
||||
@user.route('/login') |
||||
class IndexApi(Resource): |
||||
# @api.marshal_with(return_model,code=200) |
||||
# @api.expect(return_model) |
||||
@staticmethod |
||||
def post(): |
||||
""" |
||||
user login |
||||
:return: user info token |
||||
""" |
||||
data = request.json |
||||
userInfo = DictUser.query.filter_by(UserCode=data['username'], PassWord=data['password']).first() |
||||
if userInfo is None: |
||||
return SuccessResponse(ResultCode.USER_LOGIN_ERROR, None, None) |
||||
return SuccessResponse(ResultCode.SUCCESS, None, |
||||
generate_jwt_long({'UserName': userInfo.UserName})) |
||||
|
||||
|
||||
@user.route('/info') |
||||
class UserInfo(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
""" |
||||
get user info |
||||
:return: user info |
||||
""" |
||||
token = request.headers.get('X-Token') |
||||
userInfo = DictUser.query.filter_by(UserName=verify_jwt_username(token)).first() |
||||
if userInfo is None: |
||||
return BadResponse(ResultCode.INVALID_TOKEN, None, None) |
||||
return SuccessResponse(ResultCode.SUCCESS, singleEntityToJson(userInfo), |
||||
None) |
||||
|
||||
|
||||
@user.route('/code') |
||||
class UserCode(Resource): |
||||
@staticmethod |
||||
def post(): |
||||
data = request.json |
||||
user_info = DictUser.query.filter_by(UserCode=data['userCode']).first() |
||||
if user_info is None: |
||||
return BadResponse(ResultCode.USER_NOT_EXIST, None, None) |
||||
return SuccessResponse(ResultCode.SUCCESS, {'userName': user_info.UserName}, None) |
@ -0,0 +1,4 @@ |
||||
[jwt] |
||||
EXPIRY_HOURS=1 |
||||
REFRESH_DAYS=1 |
||||
SECRET='lis_reagent' |
@ -0,0 +1,10 @@ |
||||
[mssql-config] |
||||
host = 192.168.12.10 |
||||
;host = 139.155.175.14 |
||||
user = XBDLISUser |
||||
;user = sa |
||||
;pwd = BlueFlag.Lis!@# |
||||
pwd = 7439a39215e13707fcbbc444618dfd14 |
||||
;pwd = e2ba51ec7efee717794b5c0084011c67 |
||||
db = hisdata |
||||
charset = UTF-8 |
@ -0,0 +1,17 @@ |
||||
[operatingType] |
||||
bad = Bad |
||||
inStock = InStock |
||||
outStock = OutStock |
||||
delete = Delete |
||||
update = Update |
||||
basicReagentOpen = BasicReagentOpen |
||||
basicReagentClose = BasicReagentClose |
||||
basicEntryOpen = BasicEntryOpen |
||||
basicEntryClose = BasicEntryClose |
||||
scrap = Scrap |
||||
edit = Edit |
||||
|
||||
[approveType] |
||||
approving = Approving |
||||
approved = Approved |
||||
overrule = Overrule |
@ -0,0 +1,31 @@ |
||||
from models.db import db |
||||
from models.entity import ReagtStock, ReagtReagent |
||||
|
||||
|
||||
def getDiffStockList(): |
||||
return db.session.query( |
||||
ReagtReagent.ReagentId, |
||||
ReagtStock.Code, |
||||
ReagtReagent.Name, |
||||
ReagtStock.Position, |
||||
ReagtStock.LastNumber, |
||||
ReagtReagent.TypeName, |
||||
ReagtStock.Number, |
||||
ReagtStock.InTime, |
||||
ReagtReagent.Specification, |
||||
ReagtStock.Expiration, |
||||
ReagtReagent.Maker, |
||||
ReagtStock.SupplierName, |
||||
ReagtReagent.CertificationCode, |
||||
ReagtStock.ProductionBatch, |
||||
ReagtReagent.UnitPrice, |
||||
ReagtReagent.SellingPrice, |
||||
ReagtStock.VerifyPeople, |
||||
ReagtReagent.Unit, |
||||
ReagtReagent.SmallestUnit, |
||||
ReagtReagent.Ratio, |
||||
ReagtStock.StockId, |
||||
ReagtStock.MinNumberUnit, |
||||
ReagtReagent.MaxValue, |
||||
ReagtReagent.MinValue). \ |
||||
join(ReagtStock, ReagtStock.ReagentId == ReagtReagent.ReagentId) |
@ -0,0 +1,26 @@ |
||||
import json |
||||
from flask import Blueprint |
||||
from statusCode.responseEntity import SuccessResponse |
||||
from statusCode.resultCode import ResultCode |
||||
|
||||
exception = Blueprint('exception', __name__) |
||||
|
||||
|
||||
@exception.app_errorhandler(404) |
||||
def error_404(error): |
||||
return SuccessResponse(ResultCode.NOT_FIND, None, None) |
||||
|
||||
|
||||
@exception.app_errorhandler(405) |
||||
def error_405(error): |
||||
return SuccessResponse(ResultCode.METHOD_ERROR, None, None) |
||||
|
||||
|
||||
@exception.app_errorhandler(Exception) |
||||
def error_500(error): |
||||
return SuccessResponse(ResultCode.SERVICE_ERROR, None, None) |
||||
|
||||
|
||||
class MyError(Exception): |
||||
"""自定义错误类""" |
||||
pass |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,68 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
models.InStockModel |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
进库实体. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
import json |
||||
from utils.List2Json import * |
||||
|
||||
|
||||
class InStockModel(object): |
||||
Name = '', |
||||
Specification = '', |
||||
day = 0, |
||||
Maker = '', |
||||
CertificationCode = '', |
||||
UnitPrice = 0, |
||||
SellingPrice = 0, |
||||
MaxValue = 0, |
||||
MinValue = 0, |
||||
ProductionBatch = '', |
||||
TypeName = '', |
||||
Position = '', |
||||
Number = 0, |
||||
SupplierName = '' |
||||
hasChildren = False |
||||
|
||||
def __init__(self, Name, Specification, day, Maker, CertificationCode, UnitPrice, SellingPrice, MaxValue, MinValue, |
||||
ProductionBatch, TypeName, Position, Number, SupplierName, hasChildren): |
||||
self.Name = Name |
||||
self.Specification = Specification |
||||
self.day = day |
||||
self.Maker = Maker |
||||
self.CertificationCode = CertificationCode |
||||
self.UnitPrice = UnitPrice |
||||
self.Specification = Specification |
||||
self.SellingPrice = SellingPrice |
||||
self.MaxValue = MaxValue |
||||
self.MinValue = MinValue |
||||
self.ProductionBatch = ProductionBatch |
||||
self.TypeName = TypeName |
||||
self.Position = Position |
||||
self.Number = Number |
||||
self.SupplierName = SupplierName |
||||
self.hasChildren = hasChildren |
||||
|
||||
@property |
||||
def value(self): |
||||
""" |
||||
StockListModel json data |
||||
:return: json data |
||||
""" |
||||
return {"Name": self.Name, "Specification": self.Specification, "day": self.day, "Maker": |
||||
self.Maker, "CertificationCode": self.CertificationCode, "UnitPrice": self.UnitPrice, "Specification": |
||||
self.Specification, "SellingPrice": self.SellingPrice, "MaxValue": self.MaxValue, "MinValue": |
||||
self.MinValue, "ProductionBatch": self.ProductionBatch, "TypeName": self.TypeName, "Position": |
||||
self.Position, "Number": self.Number, "SupplierName": self.SupplierName, "hasChildren": |
||||
self.hasChildren} |
||||
|
||||
# return '{"Name":"' + self.Name + '", "Specification":"' + self.Specification + '", "day":"' + self.day + '", "Maker":"' + \ |
||||
# self.Maker + '","CertificationCode":"' + self.CertificationCode + '", "UnitPrice":"' + self.UnitPrice + '", "Specification":"' + \ |
||||
# self.Specification + '","SellingPrice":"' + self.SellingPrice + '", "MaxValue":"' + self.MaxValue + '", "MinValue":"' + \ |
||||
# self.MinValue + '", "ProductionBatch":"' + self.ProductionBatch + '", "TypeName":"' + self.TypeName + '", "Position":"' + \ |
||||
# self.Position + '","Number":"' + self.Number + '", "SupplierName":"' + self.SupplierName + '"}' |
@ -0,0 +1,2 @@ |
||||
class InStockExcel(object): |
||||
Name = "" |
@ -0,0 +1,32 @@ |
||||
class ReagentTypeList(object): |
||||
ReagentId = None |
||||
Name = None |
||||
Specification = None |
||||
Maker = None |
||||
CertificationCode = None |
||||
UnitPrice = None |
||||
SellingPrice = None |
||||
MaxValue = None |
||||
MinValue = None |
||||
TypeName = None |
||||
hasChildren = None |
||||
|
||||
def __init__(self, ReagentId, Name, Specification, Maker, CertificationCode, UnitPrice, SellingPrice, MaxValue, |
||||
MinValue, TypeName, hasChildren): |
||||
self.ReagentId = ReagentId, |
||||
self.Name = Name, |
||||
self.Specification = Specification, |
||||
self.Maker = Maker, |
||||
self.CertificationCode = CertificationCode, |
||||
self.UnitPrice = UnitPrice, |
||||
self.SellingPrice = SellingPrice, |
||||
self.MaxValue = MaxValue, |
||||
self.MinValue = MinValue, |
||||
self.TypeName = TypeName, |
||||
self.hasChildren = hasChildren |
||||
|
||||
def value(self): |
||||
return {"ReagentId": self.ReagentId[0], "Name": self.Name[0], "Specification": self.Specification[0], |
||||
"Maker": self.Maker[0], "CertificationCode": self.CertificationCode[0], "UnitPrice": str(self.UnitPrice[0]), |
||||
"SellingPrice": str(self.SellingPrice[0]), "MaxValue": self.MaxValue[0], "MinValue": self.MinValue[0], "TypeName": |
||||
self.TypeName[0], "hasChildren": self.hasChildren} |
@ -0,0 +1,75 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
models.StockListModel |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
库存实体. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
import json |
||||
from utils.List2Json import * |
||||
|
||||
|
||||
class StockListModel(object): |
||||
Id = None |
||||
StockId = None |
||||
Name = None |
||||
Code = None |
||||
Position = None |
||||
Number = None |
||||
LastNumber = None |
||||
InTime = None |
||||
Specification = None |
||||
Expiration = None |
||||
Maker = None |
||||
SupplierName = None |
||||
CertificationCode = None |
||||
ProductionBatch = None |
||||
UnitPrice = None |
||||
SellingPrice = None |
||||
VerifyPeople = None |
||||
TypeName = None |
||||
Unit = None |
||||
Ratio = None |
||||
SmallestUnit = None |
||||
|
||||
def __init__(self, Id, Name, StockId, Code, Position, Number, LastNumber, InTime, Specification, Expiration, Maker, |
||||
SupplierName, CertificationCode, ProductionBatch, UnitPrice, SellingPrice, VerifyPeople, |
||||
TypeName, Unit, Ratio, SmallestUnit): |
||||
self.Id = Id |
||||
self.StockId = StockId |
||||
self.Name = Name |
||||
self.Code = Code |
||||
self.Position = Position |
||||
self.Number = Number |
||||
self.LastNumber = LastNumber |
||||
self.InTime = InTime |
||||
self.Specification = Specification |
||||
self.Expiration = Expiration |
||||
self.Maker = Maker |
||||
self.SupplierName = SupplierName |
||||
self.CertificationCode = CertificationCode |
||||
self.ProductionBatch = ProductionBatch |
||||
self.UnitPrice = UnitPrice |
||||
self.SellingPrice = SellingPrice |
||||
self.VerifyPeople = VerifyPeople |
||||
self.TypeName = TypeName |
||||
self.Unit = Unit |
||||
self.Ratio = Ratio |
||||
self.SmallestUnit = SmallestUnit |
||||
|
||||
def value(self): |
||||
""" |
||||
StockListModel json data |
||||
:return: json data |
||||
""" |
||||
return '{"ID":"' + str(self.Id) + '","StockId":"' + str(self.StockId) + '","Name":"' + self.Name + '","Code":"' + self.Code + '","Position":"' + self.Position + '","Number":"' + \ |
||||
str(self.Number) + '","LastNumber":"' + str(self.LastNumber) + '","InTime":"' + str(self.InTime) + '","Specification":"' + \ |
||||
self.Specification + '","Expiration":"' + str(self.Expiration) + '","Maker":"' + self.Maker + '","SupplierName":"' + \ |
||||
self.SupplierName + '","CertificationCode":"' + self.CertificationCode + '","ProductionBatch":"' + \ |
||||
self.ProductionBatch + '","UnitPrice":"' + str(self.UnitPrice) + '","SellingPrice":"' + \ |
||||
str(self.SellingPrice) + '","VerifyPeople":"' + self.VerifyPeople +\ |
||||
'","Unit":"' + str(self.Unit) + '","TypeName":"' + \ |
||||
self.TypeName + '","Ratio":"' + str(self.Ratio) + '","SmallestUnit":"' + str(self.SmallestUnit) + '"}' |
@ -0,0 +1,51 @@ |
||||
function global:deactivate ([switch]$NonDestructive) { |
||||
# Revert to original values |
||||
if (Test-Path function:_OLD_VIRTUAL_PROMPT) { |
||||
copy-item function:_OLD_VIRTUAL_PROMPT function:prompt |
||||
remove-item function:_OLD_VIRTUAL_PROMPT |
||||
} |
||||
|
||||
if (Test-Path env:_OLD_VIRTUAL_PYTHONHOME) { |
||||
copy-item env:_OLD_VIRTUAL_PYTHONHOME env:PYTHONHOME |
||||
remove-item env:_OLD_VIRTUAL_PYTHONHOME |
||||
} |
||||
|
||||
if (Test-Path env:_OLD_VIRTUAL_PATH) { |
||||
copy-item env:_OLD_VIRTUAL_PATH env:PATH |
||||
remove-item env:_OLD_VIRTUAL_PATH |
||||
} |
||||
|
||||
if (Test-Path env:VIRTUAL_ENV) { |
||||
remove-item env:VIRTUAL_ENV |
||||
} |
||||
|
||||
if (!$NonDestructive) { |
||||
# Self destruct! |
||||
remove-item function:deactivate |
||||
} |
||||
} |
||||
|
||||
deactivate -nondestructive |
||||
|
||||
$env:VIRTUAL_ENV="D:\Project\Python\web\Flask\py" |
||||
|
||||
if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { |
||||
# Set the prompt to include the env name |
||||
# Make sure _OLD_VIRTUAL_PROMPT is global |
||||
function global:_OLD_VIRTUAL_PROMPT {""} |
||||
copy-item function:prompt function:_OLD_VIRTUAL_PROMPT |
||||
function global:prompt { |
||||
Write-Host -NoNewline -ForegroundColor Green '(py) ' |
||||
_OLD_VIRTUAL_PROMPT |
||||
} |
||||
} |
||||
|
||||
# Clear PYTHONHOME |
||||
if (Test-Path env:PYTHONHOME) { |
||||
copy-item env:PYTHONHOME env:_OLD_VIRTUAL_PYTHONHOME |
||||
remove-item env:PYTHONHOME |
||||
} |
||||
|
||||
# Add the venv to the PATH |
||||
copy-item env:PATH env:_OLD_VIRTUAL_PATH |
||||
$env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH" |
@ -0,0 +1,76 @@ |
||||
# This file must be used with "source bin/activate" *from bash* |
||||
# you cannot run it directly |
||||
|
||||
deactivate () { |
||||
# reset old environment variables |
||||
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then |
||||
PATH="${_OLD_VIRTUAL_PATH:-}" |
||||
export PATH |
||||
unset _OLD_VIRTUAL_PATH |
||||
fi |
||||
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then |
||||
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" |
||||
export PYTHONHOME |
||||
unset _OLD_VIRTUAL_PYTHONHOME |
||||
fi |
||||
|
||||
# This should detect bash and zsh, which have a hash command that must |
||||
# be called to get it to forget past commands. Without forgetting |
||||
# past commands the $PATH changes we made may not be respected |
||||
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then |
||||
hash -r |
||||
fi |
||||
|
||||
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then |
||||
PS1="${_OLD_VIRTUAL_PS1:-}" |
||||
export PS1 |
||||
unset _OLD_VIRTUAL_PS1 |
||||
fi |
||||
|
||||
unset VIRTUAL_ENV |
||||
if [ ! "$1" = "nondestructive" ] ; then |
||||
# Self destruct! |
||||
unset -f deactivate |
||||
fi |
||||
} |
||||
|
||||
# unset irrelevant variables |
||||
deactivate nondestructive |
||||
|
||||
VIRTUAL_ENV="D:\Project\Python\web\Flask\py" |
||||
export VIRTUAL_ENV |
||||
|
||||
_OLD_VIRTUAL_PATH="$PATH" |
||||
PATH="$VIRTUAL_ENV/Scripts:$PATH" |
||||
export PATH |
||||
|
||||
# unset PYTHONHOME if set |
||||
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) |
||||
# could use `if (set -u; : $PYTHONHOME) ;` in bash |
||||
if [ -n "${PYTHONHOME:-}" ] ; then |
||||
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" |
||||
unset PYTHONHOME |
||||
fi |
||||
|
||||
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then |
||||
_OLD_VIRTUAL_PS1="${PS1:-}" |
||||
if [ "x(py) " != x ] ; then |
||||
PS1="(py) ${PS1:-}" |
||||
else |
||||
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then |
||||
# special case for Aspen magic directories |
||||
# see http://www.zetadev.com/software/aspen/ |
||||
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" |
||||
else |
||||
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" |
||||
fi |
||||
fi |
||||
export PS1 |
||||
fi |
||||
|
||||
# This should detect bash and zsh, which have a hash command that must |
||||
# be called to get it to forget past commands. Without forgetting |
||||
# past commands the $PATH changes we made may not be respected |
||||
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then |
||||
hash -r |
||||
fi |
@ -0,0 +1,45 @@ |
||||
@echo off |
||||
|
||||
rem This file is UTF-8 encoded, so we need to update the current code page while executing it |
||||
for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( |
||||
set "_OLD_CODEPAGE=%%a" |
||||
) |
||||
if defined _OLD_CODEPAGE ( |
||||
"%SystemRoot%\System32\chcp.com" 65001 > nul |
||||
) |
||||
|
||||
set "VIRTUAL_ENV=D:\Project\Python\web\Flask\py" |
||||
|
||||
if not defined PROMPT ( |
||||
set "PROMPT=$P$G" |
||||
) |
||||
|
||||
if defined _OLD_VIRTUAL_PROMPT ( |
||||
set "PROMPT=%_OLD_VIRTUAL_PROMPT%" |
||||
) |
||||
|
||||
if defined _OLD_VIRTUAL_PYTHONHOME ( |
||||
set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" |
||||
) |
||||
|
||||
set "_OLD_VIRTUAL_PROMPT=%PROMPT%" |
||||
set "PROMPT=(py) %PROMPT%" |
||||
|
||||
if defined PYTHONHOME ( |
||||
set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" |
||||
set PYTHONHOME= |
||||
) |
||||
|
||||
if defined _OLD_VIRTUAL_PATH ( |
||||
set "PATH=%_OLD_VIRTUAL_PATH%" |
||||
) else ( |
||||
set "_OLD_VIRTUAL_PATH=%PATH%" |
||||
) |
||||
|
||||
set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" |
||||
|
||||
:END |
||||
if defined _OLD_CODEPAGE ( |
||||
"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul |
||||
set "_OLD_CODEPAGE=" |
||||
) |
@ -0,0 +1,21 @@ |
||||
@echo off |
||||
|
||||
if defined _OLD_VIRTUAL_PROMPT ( |
||||
set "PROMPT=%_OLD_VIRTUAL_PROMPT%" |
||||
) |
||||
set _OLD_VIRTUAL_PROMPT= |
||||
|
||||
if defined _OLD_VIRTUAL_PYTHONHOME ( |
||||
set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" |
||||
set _OLD_VIRTUAL_PYTHONHOME= |
||||
) |
||||
|
||||
if defined _OLD_VIRTUAL_PATH ( |
||||
set "PATH=%_OLD_VIRTUAL_PATH%" |
||||
) |
||||
|
||||
set _OLD_VIRTUAL_PATH= |
||||
|
||||
set VIRTUAL_ENV= |
||||
|
||||
:END |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@ |
||||
home = F:\Anaconda3 |
||||
include-system-site-packages = true |
||||
version = 3.7.4 |
@ -0,0 +1,18 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
server |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
tornado转换server的启动端口,无需启动,默认5000端口即可用,如有nginx等可混合使用. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from tornado.httpserver import HTTPServer |
||||
from tornado.wsgi import WSGIContainer |
||||
from web import app |
||||
from tornado.ioloop import IOLoop |
||||
|
||||
s = HTTPServer(WSGIContainer(app)) |
||||
s.listen(9900) # 监听 9900 端口 |
||||
IOLoop.current().start() |
@ -0,0 +1,22 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
statusCode.responseEntity |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
返回类型,数据为json,状态为200或500. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from flask import Response |
||||
from statusCode.result import * |
||||
|
||||
|
||||
def SuccessResponse(resultCode, data, token): |
||||
return Response(response=resultData(resultCode.value['code'], resultCode.value['message'], data, token).value(), |
||||
status=200, mimetype="application/json") |
||||
|
||||
|
||||
def BadResponse(resultCode, data, token): |
||||
return Response(response=resultData(resultCode.value['code'], resultCode.value['message'], data, token).value(), |
||||
status=500, mimetype="application/json") |
@ -0,0 +1,33 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
statusCode.result |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
返回前端的实体为code,message,data,token. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
import json |
||||
from utils.List2Json import * |
||||
|
||||
|
||||
class resultData(object): |
||||
code = None |
||||
message = None |
||||
data = None |
||||
token = None |
||||
|
||||
def __init__(self, code, message, data, token): |
||||
self.code = code |
||||
self.message = message |
||||
self.data = data |
||||
self.token = token |
||||
|
||||
def value(self): |
||||
""" |
||||
json data |
||||
:return: json data |
||||
""" |
||||
return json.dumps({'code': self.code, 'message': self.message, 'data': self.data, 'token': self.token}, |
||||
cls=DecimalEncoder) |
@ -0,0 +1,69 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
statusCode.resultCode |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
code跟message的Enum. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from enum import Enum |
||||
|
||||
|
||||
class ResultCode(Enum): |
||||
"""docstring for ResultCode""" |
||||
# 成功状态码 |
||||
SUCCESS = {'code': 200, 'message': "成功"} |
||||
|
||||
# 失败状态码 |
||||
ERROR = {'code': 401, 'message': "失败"} |
||||
|
||||
NOT_FIND = {'code': 404, 'message': "请求路径无效"} |
||||
|
||||
METHOD_ERROR = {'code': 405, 'message': "请求方式有误"} |
||||
|
||||
SERVICE_ERROR = {'code': 500, 'message': "服务器错误"} |
||||
|
||||
# 参数错误:10001-19999 |
||||
PARAM_IS_BLANK = {'code': 10001, 'message': "参数为空"} |
||||
PARAM_IS_INVALID = {'code': 10002, 'message': "参数无效"} |
||||
PARAM_NOT_COMPLETE = {'code': 10003, 'message': "参数缺失"} |
||||
PARAM_TYPE_BIND_ERROR = {'code': 10004, 'message': "参数类型错误"} |
||||
|
||||
# 账户错误:20001-29999 |
||||
USER_NOT_EXIST = {'code': 20001, 'message': "账户不存在"} |
||||
USER_ACCOUNT_FORBIDDEN = {'code': 20002, 'message': "账号已禁用"} |
||||
USER_ACCOUNT_DELETE = {'code': 20003, 'message': "账号已删除"} |
||||
USER_LOGIN_ERROR = {'code': 20004, 'message': "账号或密码错误"} |
||||
LOGIN_EXPIRED = {'code': 20005, 'message': "登录信息过期"} |
||||
USER_LOGOUT = {'code': 20006, 'message': '用户注销'} |
||||
|
||||
# 业务错误:30001-39999 |
||||
SPECIFIED_QUESTIONED_USER_NOT_EXIST = {'code': 30001, 'message': "某业务出现问题"} |
||||
DATA_OCCUPATION = {'code': 30002, 'message': "数据占用"} |
||||
BASIC_INFO_IS_USING = {'code': 30003, 'message': "该基础信息正在被使用,请删除正在使用该信息的库存再删除该信息"} |
||||
NOT_ALLOW_DELETE_HIS_IN_STOCK_INTO = {'code': 30004, 'message': "不允许删除单条his入库信息,请从入库单删除"} |
||||
GROUP_INFO_IS_USING = {'code': 30005, 'message': "该小组信息正在被使用,无法直接删除小组名称"} |
||||
|
||||
# 系统错误:40001-49999 |
||||
SYSTEM_INNER_ERROR = {'code': 40001, 'message': "系统繁忙,请稍后重试"} |
||||
|
||||
# 数据错误:50001-599999 |
||||
SOURCE_DATA_NONE = {'code': 50001, 'message': "数据未找到"} |
||||
DATA_IS_WRONG = {'code': 50002, 'message': "数据有误"} |
||||
DATA_ALREADY_EXISTED = {'code': 50003, 'message': "数据已存在"} |
||||
|
||||
# 接口错误:60001-69999 |
||||
INTERFACE_INNER_INVOKE_ERROR = {'code': 60001, 'message': "内部系统接口调用异常"} |
||||
INTERFACE_OUTER_INVOKE_ERROR = {'code': 60002, 'message': "外部系统接口调用异常"} |
||||
INTERFACE_FORBID_VISIT = {'code': 60003, 'message': "该接口禁止访问"} |
||||
INTERFACE_ADDRESS_INVALID = {'code': 60004, 'message': "接口地址无效"} |
||||
INTERFACE_REQUEST_TIMEOUT = {'code': 60005, 'message': "接口请求超时"} |
||||
INTERFACE_EXCEED_LOAD = {'code': 60006, 'message': "接口负载过高"} |
||||
|
||||
# 权限错误:70001-79999 |
||||
NOT_FOUND_AUTHORIZATION = {'code': 70001, 'message': "请求头必须携带token字段"} |
||||
AUTHENTICATION_NO_ACCESS = {'code': 70002, 'message': "认证失败"} |
||||
PERMISSION_NO_ACCESS = {'code': 70003, 'message': "权限不足"} |
||||
INVALID_TOKEN = {'code': 70004, 'message': "无效token"} |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,31 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
utils.BatchCode |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
入库批次码生成,随机9位. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from random import randint |
||||
from utils.apiDoc import * |
||||
|
||||
|
||||
def GetBatchCode(): |
||||
range_start = 10 ** (9 - 1) |
||||
range_end = (10 ** 9) - 1 |
||||
batchCode = randint(range_start, range_end) |
||||
while not ReagtStock.query.filter_by(Code=F'{batchCode}').first() is None: |
||||
batchCode = randint(range_start, range_end) |
||||
return batchCode |
||||
|
||||
|
||||
def GetGroupCode(): |
||||
range_start = 10 ** (9 - 1) |
||||
range_end = (10 ** 9) - 1 |
||||
batchCode = randint(range_start, range_end) |
||||
while not ReagtGroup.query.filter_by(GroupCode=F'{batchCode}').first() is None: |
||||
batchCode = randint(range_start, range_end) |
||||
return batchCode |
||||
|
@ -0,0 +1,22 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
utils.Dict2Obj |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
dic to class. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
|
||||
|
||||
class Dict2Obj(object): |
||||
""" |
||||
Turns a dictionary into a class |
||||
""" |
||||
|
||||
# ---------------------------------------------------------------------- |
||||
def __init__(self, dictionary): |
||||
"""Constructor""" |
||||
for key in dictionary: |
||||
setattr(self, key, dictionary[key]) |
@ -0,0 +1,54 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
utils.List2Json |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
Sql_alchemy的实体转json. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
import decimal |
||||
import types |
||||
from datetime import datetime |
||||
|
||||
from flask import json |
||||
from sqlalchemy.ext.declarative import DeclarativeMeta |
||||
|
||||
|
||||
class AlchemyEncoder(json.JSONEncoder): |
||||
|
||||
def default(self, obj): |
||||
if isinstance(obj.__class__, DeclarativeMeta): |
||||
# an SQLAlchemy class |
||||
fields = {} |
||||
for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']: |
||||
data = obj.__getattribute__(field) |
||||
if field == 'query' or field == 'query_class': |
||||
continue |
||||
try: |
||||
# json.dumps(data, ensure_ascii=False) this will fail on non-encodable values, like other classes |
||||
if str(data) == 'None': |
||||
data = '' |
||||
if isinstance(data, types.GeneratorType): |
||||
data |
||||
fields[field] = str(data) |
||||
if isinstance(data, bool) or isinstance(data, int): |
||||
fields[field] = data |
||||
if isinstance(data, decimal.Decimal): |
||||
return (str(data) for data in [data]) |
||||
except TypeError: |
||||
fields[field] = None |
||||
# a json-encodable dict |
||||
return fields |
||||
|
||||
return json.JSONEncoder.default(self, obj) |
||||
|
||||
|
||||
class DecimalEncoder(json.JSONEncoder): |
||||
def default(self, obj): |
||||
if isinstance(obj, decimal.Decimal): |
||||
return float(obj) |
||||
if isinstance(obj, datetime): |
||||
return str(obj) |
||||
return super(DecimalEncoder, self).default(obj) |
@ -0,0 +1,91 @@ |
||||
from datetime import datetime, date |
||||
|
||||
|
||||
def db_page(entity_filter, order, data, number): |
||||
"""分页帮助方法. |
||||
|
||||
对db.session出来的实体进行分页 |
||||
|
||||
Args: |
||||
entity_filter: an entity that need pagination. |
||||
order: Sort by. |
||||
data: get pageNumber. |
||||
number: Number of lists per page |
||||
|
||||
Returns: |
||||
可供json转换的dict |
||||
|
||||
Raises: |
||||
TYPEError: 类型转换出错 |
||||
""" |
||||
entityPaginate = entity_filter.order_by(order.desc()).paginate( |
||||
int(data.get('pageNumber')), number, |
||||
error_out=False) |
||||
resultList = [] |
||||
for (i, result) in enumerate(entityPaginate.items): |
||||
result_modified = dict(zip(result.keys(), result)) |
||||
for (j, child) in enumerate(result): |
||||
if type(child) == date or type(child) == datetime: |
||||
result_modified.__setitem__(result.keys()[j], str(child)) |
||||
resultList.append(result_modified) |
||||
return resultList |
||||
|
||||
|
||||
def db_page_entity(entity, data, number): |
||||
"""分页帮助方法. |
||||
|
||||
对实体查询出来的实体集合进行分页 |
||||
|
||||
Args: |
||||
entity: an entity that need pagination. |
||||
data: get pageNumber. |
||||
number: Number of lists per page |
||||
|
||||
Returns: |
||||
可供json转换的dict |
||||
|
||||
Raises: |
||||
TYPEError: 类型转换出错 |
||||
""" |
||||
data_list = entity.paginate(int(data.get('pageNumber')), number, error_out=False) |
||||
result_list = [dict(zip([attr for attr in dir(result) if '_' not in attr and |
||||
attr is not 'query' and |
||||
attr is not 'metadata'], |
||||
[str(getattr(result, attr)) if |
||||
type(getattr(result, attr)) == date or |
||||
type(getattr(result, attr)) == datetime else |
||||
getattr(result, attr) for attr in dir(result) if '_' not in attr and |
||||
attr is not 'query' and |
||||
attr is not 'metadata'])) |
||||
for result in data_list.items] |
||||
return result_list |
||||
|
||||
|
||||
def entityDictToStringDict(resultList): |
||||
""" |
||||
没啥用的函数,以前用来转换json数据为string模式的,更新了之后可以支持所有类型的数据 以前是因为json.dumps()不支持decimal类型的数据 |
||||
用List2Json中的方法转换为float就解决了 |
||||
""" |
||||
jsonList = [] |
||||
for dic in resultList: |
||||
dicItem = {} |
||||
for key, value in dic.items(): |
||||
if value is None: |
||||
value = '' |
||||
dicItem[key] = str(value) |
||||
jsonList.append(dicItem) |
||||
return jsonList |
||||
|
||||
|
||||
def singleEntityToJson(singleEntity): |
||||
""" |
||||
单条数据转json,不需要分页的 |
||||
""" |
||||
dictList = [dict(zip([attr for attr in dir(singleEntity) if '_' not in attr and |
||||
attr is not 'query' and |
||||
attr is not 'metadata'], |
||||
[getattr(singleEntity, attr) for attr in dir(singleEntity) |
||||
if '_' not in attr and |
||||
attr is not 'query' and |
||||
attr is not 'metadata']))] |
||||
return dictList[0] |
@ -0,0 +1,12 @@ |
||||
from web import * |
||||
|
||||
|
||||
def ReagentTypeSort(List): |
||||
newList = [] |
||||
for item in List: |
||||
if item['hasChildren']: |
||||
newList.append(item) |
||||
for itemFalse in List: |
||||
if not itemFalse['hasChildren']: |
||||
newList.append(itemFalse) |
||||
return newList |
@ -0,0 +1,56 @@ |
||||
# -*- coding: utf-8 -*- |
||||
""" |
||||
utils.apiDoc |
||||
~~~~~~~~~~~~~~ |
||||
|
||||
flask_rest_plus的配置以及所有接口的引用. |
||||
|
||||
:copyright: 云南新八达科技有限公司. |
||||
:author: 李进才. |
||||
""" |
||||
from flask import Flask, url_for, redirect, request |
||||
from flask_sqlalchemy import SQLAlchemy |
||||
from utils.jwt import * |
||||
from models.entity import * |
||||
from statusCode.resultCode import * |
||||
from statusCode.responseEntity import * |
||||
import json |
||||
from utils.Dict2Obj import * |
||||
from flask_restplus import Resource, Api, fields |
||||
from models.db import * |
||||
|
||||
|
||||
@app.before_request |
||||
def authenticate(): |
||||
token = request.headers.get('X-Token') |
||||
app.logger.info(request.path) |
||||
if verify_jwt(token) is None and request.path != '/User/login' and request.path != '/' and request.path.find( |
||||
'swagger') == -1: |
||||
return SuccessResponse(ResultCode.INVALID_TOKEN, None, |
||||
None) |
||||
|
||||
|
||||
api = Api(app, title="Reagent Information System", description="Reagent Management System") |
||||
user = api.namespace('User', description='User Information Operating') |
||||
stock = api.namespace('Stock', description='Reagent Stock Info And Management') |
||||
entry = api.namespace('Entry', description='input default tip management') |
||||
bad = api.namespace('Bad', description='Loss of reagent') |
||||
log = api.namespace('Log', description='Log of Stock') |
||||
dictionary = api.namespace('Dictionary', description='Basic Dictionary of reagent') |
||||
statistics = api.namespace('Statistics', description='Statistics of reagent') |
||||
inventory = api.namespace('Inventory', description='库存盘点') |
||||
approve = api.namespace('Approve', description='请购相关处理') |
||||
file = api.namespace('File', description='文件上传等相关操作') |
||||
authority = api.namespace("Authority", description='相关权限的操作') |
||||
basic = api.namespace('Basic', description='basic Dictionary of manager ') |
||||
accounting = api.namespace('Accounting', description='用量核算') |
||||
|
||||
in_stock_model = stock.model("inStockData", |
||||
{"Name": fields.String, "Specification": fields.String, "Day": fields.Integer, |
||||
"Maker": fields.String, "CertificationCode": fields.String, |
||||
"UnitPrice": fields.Integer, "SellingPrice": fields.Integer, |
||||
"MaxValue": fields.Integer, "MinValue": fields.Integer, |
||||
"ProductionBatch": fields.String, "TypeName": fields.String, |
||||
"Position": fields.String, "Number": fields.Integer, |
||||
"SupplierName": fields.String}, |
||||
"remark") |
@ -0,0 +1,21 @@ |
||||
from sqlalchemy import or_ |
||||
|
||||
from utils.PageHepler import db_page_entity |
||||
from utils.apiDoc import * |
||||
|
||||
|
||||
def get_basic_entry_list(entity, data, entity_order): |
||||
reagentEntity = db.session.query(entity) \ |
||||
.order_by(entity_order) |
||||
if request.args.get('query') is not None: |
||||
reagentEntity = db.session.query(entity) \ |
||||
.filter(or_(entity.Name.contains(data.get('query')), |
||||
entity.PinYinCode.contains(data.get('query')), |
||||
entity.Maker.contains(data.get('query')))) \ |
||||
.order_by(entity_order) |
||||
return SuccessResponse(ResultCode.SUCCESS, |
||||
{'totalNumber': reagentEntity.count(), 'list': |
||||
db_page_entity(reagentEntity, data, 12)}, None) |
||||
|
||||
|
||||
|
@ -0,0 +1,64 @@ |
||||
import configparser |
||||
|
||||
config = configparser.ConfigParser() |
||||
config.read('./config/operatingType.ini') |
||||
|
||||
|
||||
def GetOperatingTypeBad(): |
||||
return config.get('operatingType', 'bad') |
||||
|
||||
|
||||
def GetOperatingTypeScrap(): |
||||
return config.get('operatingType', 'scrap') |
||||
|
||||
|
||||
def GetOperatingTypeInStock(): |
||||
return config.get('operatingType', 'inStock') |
||||
|
||||
|
||||
def GetOperatingTypeOutStock(): |
||||
return config.get('operatingType', 'outStock') |
||||
|
||||
|
||||
def GetOperatingTypeUpdate(): |
||||
return config.get('operatingType', 'update') |
||||
|
||||
|
||||
def GetOperatingTypeEdit(): |
||||
return config.get('operatingType', 'edit') |
||||
|
||||
|
||||
def GetOperatingTypeUseName(name): |
||||
return config.get('operatingType', name) |
||||
|
||||
|
||||
def GetOperatingTypeBasicReagentOpen(): |
||||
return config.get('operatingType', 'basicReagentOpen') |
||||
|
||||
|
||||
def GetOperatingTypeBasicReagentClose(): |
||||
return config.get('operatingType', 'basicReagentClose') |
||||
|
||||
|
||||
def GetOperatingTypeBasicEntryOpen(): |
||||
return config.get('operatingType', 'basicEntryOpen') |
||||
|
||||
|
||||
def GetOperatingTypeBasicEntryClose(): |
||||
return config.get('operatingType', 'basicEntryClose') |
||||
|
||||
|
||||
def GetOperatingTypeDelete(): |
||||
return config.get('operatingType', 'delete') |
||||
|
||||
|
||||
def GetApproveTypeApproving(): |
||||
return config.get('approveType', 'approving') |
||||
|
||||
|
||||
def GetApproveTypeApproved(): |
||||
return config.get('approveType', 'approved') |
||||
|
||||
|
||||
def GetApproveTypeOverrule(): |
||||
return config.get('approveType', 'overrule') |
@ -0,0 +1,26 @@ |
||||
#!/usr/bin/python |
||||
# -*- coding: utf-8 -*- |
||||
import binascii |
||||
from pyDes import des, CBC, PAD_PKCS5 |
||||
secret_key = '021ynxbd' |
||||
|
||||
|
||||
def des_encrypt(s): |
||||
iv = secret_key |
||||
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5) |
||||
en = k.encrypt(s, padmode=PAD_PKCS5) |
||||
return binascii.b2a_hex(en) |
||||
|
||||
|
||||
def des_decrypt(s): |
||||
iv = secret_key |
||||
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5) |
||||
de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5) |
||||
return de |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
secret_str = des_encrypt('XBD.User@000626') |
||||
print('密文:', secret_str) |
||||
clear_str = des_decrypt(secret_str) |
||||
print('明文:', clear_str) |
@ -0,0 +1,39 @@ |
||||
from sqlalchemy import or_ |
||||
from models.entity import * |
||||
|
||||
from statusCode.responseEntity import SuccessResponse, BadResponse |
||||
from statusCode.resultCode import ResultCode |
||||
from utils.PageHepler import db_page_entity |
||||
|
||||
|
||||
def GetList(entity, entityId, name, code, data, length=6, is_all=False): |
||||
filterItem = entity.query.order_by(entityId.desc()) |
||||
if data.get('query') is not None: |
||||
filterItem = entity.query.filter( |
||||
or_(name.contains(data['query']), |
||||
code.contains(data['query']))) \ |
||||
.order_by(entityId.desc()) |
||||
if is_all: |
||||
length = filterItem.count() |
||||
return SuccessResponse(ResultCode.SUCCESS, {'totalNumber': filterItem.count(), |
||||
'list': db_page_entity(filterItem, data, length)}, None) |
||||
|
||||
|
||||
def StatusChange(entity, dataId, data, entityId, stockNameLeft, stockNameRight): |
||||
filterItem = entity.query.filter(entityId == dataId).first() |
||||
if len(ReagtStock.query.filter(stockNameLeft == stockNameRight).all()) != 0: |
||||
return SuccessResponse(ResultCode.DATA_OCCUPATION, None, None) |
||||
using = data['Using'] != 'false' |
||||
if filterItem.Using == using: |
||||
return BadResponse(ResultCode.PARAM_IS_INVALID, None, None) |
||||
filterItem.Using = using |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
||||
|
||||
|
||||
def DictionaryAdd(existEntity, newEntity): |
||||
if existEntity is not None: |
||||
return SuccessResponse(ResultCode.DATA_ALREADY_EXISTED, None, None) |
||||
db.session.add(newEntity) |
||||
db.session.commit() |
||||
return SuccessResponse(ResultCode.SUCCESS, None, None) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue