warehouse.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, Query, HTTPException, status,WebSocket,WebSocketDisconnect
  4. from common.security import valid_access_token,valid_websocket_token
  5. from fastapi.responses import JSONResponse,StreamingResponse
  6. from common.db import db_czrz
  7. from sqlalchemy.orm import Session
  8. from sqlalchemy.sql import func
  9. from common.auth_user import *
  10. from sqlalchemy import text
  11. from pydantic import BaseModel
  12. from common.BigDataCenterAPI import *
  13. from database import get_db
  14. from typing import List
  15. from models import *
  16. from utils import *
  17. from utils.spatial import *
  18. from utils.ry_system_util import *
  19. from utils.resource_provision_util import *
  20. from common.websocketManager import *
  21. import json
  22. import traceback
  23. import xlrd
  24. import os
  25. # 目录在文档上传接口写死
  26. UPLOAD_mergefile_PATH = '/data/upload/mergefile'
  27. router = APIRouter()
  28. @router.post("/create")
  29. async def create_pattern(
  30. user_id=Depends(valid_access_token),
  31. body = Depends(remove_xss_json),
  32. db: Session = Depends(get_db)
  33. ):
  34. try:
  35. new_type = ResourceProvisionWarehouseInfo(
  36. warehouse_id = new_guid(),
  37. warehouse_name=body['warehouse_name'],
  38. status=body['status'],
  39. contact_person=body['contact_person'],
  40. contact_phone=body['contact_phone'],
  41. address=body['address'],
  42. type=body['type'],
  43. level=body['level'],
  44. storage_dept_id=body['storage_dept_id'],
  45. storage_dept_name='', #body['storage_dept_name']
  46. area_name=body['area_name'],
  47. longitude=body['longitude'],
  48. latitude=body['latitude'],
  49. area =body['area'],
  50. remark=body['remark'],
  51. create_by = user_id
  52. )
  53. db.add(new_type)
  54. db.commit()
  55. return {"code": 200, "msg": "创建成功", "data": None}
  56. except Exception as e:
  57. traceback.print_exc()
  58. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  59. @router.put("/update/{id}")
  60. async def update_pattern(
  61. id :str ,
  62. user_id=Depends(valid_access_token),
  63. body=Depends(remove_xss_json),
  64. db: Session = Depends(get_db)
  65. ):
  66. try:
  67. update_warehouse = warehouse_id_get_warehouse_info(db,id)
  68. if not update_warehouse:
  69. return JSONResponse(status_code=404,content={"code":404,"msg":"warehouse not found"})
  70. update_warehouse.warehouse_name = body['warehouse_name']
  71. update_warehouse.status = body['status']
  72. update_warehouse.contact_person = body['contact_person']
  73. update_warehouse.contact_phone = body['contact_phone']
  74. update_warehouse.address = body['address']
  75. update_warehouse.type = body['type']
  76. update_warehouse.level = body['level']
  77. update_warehouse.storage_dept_id = body['storage_dept_id']
  78. update_warehouse.storage_dept_name = body['storage_dept_name']
  79. update_warehouse.area_name = body['area_name']
  80. update_warehouse.longitude = body['longitude']
  81. update_warehouse.latitude = body['latitude']
  82. update_warehouse.area = body['area']
  83. update_warehouse.remark = body['remark']
  84. update_warehouse.update_by = user_id
  85. db.commit()
  86. return {"code": 200, "msg": "更新成功"}
  87. except Exception as e:
  88. traceback.print_exc()
  89. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  90. @router.get("/info/{id}")
  91. async def get_pattern_info(
  92. id: str,
  93. user_id=Depends(valid_access_token),
  94. db: Session = Depends(get_db)
  95. ):
  96. try:
  97. info = warehouse_id_get_warehouse_info(db,id)
  98. if not info:
  99. return JSONResponse(status_code=404,content={"code":404,"msg":"warehouse not found"})
  100. dept_info = dept_id_get_dept_info(db,info.storage_dept_id)
  101. data = {"warehouse_id": info.warehouse_id,
  102. "warehouse_name": info.warehouse_name,
  103. "status": info.status,
  104. "contact_person": info.contact_person,
  105. "contact_phone": info.contact_phone,
  106. "address": info.address,
  107. "remark": info.remark,
  108. "type": info.type,
  109. "level": info.level,
  110. "storage_dept_id": info.storage_dept_id,
  111. "storage_dept_name": dept_info.dept_name,
  112. "area_name": info.area_name,
  113. "longitude": info.longitude,
  114. "latitude": info.latitude,
  115. "create_by": info.create_by,
  116. "area":info.area,
  117. "create_time":info.create_time}
  118. return {"code": 200, "msg": "获取成功", "data": data}
  119. except Exception as e:
  120. traceback.print_exc()
  121. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  122. @router.get("/list")
  123. async def get_pattern_list(
  124. # name: str = Query(None, description='名称'),
  125. user_id=Depends(valid_access_token),
  126. page: int = Query(1, gt=0, description='页码'),
  127. pageSize: int = Query(None, gt=0, description='每页条目数量'),
  128. db: Session = Depends(get_db)
  129. ):
  130. try:
  131. query = db.query(ResourceProvisionWarehouseInfo)
  132. query = query.filter_by(del_flag='0')
  133. # if name:
  134. # query = query.filter(ResourceProvisionWarehouseInfo.material_category_name.like(f'%{name}%'))
  135. total_items = query.count()
  136. if pageSize is None:
  137. pageSize=total_items
  138. # 排序
  139. query = query.order_by(ResourceProvisionWarehouseInfo.create_time.desc())
  140. # 执行分页查询
  141. lists = query.offset((page - 1) * pageSize).limit(pageSize).all()
  142. data = [ ]
  143. for info in lists:
  144. dept_info = dept_id_get_dept_info(db, info.storage_dept_id)
  145. data.append({"warehouse_id": info.warehouse_id,
  146. "warehouse_name": info.warehouse_name,
  147. "status": info.status,
  148. "contact_person": info.contact_person,
  149. "contact_phone": info.contact_phone,
  150. "address": info.address,
  151. "remark": info.remark,
  152. "type": info.type,
  153. "level": info.level,
  154. "storage_dept_id": info.storage_dept_id,
  155. "storage_dept_name": dept_info.dept_name,
  156. "area_name": info.area_name,
  157. "longitude": info.longitude,
  158. "latitude": info.latitude,
  159. "create_by": info.create_by,
  160. "area":info.area,
  161. "create_time":info.create_time})
  162. return {"code": 200, "msg": "查询成功", "data": data,
  163. "total": total_items,
  164. "page": page,
  165. "pageSize": pageSize,
  166. "totalPages": (total_items + pageSize - 1) // pageSize
  167. }
  168. except Exception as e:
  169. traceback.print_exc()
  170. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  171. @router.get("/export")
  172. async def export_data(
  173. request: Request,
  174. # name: str = Query(None, description='名称'),
  175. user_id=Depends(valid_access_token),
  176. auth_user: AuthUser = Depends(find_auth_user),
  177. db: Session = Depends(get_db)
  178. ):
  179. try:
  180. query = db.query(ResourceProvisionWarehouseInfo)
  181. query = query.filter_by(del_flag='0')
  182. # if name:
  183. # query = query.filter(ResourceProvisionWarehouseInfo.material_category_name.like(f'%{name}%'))
  184. # 排序
  185. query = query.order_by(ResourceProvisionWarehouseInfo.create_time.desc())
  186. # 执行分页查询
  187. lists = query.all()
  188. data = []
  189. for info in lists:
  190. dept_info = dept_id_get_dept_info(db, info.storage_dept_id)
  191. data.append({"仓库id": info.warehouse_id,
  192. "仓库": info.warehouse_name,
  193. "状态": info.status,
  194. "联系人": info.contact_person,
  195. "联系电话": info.contact_phone,
  196. "地址": info.address,
  197. "备注": info.remark,
  198. "类型": info.type,
  199. "等级": info.level,
  200. "物资保管部门id": info.storage_dept_id,
  201. "物资保管部门名称": dept_info.dept_name,
  202. "地区": info.area_name,
  203. "经度": info.longitude,
  204. "纬度": info.latitude,
  205. "创建者": info.create_by,
  206. "占地面积(平方米)":info.area,
  207. "数据创建时间":info.create_time})
  208. # 返回结果
  209. import pandas as pd
  210. from io import BytesIO
  211. # 将查询结果转换为 DataFrame
  212. df = pd.DataFrame(data)
  213. # 将 DataFrame 导出为 Excel 文件
  214. output = BytesIO()
  215. with pd.ExcelWriter(output, engine='openpyxl') as writer:
  216. df.to_excel(writer, index=False)
  217. # 设置响应头
  218. output.seek(0)
  219. from urllib.parse import quote
  220. encoded_filename = f'仓库明细{datetime.now().strftime("%Y%m%d%H%mi%s")}.xlsx'
  221. encoded_filename = quote(encoded_filename, encoding='utf-8')
  222. headers = {
  223. 'Content-Disposition': f'attachment; filename*=UTF-8\'\'{encoded_filename}',
  224. 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  225. }
  226. db_czrz.log(db, auth_user, "物资储备管理", f"物资储备管理仓库明细导出数据成功", request.client.host)
  227. # 返回文件流
  228. return StreamingResponse(output, headers=headers)
  229. except Exception as e:
  230. traceback.print_exc()
  231. return JSONResponse(status_code=500, content={"code": 500, "msg": f"Internal server error: {str(e)}"})
  232. @router.delete("/delete/{id}")
  233. async def delete_pattern(
  234. id: str,
  235. user_id=Depends(valid_access_token),
  236. db: Session = Depends(get_db)
  237. ):
  238. try:
  239. # 检查图案是否存在
  240. info = warehouse_id_get_warehouse_info(db, id)
  241. if not info:
  242. return JSONResponse(status_code=404, content={"code": 404, "msg": "warehouse not found"})
  243. info.del_flag='2'
  244. db.commit()
  245. return {"code": 200, "msg": "删除成功"}
  246. except Exception as e:
  247. traceback.print_exc()
  248. raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")
  249. @router.post("/import_data")
  250. async def import_data(
  251. body = Depends(remove_xss_json),
  252. user_id=Depends(valid_access_token), db: Session = Depends(get_db)):
  253. # 获取表结构
  254. import os,openpyxl
  255. schema_name = "mmyjhd"
  256. table_name = "resource_provision_warehouse_info"
  257. columns = [{"column_name":"warehouse_name","column_comment":"仓库名称"},
  258. {"column_name":"status","column_comment":"状态1启用0关闭"},
  259. {"column_name":"contact_person","column_comment":"联系人"},
  260. {"column_name":"contact_phone","column_comment":"联系电话"},
  261. {"column_name":"address","column_comment":"地址"},
  262. {"column_name":"type","column_comment":"类型"},
  263. {"column_name":"level","column_comment":"等级"},
  264. {"column_name":"storage_dept_name","column_comment":"物资保管部门名称"},
  265. {"column_name":"area_name","column_comment":"地区(区县)"},
  266. {"column_name":"longitude","column_comment":"经度"},
  267. {"column_name":"latitude","column_comment":"纬度"},
  268. {"column_name":"area","column_comment":"占地面积(平方米)"},
  269. {"column_name":"remark","column_comment":"备注"}]
  270. filename = body['filename']
  271. if '../' in filename or '/' in filename:
  272. return JSONResponse(status_code=400, content={'code': 400, "msg": '警告:禁止篡改文件路径'})
  273. file_path = f'/data/upload/mergefile/uploads/{filename}'
  274. if not os.path.exists(file_path):
  275. return JSONResponse(status_code=404, content={'code': 404, 'msg': f"文件不存在"})
  276. # print("文件不存在,请检查路径!")
  277. # 读取 Excel 文件
  278. try:
  279. workbook = openpyxl.load_workbook(file_path)
  280. sheet = workbook.active
  281. data = pd.read_excel(file_path, header=1)
  282. data = data.to_dict(orient='records')
  283. except Exception as e:
  284. traceback.print_exc()
  285. return JSONResponse(status_code=400, content={'code': 400, 'msg': f"接口发生错误:{e}"})
  286. # raise HTTPException(status_code=400, detail="Invalid Excel file")
  287. # 获取字段名和字段备注名
  288. column_names = [col["column_name"] for col in columns if col["column_name"]!='id']
  289. column_comments = [col["column_comment"] for col in columns if col["column_name"]!='id']
  290. # 检查第一行是否为字段备注名
  291. first_row = [cell.value for cell in sheet[1]]
  292. if first_row != column_comments:
  293. print("接口发生错误:Excel columns do not match the expected columns")
  294. return JSONResponse(status_code=400, content={'code': 400, 'msg': f"接口发生错误:Excel columns do not match the expected columns"})
  295. # raise HTTPException(status_code=400, detail="Excel columns do not match the expected columns")
  296. # 检查第二行是否为字段名
  297. second_row = [cell.value for cell in sheet[2]]
  298. if second_row != column_names:
  299. print("接口发生错误:Excel columns do not match the expected columns")
  300. return JSONResponse(status_code=400,
  301. content={'code': 400, 'msg': f"接口发生错误:Excel columns do not match the expected columns"})
  302. # raise HTTPException(status_code=400, detail="Excel columns do not match the expected columns")
  303. # 将数据插入到数据库
  304. try:
  305. # insert_query = text(
  306. # f"INSERT INTO `{schema_name}`.`{table_name}` ({', '.join(column_names)}) VALUES ({', '.join([':' + col for col in column_names])})")
  307. # for row in sheet.iter_rows(min_row=3, values_only=True):
  308. for row in data:
  309. infotype = row['type']
  310. 'warehouse_type'
  311. 'warehouse_level'
  312. new_type = ResourceProvisionWarehouseInfo(
  313. warehouse_id=new_guid(),
  314. warehouse_name=row['warehouse_name'],
  315. status=row['status'],
  316. contact_person=row['contact_person'],
  317. contact_phone=row['contact_phone'],
  318. address=row['address'],
  319. type=infotype,
  320. level=row['level'],
  321. storage_dept_id=row['storage_dept_id'],
  322. storage_dept_name=row['storage_dept_name'], # body['storage_dept_name']
  323. area_name=row['area_name'],
  324. longitude=row['longitude'],
  325. latitude=row['latitude'],
  326. area=row['area'],
  327. remark=row['remark'],
  328. create_by=user_id
  329. )
  330. db.add(new_type)
  331. db.commit()
  332. # db.execute(insert_query, dict(zip(column_names, row)))
  333. # db.commit()
  334. return {"code":200,"msg": "Data imported successfully"}
  335. except Exception as e:
  336. db.rollback()
  337. traceback.print_exc()
  338. return JSONResponse(status_code=500,
  339. content={'code': 500, 'msg': f"接口发生错误:{e}"})
  340. # 导入
  341. @router.post('/import')
  342. async def import_doc(
  343. request: Request,
  344. db: Session = Depends(get_db),
  345. body = Depends(remove_xss_json),
  346. user_id = Depends(valid_access_token)
  347. ):
  348. # print(body)
  349. try:
  350. filename = body['filename']
  351. if len(filename) == 0:
  352. raise Exception()
  353. file = filename[0]
  354. url = file['url']
  355. file_path = f"{UPLOAD_mergefile_PATH}/uploads/{url}"
  356. file_path = os.path.abspath(file_path)
  357. print(file_path)
  358. book = xlrd.open_workbook(file_path)
  359. sheet = book.sheet_by_index(0)
  360. data = []
  361. '''
  362. for i in range(9, sheet.nrows):
  363. # 预案名称
  364. plan_name = sheet.cell(i, 0).value
  365. # 一级目录
  366. title1 = sheet.cell(i, 1).value
  367. # 二级目录
  368. title2 = sheet.cell(i, 2).value
  369. # 三级目录
  370. title3 = sheet.cell(i, 3).value
  371. # 正文
  372. content = sheet.cell(i, 4).value
  373. if len(plan_name) < 1 and len(title1) < 1 and len(title2) < 1 and len(title3) < 1 and len(content) < 1 :
  374. break
  375. data.append({
  376. 'plan_name': plan_name,
  377. 'title1': title1,
  378. 'title2': title2,
  379. 'title3': title3,
  380. 'content': content,
  381. })
  382. if len(data) > 0:
  383. db.query(EmergencyDoc).filter(EmergencyDoc.plan_id == plan_id).delete()
  384. db.commit()
  385. title1 = ''
  386. content = ''
  387. docs = []
  388. for n in data:
  389. if n['title1'] != '':
  390. if len(docs) > 0:
  391. add_doc_1(db, title1, content, docs, plan_id)
  392. docs = []
  393. title1 = n['title1']
  394. content = n['content']
  395. if n['title2'] != '':
  396. docs.append(n)
  397. continue
  398. docs.append(n)
  399. if len(docs) > 0:
  400. add_doc_1(db, title1, content, docs, plan_id)
  401. '''
  402. return {
  403. 'code': 200,
  404. 'msg': '导入成功'
  405. }
  406. except Exception:
  407. traceback.print_exc()
  408. return {
  409. 'code': 500,
  410. 'msg': '导入发生异常'
  411. }