schedule.py 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, Query, HTTPException, status, BackgroundTasks
  4. from common.security import valid_access_token
  5. from fastapi.responses import JSONResponse, FileResponse,StreamingResponse
  6. from sqlalchemy.orm import Session
  7. from sqlalchemy import and_, or_
  8. from sqlalchemy.sql import func
  9. from common.auth_user import *
  10. from pydantic import BaseModel
  11. from common.db import db_dept
  12. from common.db import db_czrz
  13. from exceptions import AppException, HmacException
  14. from database import get_db
  15. from typing import List
  16. from models import *
  17. from utils import *
  18. from utils.ry_system_util import *
  19. from utils.video_util import *
  20. import traceback
  21. import os
  22. import json
  23. router = APIRouter()
  24. def name_get_user_id(db,keywords):
  25. query = db.query(EmergencyContactUser)
  26. query = query.filter(EmergencyContactUser.del_flag != '2')
  27. query = query.filter(EmergencyContactUser.name.like(f"%{keywords}%"))
  28. data = query.all()
  29. return [info.id for info in data]
  30. def user_id_get_duty_id(db,user_id_list):
  31. query = db.query(DutyPersonnelArrangement)
  32. query = query.filter(DutyPersonnelArrangement.del_flag != '2')
  33. query = query.filter(DutyPersonnelArrangement.personnel_id.in_(user_id_list))
  34. data = query.all()
  35. return [info.duty_id for info in data]
  36. def duty_id_get_user_id(db,duty_id):
  37. query = db.query(DutyPersonnelArrangement)
  38. query = query.filter(DutyPersonnelArrangement.del_flag != '2')
  39. query = query.filter(DutyPersonnelArrangement.duty_id==duty_id)
  40. data = query.all()
  41. return data
  42. def user_id_get_info(db,user_id):
  43. query = db.query(EmergencyContactUser)
  44. query = query.filter(EmergencyContactUser.del_flag != '2')
  45. query = query.filter(EmergencyContactUser.id==user_id)
  46. data = query.first()
  47. return data
  48. def position_id_get_info(db,position_id):
  49. query = db.query(DutyPosition)
  50. query = query.filter(DutyPosition.del_flag != '2')
  51. query = query.filter(DutyPosition.id==position_id)
  52. data = query.first()
  53. return data
  54. def dept_id_get_info(db,dept_id):
  55. query = db.query(EmergencyContactDepartment)
  56. query = query.filter(EmergencyContactDepartment.del_flag != '2')
  57. query = query.filter(EmergencyContactDepartment.id==dept_id)
  58. data = query.first()
  59. return data
  60. def get_duty_unit_id_list(db):
  61. query = db.query(SysDictData)
  62. query = query.filter(SysDictData.del_flag != '2')
  63. query = query.filter(SysDictData.dict_type=='duty_unit')
  64. data = query.all()
  65. return [int(i.dict_value) for i in data]
  66. def dept_id_get_duty_unit_id(db,dept_id,duty_unit_id_list):
  67. if dept_id == 0:
  68. return 0
  69. if dept_id in duty_unit_id_list:
  70. return dept_id
  71. query = db.query(EmergencyContactDepartment)
  72. query = query.filter(EmergencyContactDepartment.del_flag != '2')
  73. query = query.filter(EmergencyContactDepartment.id==dept_id)
  74. data = query.first()
  75. if data:
  76. dept_id_get_duty_unit_id(db, data.parent_department_id, duty_unit_id_list)
  77. else:
  78. return 0
  79. def mobile_phone_get_dept_id(db,mobile_phone,duty_unit_id_list):
  80. query = db.query(EmergencyContactUser)
  81. query = query.filter(EmergencyContactUser.del_flag != '2')
  82. query = query.filter(EmergencyContactUser.mobile_phone==mobile_phone)
  83. data = query.first()
  84. if data:
  85. dept_id = data.department_id
  86. dept_id = dept_id_get_duty_unit_id(db, dept_id, duty_unit_id_list)
  87. return dept_id
  88. else:
  89. return 0
  90. @router.get('/list')
  91. async def get_dict_data_by_type(
  92. keywords:str =Query(None),
  93. duty_type:str =Query(None),
  94. start_time:str =Query(None),
  95. end_time:str =Query(None),
  96. duty_unit:int =Query(None),
  97. page: int = Query(1, gt=0),
  98. pageSize: int = Query(10, gt=0),
  99. db: Session = Depends(get_db),
  100. body = Depends(remove_xss_json),
  101. user_id = Depends(valid_access_token)
  102. ):
  103. try:
  104. # 根据 dict_type 查询字典数据
  105. # dict_data = db.query(SysDictData).filter_by(dict_type=dictType).all()
  106. query = db.query(DutySchedule)
  107. query = query.filter(DutySchedule.del_flag != '2')
  108. # 添加查询条件
  109. if keywords:
  110. user_list= name_get_user_id(db,keywords)
  111. duty_list = user_id_get_duty_id(db,user_list)
  112. query = query.filter(DutySchedule.id.in_(duty_list))
  113. if duty_type:
  114. query = query.filter(DutySchedule.duty_type==duty_type)
  115. if start_time:
  116. start_time = datetime.strptime(start_time, "%Y-%m-%d").date()
  117. query = query.filter(DutySchedule.duty_date>=start_time)
  118. if end_time:
  119. end_time = datetime.strptime(end_time, "%Y-%m-%d").date()
  120. query = query.filter(DutySchedule.duty_date<=end_time)
  121. if duty_unit:
  122. query = query.filter(DutySchedule.duty_unit==duty_unit)
  123. # 计算总记录数
  124. total_count = query.count()
  125. # 计算分页
  126. offset = (page - 1) * pageSize
  127. query = query.order_by(DutySchedule.start_time.desc(),DutySchedule.end_time.desc(),DutySchedule.update_time.desc())
  128. duty_data = query.offset(offset).limit(pageSize).all()
  129. # 转换为字典
  130. data_list = []
  131. for d in duty_data:
  132. user_data = []
  133. user_list = duty_id_get_user_id(db,d.id)
  134. for user_info in user_list:
  135. contact_info = user_id_get_info(db, user_info.personnel_id)
  136. user_data.append({"position_id":user_info.position_id,
  137. "personnel_id":user_info.personnel_id,
  138. "name":contact_info.name,
  139. "position":contact_info.position,
  140. "mobile_phone":contact_info.mobile_phone,
  141. "office_phone":contact_info.office_phone,
  142. "department_id":contact_info.department_id,
  143. "yzy_userid":contact_info.userid})
  144. data_list.append({
  145. "id": d.id,
  146. "start_time": d.start_time.strftime('%Y-%m-%d %H:%M:%S') if d.start_time else '',
  147. "end_time":d.end_time.strftime('%Y-%m-%d %H:%M:%S') if d.end_time else '',
  148. "duty_date": d.duty_date,
  149. "shift_type":d.shift_type,
  150. "duty_unit": d.duty_unit,
  151. "duty_type": d.duty_type,
  152. "createTime": d.create_time.strftime('%Y-%m-%d %H:%M:%S') if d.create_time else '',
  153. "user_data":user_data
  154. })
  155. # 构建返回结果
  156. result = {
  157. "total": total_count,
  158. "page": page,
  159. "pageSize": pageSize,
  160. "totalPages": (total_count + pageSize - 1) // pageSize,
  161. "data": data_list,
  162. "code": 200,
  163. "msg": "查询成功"
  164. }
  165. return result
  166. except Exception as e:
  167. # 处理异常
  168. traceback.print_exc()
  169. return JSONResponse(status_code=404, content={
  170. 'code': 404,
  171. 'msg': str(e)
  172. })
  173. @router.get('/latest_by_group')
  174. async def get_dict_data_by_type(
  175. keywords:str =Query(None),
  176. start_time:str =Query(None),
  177. end_time:str =Query(None),
  178. duty_unit:int =Query(None),
  179. page: int = Query(1, gt=0),
  180. pageSize: int = Query(10, gt=0),
  181. db: Session = Depends(get_db),
  182. body = Depends(remove_xss_json),
  183. user_id = Depends(valid_access_token)
  184. ):
  185. try:
  186. # 根据 dict_type 查询字典数据
  187. # dict_data = db.query(SysDictData).filter_by(dict_type=dictType).all()
  188. query = db.query(DutySchedule)
  189. query = query.filter(DutySchedule.del_flag != '2')
  190. # 添加查询条件
  191. if keywords:
  192. user_list= name_get_user_id(db,keywords)
  193. duty_list = user_id_get_duty_id(db,user_list)
  194. query = query.filter(DutySchedule.id.in_(duty_list))
  195. if start_time:
  196. start_time = datetime.strptime(start_time, "%Y-%m-%d").date()
  197. query = query.filter(DutySchedule.duty_date>=start_time)
  198. if end_time:
  199. end_time = datetime.strptime(end_time, "%Y-%m-%d").date()
  200. query = query.filter(DutySchedule.duty_date<=end_time)
  201. if duty_unit:
  202. query = query.filter(DutySchedule.duty_unit==duty_unit)
  203. else:
  204. now_user_info=user_id_get_user_info(db,user_id)
  205. print(user_id,now_user_info.phonenumber,get_duty_unit_id_list(db))
  206. if now_user_info:
  207. query = query.filter(DutySchedule.duty_unit==mobile_phone_get_dept_id(db,mpfun.dec_data(now_user_info.phonenumber),get_duty_unit_id_list(db)))
  208. else:
  209. return {
  210. "total": 0,
  211. "page": page,
  212. "pageSize": pageSize,
  213. "totalPages": (0 + pageSize - 1) // pageSize,
  214. "data": [],
  215. "code": 200,
  216. "msg": "查询成功"
  217. }
  218. subquery = db.query(
  219. DutySchedule.duty_date,
  220. DutySchedule.shift_type,
  221. func.max(DutySchedule.update_time).label("latest_create_time")
  222. ).filter(DutySchedule.del_flag != '2').group_by(
  223. DutySchedule.duty_date,
  224. DutySchedule.shift_type
  225. ).subquery()
  226. query = query.join(
  227. subquery,
  228. and_(
  229. DutySchedule.duty_date == subquery.c.duty_date,
  230. DutySchedule.shift_type == subquery.c.shift_type,
  231. DutySchedule.update_time == subquery.c.latest_create_time
  232. )
  233. )
  234. # 计算总记录数
  235. total_count = query.count()
  236. # 计算分页
  237. offset = (page - 1) * pageSize
  238. query = query.order_by(DutySchedule.update_time.desc())
  239. print(query)
  240. duty_data = query.offset(offset).limit(pageSize).all()
  241. # 转换为字典
  242. data_list = []
  243. for d in duty_data:
  244. user_data = []
  245. user_list = duty_id_get_user_id(db,d.id)
  246. for user_info in user_list:
  247. contact_info = user_id_get_info(db, user_info.personnel_id)
  248. user_data.append({"position_id":user_info.position_id,
  249. "personnel_id":user_info.personnel_id,
  250. "name":contact_info.name,
  251. "position":contact_info.position,
  252. "mobile_phone":contact_info.mobile_phone,
  253. "office_phone":contact_info.office_phone,
  254. "department_id":contact_info.department_id,
  255. "yzy_userid":contact_info.userid})
  256. data_list.append({
  257. "id": d.id,
  258. "start_time": d.start_time.strftime('%Y-%m-%d %H:%M:%S') if d.start_time else '',
  259. "end_time":d.end_time.strftime('%Y-%m-%d %H:%M:%S') if d.end_time else '',
  260. "duty_date": d.duty_date,
  261. "shift_type":d.shift_type,
  262. "duty_unit": d.duty_unit,
  263. "duty_type": d.duty_type,
  264. "createTime": d.create_time.strftime('%Y-%m-%d %H:%M:%S') if d.create_time else '',
  265. "user_data":user_data
  266. })
  267. # 构建返回结果
  268. result = {
  269. "total": total_count,
  270. "page": page,
  271. "pageSize": pageSize,
  272. "totalPages": (total_count + pageSize - 1) // pageSize,
  273. "data": data_list,
  274. "code": 200,
  275. "msg": "查询成功"
  276. }
  277. return result
  278. except Exception as e:
  279. # 处理异常
  280. traceback.print_exc()
  281. return JSONResponse(status_code=404, content={
  282. 'code': 404,
  283. 'msg': str(e)
  284. })
  285. @router.get('/info/{id}')
  286. async def get_dict_data_by_type(
  287. id: str ,
  288. db: Session = Depends(get_db),
  289. body = Depends(remove_xss_json),
  290. user_id = Depends(valid_access_token)
  291. ):
  292. try:
  293. # 根据 dict_type 查询字典数据
  294. # dict_data = dict_type_get_dict_data_info(db,'three_proofing')
  295. query = db.query(DutySchedule)
  296. # 添加查询条件
  297. # if dictType:
  298. query = query.filter(DutySchedule.id==id)
  299. query = query.filter(DutySchedule.del_flag != '2')
  300. d = query.first()
  301. user_data = []
  302. user_list = duty_id_get_user_id(db, d.id)
  303. for user_info in user_list:
  304. contact_info = user_id_get_info(db, user_info.personnel_id)
  305. user_data.append({"position_id": user_info.position_id,
  306. "personnel_id": user_info.personnel_id,
  307. "name": contact_info.name,
  308. "position": contact_info.position,
  309. "mobile_phone": contact_info.mobile_phone,
  310. "office_phone": contact_info.office_phone,
  311. "department_id": contact_info.department_id,
  312. "yzy_userid": contact_info.userid})
  313. data_list={
  314. "id": d.id,
  315. "start_time": d.start_time,
  316. "end_time": d.end_time,
  317. "duty_date": d.duty_date,
  318. "shift_type": d.shift_type,
  319. "duty_unit": d.duty_unit,
  320. "duty_type": d.duty_type,
  321. "createTime": d.create_time.strftime('%Y-%m-%d %H:%M:%S') if d.create_time else '',
  322. "user_data": user_data
  323. }
  324. # 构建返回结果
  325. result = {
  326. "data": data_list,
  327. "code": 200,
  328. "msg": "查询成功"
  329. }
  330. return result
  331. except Exception as e:
  332. # 处理异常
  333. traceback.print_exc()
  334. return JSONResponse(status_code=404, content={
  335. 'code': 404,
  336. 'msg': str(e)
  337. })
  338. @router.post('/create')
  339. async def create_dict_data(
  340. db: Session = Depends(get_db),
  341. body = Depends(remove_xss_json),
  342. user_id = Depends(valid_access_token)
  343. ):
  344. try:
  345. # 创建一个新的 SysDictData 实例
  346. user_data = body['user_data']
  347. if len(user_data)==0:
  348. return JSONResponse(status_code=404, content={
  349. 'errcode': 404,
  350. 'errmsg': '值班人员不能为空'
  351. })
  352. new_duty_data = DutySchedule(
  353. start_time=body['start_time'],
  354. end_time=body['end_time'],
  355. duty_date=body['duty_date'],
  356. shift_type=body['shift_type'],
  357. duty_unit=body['duty_unit'],
  358. duty_type=body['duty_type'],
  359. create_by=user_id
  360. )
  361. # 添加到会话并提交
  362. db.add(new_duty_data)
  363. db.commit()
  364. db.refresh(new_duty_data)
  365. user_list = []
  366. for user_info in user_data:
  367. user_list.append( DutyPersonnelArrangement(
  368. duty_id=new_duty_data.id,
  369. position_id=user_info['position_id'],
  370. personnel_id=user_info['personnel_id'],
  371. create_by=user_id
  372. ))
  373. db.add_all(user_list)
  374. db.commit()
  375. # 构建返回结果
  376. result = {
  377. "code": 200,
  378. "msg": "操作成功",
  379. "data": None
  380. }
  381. return result
  382. except Exception as e:
  383. # 处理异常
  384. traceback.print_exc()
  385. return JSONResponse(status_code=404, content={
  386. 'code': 404,
  387. 'msg': str(e)
  388. })
  389. @router.post('/list_create')
  390. async def create_dict_data(
  391. db: Session = Depends(get_db),
  392. body = Depends(remove_xss_json),
  393. user_id = Depends(valid_access_token)
  394. ):
  395. try:
  396. # 创建一个新的 SysDictData 实例
  397. if isinstance(body,list) == False:
  398. return JSONResponse(status_code=500,content={'msg':"请求体非列表","code":500})
  399. for data in body:
  400. user_data = data['user_data']
  401. if len(user_data)==0:
  402. return JSONResponse(status_code=404, content={
  403. 'errcode': 404,
  404. 'errmsg': '值班人员不能为空'
  405. })
  406. new_duty_data = DutySchedule(
  407. start_time=data['start_time'],
  408. end_time=data['end_time'],
  409. duty_date=data['duty_date'],
  410. shift_type=data['shift_type'],
  411. duty_unit=data['duty_unit'],
  412. duty_type=data['duty_type'],
  413. create_by=user_id
  414. )
  415. # 添加到会话并提交
  416. db.add(new_duty_data)
  417. db.commit()
  418. db.refresh(new_duty_data)
  419. user_list = []
  420. for user_info in user_data:
  421. user_list.append( DutyPersonnelArrangement(
  422. duty_id=new_duty_data.id,
  423. position_id=user_info['position_id'],
  424. personnel_id=user_info['personnel_id'],
  425. create_by=user_id
  426. ))
  427. db.add_all(user_list)
  428. db.commit()
  429. # 构建返回结果
  430. result = {
  431. "code": 200,
  432. "msg": "操作成功",
  433. "data": None
  434. }
  435. return result
  436. except Exception as e:
  437. # 处理异常
  438. traceback.print_exc()
  439. return JSONResponse(status_code=404, content={
  440. 'code': 404,
  441. 'msg': str(e)
  442. })
  443. @router.put("/update")
  444. async def updata_dict_type(
  445. db: Session = Depends(get_db),
  446. body = Depends(remove_xss_json),
  447. user_id = Depends(valid_access_token)
  448. ):
  449. try:
  450. # 从请求数据创建一个新的 SysDictType 实例
  451. query = db.query(DutySchedule)
  452. query = query.filter(DutySchedule.id == body['id'])
  453. query = query.filter(DutySchedule.del_flag != '2')
  454. # query = db.query(SysDictData).filter(SysDictData.dict_code == form_data.dictCode)
  455. # query = db.query(SysDictData).filter(SysDictData.del_flag != '2')
  456. duty_data = query.first()
  457. old_user_list = duty_id_get_user_id(db,duty_data.id)
  458. for info in old_user_list:
  459. info.del_flag = '2'
  460. db.commit()
  461. user_data = body['user_data']
  462. if len(user_data)==0:
  463. return JSONResponse(status_code=404, content={
  464. 'errcode': 404,
  465. 'errmsg': '值班人员不能为空'
  466. })
  467. user_list = []
  468. for user_info in user_data:
  469. user_list.append(DutyPersonnelArrangement(
  470. duty_id=duty_data.id,
  471. position_id=user_info['position_id'],
  472. personnel_id=user_info['personnel_id'],
  473. create_by=user_id
  474. ))
  475. db.add_all(user_list)
  476. if not duty_data:
  477. return JSONResponse(status_code=404, content={
  478. 'errcode': 404,
  479. 'errmsg': '值班不存在'
  480. })
  481. duty_data.start_time=body['start_time']
  482. duty_data.end_time = body['end_time']
  483. duty_data.duty_date = body['duty_date']
  484. duty_data.shift_type=body['shift_type']
  485. duty_data.duty_unit = body['duty_unit']
  486. duty_data.duty_type = body['duty_type']
  487. duty_data.update_by = user_id
  488. # 添加到数据库会话并提交
  489. db.commit()
  490. # db.refresh(new_dict_type) # 可选,如果需要刷新实例状态
  491. # 构建并返回响应
  492. return {
  493. "code": 200,
  494. "msg": "操作成功",
  495. "data": None # 根据你的响应示例,data 为 null
  496. }
  497. except Exception as e:
  498. # 处理异常
  499. traceback.print_exc()
  500. return JSONResponse(status_code=404, content={
  501. 'code': 404,
  502. 'msg': str(e)
  503. })
  504. @router.delete("/delete/{id}") # 使用 ID 来标识要删除的接口
  505. async def delete_dict_data(
  506. id: str,
  507. db: Session = Depends(get_db),
  508. body = Depends(remove_xss_json),
  509. user_id = Depends(valid_access_token)
  510. ):
  511. try:
  512. # 从数据库中获取要删除的 OneShareApiEntity 实例
  513. query = db.query(DutySchedule)
  514. query = query.filter(DutySchedule.id == id)
  515. query = query.filter(DutySchedule.del_flag != '2')
  516. position_data = query.first()
  517. # dict_data = db.query(SysDictData).filter(SysDictData.dict_code == dictCode and SysDictData.del_flag != '2').first()
  518. if not position_data:
  519. return JSONResponse(status_code=404, content={
  520. 'code': 404,
  521. 'msg': '值班不存在'
  522. })
  523. position_data.del_flag = '2'
  524. # 删除实例
  525. # db.delete(api)
  526. db.commit()
  527. # 构建并返回响应
  528. return {
  529. "code": 200,
  530. "msg": "操作成功",
  531. "data": None
  532. }
  533. except Exception as e:
  534. traceback.print_exc()
  535. return JSONResponse(status_code=404, content={
  536. 'code': 404,
  537. 'msg': str(e)
  538. })
  539. @router.delete("/delete_list/{id_list}") # 使用 ID 来标识要删除的接口
  540. async def delete_dict_data(
  541. id_list: str,
  542. db: Session = Depends(get_db),
  543. body = Depends(remove_xss_json),
  544. user_id = Depends(valid_access_token)
  545. ):
  546. try:
  547. # 从数据库中获取要删除的 OneShareApiEntity 实例
  548. id_list = [int(i) for i in id_list.split(',')]
  549. query = db.query(DutySchedule)
  550. query = query.filter(DutySchedule.id.in_(id_list))
  551. query = query.filter(DutySchedule.del_flag != '2')
  552. position_data = query.all()
  553. # dict_data = db.query(SysDictData).filter(SysDictData.dict_code == dictCode and SysDictData.del_flag != '2').first()
  554. if not position_data:
  555. return JSONResponse(status_code=404, content={
  556. 'code': 404,
  557. 'msg': '值班不存在'
  558. })
  559. for info in position_data:
  560. info.del_flag = '2'
  561. # 删除实例
  562. # db.delete(api)
  563. db.commit()
  564. # 构建并返回响应
  565. return {
  566. "code": 200,
  567. "msg": "操作成功",
  568. "data": None
  569. }
  570. except Exception as e:
  571. traceback.print_exc()
  572. return JSONResponse(status_code=404, content={
  573. 'code': 404,
  574. 'msg': str(e)
  575. })
  576. # 自定义排班 导出
  577. @router.post('/zdypb/createImport')
  578. # 值班排班 导入
  579. @router.post('/zbpb/createImport')
  580. async def create_contact(
  581. request: Request,
  582. background_tasks: BackgroundTasks,
  583. db: Session = Depends(get_db),
  584. body=Depends(remove_xss_json),
  585. auth_user: AuthUser = Depends(find_auth_user),
  586. user_id=Depends(valid_access_token)
  587. ):
  588. try:
  589. # 提取请求数据
  590. filename = body['filename']
  591. file_name_desc = body['file_name_desc']
  592. duty_unit = body['duty_unit']
  593. duty_type = ''
  594. if 'duty_type' in body:
  595. duty_type = body['duty_type']
  596. if len(filename) == 0:
  597. raise Exception()
  598. file_path = f'/data/upload/mergefile/uploads/{filename}'
  599. # 检查文件是否存在
  600. if not os.path.isfile(file_path):
  601. return JSONResponse(status_code=404, content={
  602. 'errcode': 404,
  603. 'errmsg': f'{filename}不存在'
  604. })
  605. msg = '成功'
  606. code =200
  607. try:
  608. book = xlrd.open_workbook(file_path)
  609. sheet = book.sheet_by_index(0)
  610. except:
  611. msg = f'\n文件打开失败,请核实文件格式为xlsx/xlx>'
  612. code = 500
  613. return JSONResponse(status_code=code, content={
  614. "code": code,
  615. "msg": msg,
  616. "data": None
  617. })
  618. duty_data = {}
  619. duty_persion_data = {}
  620. import_status = True
  621. for row in range(2, sheet.nrows):
  622. user_data = []
  623. start_date = sheet.cell(row, 0).value
  624. if start_date == '':
  625. msg = f'\n行<{row + 1}>日期不能为空<{start_date}>'
  626. code = 500
  627. start_time = sheet.cell(row, 1).value
  628. if start_time == '':
  629. msg = f'\n行<{row + 1}>日期不能为空<{start_time}>'
  630. code = 500
  631. end_date = sheet.cell(row, 2).value
  632. if end_date == '':
  633. msg = f'\n行<{row + 1}>日期不能为空<{end_date}>'
  634. code = 500
  635. end_time = sheet.cell(row, 3).value
  636. if end_time == '':
  637. msg = f'\n行<{row + 1}>日期不能为空<{end_time}>'
  638. code = 500
  639. dbld = sheet.cell(row, 4).value
  640. if dbld == '':
  641. msg = f'\n行<{row + 1}>日期不能为空<{dbld}>'
  642. code = 500
  643. for name in dbld.split(','):
  644. personnel_id_list = name_get_user_id(db, name)
  645. if len(personnel_id_list)==0:
  646. import_status = False
  647. msg = f'\n行<{row + 1}>非应急通讯录人员<{name}>'
  648. code = 500
  649. for personnel_id in personnel_id_list:
  650. user_data.append({"position_id":1,"personnel_id":personnel_id})
  651. kjdb = sheet.cell(row, 5).value
  652. if kjdb == '':
  653. msg = f'\n行<{row + 1}>日期不能为空<{kjdb}>'
  654. code = 500
  655. for name in kjdb.split(','):
  656. personnel_id_list = name_get_user_id(db, name)
  657. if len(personnel_id_list)==0:
  658. import_status = False
  659. msg = f'\n行<{row + 1}>非应急通讯录人员<{name}>'
  660. code = 500
  661. for personnel_id in personnel_id_list:
  662. user_data.append({"position_id":1,"personnel_id":personnel_id})
  663. zb = sheet.cell(row, 6).value
  664. if zb == '':
  665. msg = f'\n行<{row + 1}>日期不能为空<{zb}>'
  666. code = 500
  667. for name in zb.split(','):
  668. personnel_id_list = name_get_user_id(db, name)
  669. if len(personnel_id_list)==0:
  670. import_status = False
  671. msg = f'\n行<{row + 1}>非应急通讯录人员<{name}>'
  672. code = 500
  673. for personnel_id in personnel_id_list:
  674. user_data.append({"position_id":1,"personnel_id":personnel_id})
  675. zz = sheet.cell(row, 7).value
  676. if zz == '':
  677. msg = f'\n行<{row + 1}>日期不能为空<{zz}>'
  678. code = 500
  679. for name in zz.split(','):
  680. personnel_id_list = name_get_user_id(db, name)
  681. if len(personnel_id_list)==0:
  682. import_status = False
  683. msg = f'\n行<{row + 1}>非应急通讯录人员<{name}>'
  684. code = 500
  685. for personnel_id in personnel_id_list:
  686. user_data.append({"position_id":1,"personnel_id":personnel_id})
  687. if start_date == end_date:
  688. shift_type = '1'
  689. else:
  690. if start_time==end_time:
  691. shift_type = '2'
  692. else:
  693. shift_type = '3'
  694. new_duty_data = DutySchedule(
  695. start_time=f'{start_date} {start_time}',
  696. end_time=f'{end_date} {end_time}',
  697. duty_date=start_date,
  698. shift_type=shift_type,
  699. duty_unit=duty_unit,
  700. duty_type=duty_type,
  701. create_by=user_id
  702. )
  703. duty_data[start_date+str(shift_type)] = new_duty_data
  704. # 添加到会话并提交
  705. duty_persion_data[start_date + str(shift_type)] = user_data
  706. # db.add(new_duty_data)
  707. # db.commit()
  708. # db.refresh(new_duty_data)
  709. # user_list = []
  710. # for user_info in user_data:
  711. # user_list.append(DutyPersonnelArrangement(
  712. # duty_id=new_duty_data.id,
  713. # position_id=user_info['position_id'],
  714. # personnel_id=user_info['personnel_id'],
  715. # create_by=user_id
  716. # ))
  717. # db.add_all(user_list)
  718. # db.commit()
  719. if import_status:
  720. for duty in duty_data:
  721. new_duty_data = duty_data[duty]
  722. db.add(new_duty_data)
  723. db.commit()
  724. db.refresh(new_duty_data)
  725. user_list = []
  726. for user_info in duty_persion_data[duty]:
  727. user_list.append(DutyPersonnelArrangement(
  728. duty_id=new_duty_data.id,
  729. position_id=user_info['position_id'],
  730. personnel_id=user_info['personnel_id'],
  731. create_by=user_id
  732. ))
  733. db.add_all(user_list)
  734. db.commit()
  735. except Exception as e:
  736. traceback.print_exc()
  737. # 处理异常
  738. db.rollback()
  739. code = 500
  740. msg = str(e)
  741. return JSONResponse(status_code=code, content={
  742. "code": code,
  743. "msg": msg,
  744. "data": None
  745. })
  746. # 值班排班 导出
  747. @router.get("/zbpb/export")
  748. async def download_file(keywords:str =Query(None),
  749. duty_type:str =Query(None),
  750. start_time:str =Query(None),
  751. end_time:str =Query(None),
  752. duty_unit:int =Query(None),
  753. db: Session = Depends(get_db),
  754. body = Depends(remove_xss_json),
  755. user_id = Depends(valid_access_token)):
  756. """
  757. 根据提供的文件名下载文件。
  758. :param filename: 要下载的文件的名称。
  759. """
  760. try:
  761. query = db.query(DutySchedule)
  762. query = query.filter(DutySchedule.del_flag != '2')
  763. # 添加查询条件
  764. if keywords:
  765. user_list = name_get_user_id(db, keywords)
  766. duty_list = user_id_get_duty_id(db, user_list)
  767. query = query.filter(DutySchedule.id.in_(duty_list))
  768. if duty_type:
  769. query = query.filter(DutySchedule.duty_type == duty_type)
  770. if start_time:
  771. start_time = datetime.strptime(start_time, "%Y-%m-%d").date()
  772. query = query.filter(DutySchedule.duty_date >= start_time)
  773. if end_time:
  774. end_time = datetime.strptime(end_time, "%Y-%m-%d").date()
  775. query = query.filter(DutySchedule.duty_date <= end_time)
  776. if duty_unit:
  777. query = query.filter(DutySchedule.duty_unit == duty_unit)
  778. subquery = db.query(
  779. DutySchedule.duty_date,
  780. DutySchedule.shift_type,
  781. func.max(DutySchedule.update_time).label("latest_create_time")
  782. ).filter(DutySchedule.del_flag != '2').group_by(
  783. DutySchedule.duty_date,
  784. DutySchedule.shift_type
  785. ).subquery()
  786. query = query.join(
  787. subquery,
  788. and_(
  789. DutySchedule.duty_date == subquery.c.duty_date,
  790. DutySchedule.shift_type == subquery.c.shift_type,
  791. DutySchedule.update_time == subquery.c.latest_create_time
  792. )
  793. )
  794. query = query.order_by(DutySchedule.duty_date)
  795. duty_data = query.all()
  796. # 转换为字典
  797. data_list = []
  798. for d in duty_data:
  799. data = {
  800. "值班开始日期": d.start_time.strftime('%Y-%m-%d') if d.start_time else '',
  801. "值班开始时间": d.start_time.strftime('%H:%M') if d.start_time else '',
  802. "值班结束日期": d.end_time.strftime('%Y-%m-%d') if d.end_time else '',
  803. "值班结束时间": d.end_time.strftime('%H:%M') if d.end_time else '',
  804. "带班领导": ""
  805. }
  806. user_data = {}
  807. user_list = duty_id_get_user_id(db, d.id)
  808. for user_info in user_list:
  809. contact_info = user_id_get_info(db, user_info.personnel_id)
  810. position= position_id_get_info(db,user_info.position_id)
  811. if position.position_name in user_data:
  812. user_data[position.position_name].append(contact_info.name)
  813. else:
  814. user_data[position.position_name]=[contact_info.name]
  815. for position_name in user_data:
  816. data[position_name] = ",".join(user_data[position_name])
  817. data_list.append(data)
  818. # 构造文件的完整路径
  819. import pandas as pd
  820. from io import BytesIO
  821. # 将查询结果转换为 DataFrame
  822. df = pd.DataFrame(data_list)
  823. # 将 DataFrame 导出为 Excel 文件
  824. output = BytesIO()
  825. with pd.ExcelWriter(output, engine='openpyxl') as writer:
  826. df.to_excel(writer, index=False)
  827. # 设置响应头
  828. output.seek(0)
  829. from urllib.parse import quote
  830. encoded_filename = f'值班排班{datetime.now().strftime("%Y%m%d%H%mi%s")}.xlsx'
  831. encoded_filename = quote(encoded_filename, encoding='utf-8')
  832. headers = {
  833. 'Content-Disposition': f'attachment; filename*=UTF-8\'\'{encoded_filename}',
  834. 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  835. }
  836. # 返回文件流
  837. return StreamingResponse(output, headers=headers)
  838. except HTTPException as e:
  839. raise e
  840. except Exception as e:
  841. # 处理其他异常情况
  842. raise HTTPException(status_code=500, detail=str(e))
  843. # 本单位值班 导出
  844. @router.get("/bdwzb/export")
  845. # 各级单位值班表 导出
  846. @router.get("/gjdwzbb/export")
  847. async def download_file(keywords:str =Query(None),
  848. start_time:str =Query(None),
  849. end_time:str =Query(None),
  850. duty_unit:int =Query(None),
  851. db: Session = Depends(get_db),
  852. body = Depends(remove_xss_json),
  853. user_id = Depends(valid_access_token)):
  854. """
  855. 根据提供的文件名下载文件。
  856. :param filename: 要下载的文件的名称。
  857. """
  858. try:
  859. query = db.query(DutySchedule)
  860. query = query.filter(DutySchedule.del_flag != '2')
  861. # 添加查询条件
  862. if keywords:
  863. user_list = name_get_user_id(db, keywords)
  864. duty_list = user_id_get_duty_id(db, user_list)
  865. query = query.filter(DutySchedule.id.in_(duty_list))
  866. if start_time:
  867. start_time = datetime.strptime(start_time, "%Y-%m-%d").date()
  868. query = query.filter(DutySchedule.duty_date >= start_time)
  869. if end_time:
  870. end_time = datetime.strptime(end_time, "%Y-%m-%d").date()
  871. query = query.filter(DutySchedule.duty_date <= end_time)
  872. if duty_unit:
  873. query = query.filter(DutySchedule.duty_unit == duty_unit)
  874. else:
  875. now_user_info = user_id_get_user_info(db, user_id)
  876. print(user_id, now_user_info.phonenumber, get_duty_unit_id_list(db))
  877. if now_user_info:
  878. query = query.filter(
  879. DutySchedule.duty_unit == mobile_phone_get_dept_id(db, mpfun.dec_data(now_user_info.phonenumber),
  880. get_duty_unit_id_list(db)))
  881. else:
  882. return {
  883. "data": [],
  884. "code": 200,
  885. "msg": "查询成功"
  886. }
  887. subquery = db.query(
  888. DutySchedule.duty_date,
  889. DutySchedule.shift_type,
  890. func.max(DutySchedule.update_time).label("latest_create_time")
  891. ).filter(DutySchedule.del_flag != '2').group_by(
  892. DutySchedule.duty_date,
  893. DutySchedule.shift_type
  894. ).subquery()
  895. query = query.join(
  896. subquery,
  897. and_(
  898. DutySchedule.duty_date == subquery.c.duty_date,
  899. DutySchedule.shift_type == subquery.c.shift_type,
  900. DutySchedule.update_time == subquery.c.latest_create_time
  901. )
  902. )
  903. query = query.order_by(DutySchedule.update_time.desc())
  904. duty_data = query.all()
  905. # 转换为字典
  906. data_list = []
  907. for d in duty_data:
  908. user_data = []
  909. leaders = []
  910. user_list = duty_id_get_user_id(db, d.id)
  911. for user_info in user_list:
  912. contact_info = user_id_get_info(db, user_info.personnel_id)
  913. position= position_id_get_info(db,user_info.position_id)
  914. if position.position_name=='带班领导':
  915. leaders.append(contact_info.name)
  916. user_data.append(contact_info.name)
  917. data_list.append({
  918. "单位名称": dept_id_get_info(db,d.duty_unit).department_name,
  919. "开始时间": d.start_time.strftime('%Y-%m-%d %H:%M:%S') if d.start_time else '',
  920. "结束时间": d.end_time.strftime('%Y-%m-%d %H:%M:%S') if d.end_time else '',
  921. "带班领导": "、".join(leaders),
  922. "值班人员": "、".join(user_data)
  923. })
  924. # 构造文件的完整路径
  925. import pandas as pd
  926. from io import BytesIO
  927. # 将查询结果转换为 DataFrame
  928. df = pd.DataFrame(data_list)
  929. # 将 DataFrame 导出为 Excel 文件
  930. output = BytesIO()
  931. with pd.ExcelWriter(output, engine='openpyxl') as writer:
  932. df.to_excel(writer, index=False)
  933. # 设置响应头
  934. output.seek(0)
  935. from urllib.parse import quote
  936. encoded_filename = f'值班表{datetime.now().strftime("%Y%m%d%H%mi%s")}.xlsx'
  937. encoded_filename = quote(encoded_filename, encoding='utf-8')
  938. headers = {
  939. 'Content-Disposition': f'attachment; filename*=UTF-8\'\'{encoded_filename}',
  940. 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  941. }
  942. # 返回文件流
  943. return StreamingResponse(output, headers=headers)
  944. except HTTPException as e:
  945. raise e
  946. except Exception as e:
  947. # 处理其他异常情况
  948. raise HTTPException(status_code=500, detail=str(e))
  949. # 各级单位值班人 导出
  950. @router.get("/gjdwzbr/export")
  951. async def download_file(keywords:str =Query(None),
  952. start_time:str =Query(None),
  953. end_time:str =Query(None),
  954. duty_unit:int =Query(None),
  955. db: Session = Depends(get_db),
  956. body = Depends(remove_xss_json),
  957. user_id = Depends(valid_access_token)):
  958. """
  959. 根据提供的文件名下载文件。
  960. :param filename: 要下载的文件的名称。
  961. """
  962. try:
  963. query = db.query(DutySchedule)
  964. query = query.filter(DutySchedule.del_flag != '2')
  965. # 添加查询条件
  966. if keywords:
  967. user_list = name_get_user_id(db, keywords)
  968. duty_list = user_id_get_duty_id(db, user_list)
  969. query = query.filter(DutySchedule.id.in_(duty_list))
  970. if start_time:
  971. start_time = datetime.strptime(start_time, "%Y-%m-%d").date()
  972. query = query.filter(DutySchedule.duty_date >= start_time)
  973. if end_time:
  974. end_time = datetime.strptime(end_time, "%Y-%m-%d").date()
  975. query = query.filter(DutySchedule.duty_date <= end_time)
  976. if duty_unit:
  977. query = query.filter(DutySchedule.duty_unit == duty_unit)
  978. else:
  979. now_user_info = user_id_get_user_info(db, user_id)
  980. print(user_id, now_user_info.phonenumber, get_duty_unit_id_list(db))
  981. if now_user_info:
  982. query = query.filter(
  983. DutySchedule.duty_unit == mobile_phone_get_dept_id(db, mpfun.dec_data(now_user_info.phonenumber),
  984. get_duty_unit_id_list(db)))
  985. else:
  986. return {
  987. "data": [],
  988. "code": 200,
  989. "msg": "查询成功"
  990. }
  991. subquery = db.query(
  992. DutySchedule.duty_date,
  993. DutySchedule.shift_type,
  994. func.max(DutySchedule.update_time).label("latest_create_time")
  995. ).filter(DutySchedule.del_flag != '2').group_by(
  996. DutySchedule.duty_date,
  997. DutySchedule.shift_type
  998. ).subquery()
  999. query = query.join(
  1000. subquery,
  1001. and_(
  1002. DutySchedule.duty_date == subquery.c.duty_date,
  1003. DutySchedule.shift_type == subquery.c.shift_type,
  1004. DutySchedule.update_time == subquery.c.latest_create_time
  1005. )
  1006. )
  1007. query = query.order_by(DutySchedule.update_time.desc())
  1008. duty_data = query.all()
  1009. # 转换为字典
  1010. data_list = []
  1011. yz_list = []
  1012. for d in duty_data:
  1013. user_list = duty_id_get_user_id(db, d.id)
  1014. for user_info in user_list:
  1015. contact_info = user_id_get_info(db, user_info.personnel_id)
  1016. position = position_id_get_info(db, user_info.position_id)
  1017. department = dept_id_get_info(db,contact_info.department_id)
  1018. yz = d.duty_date.strftime('%Y-%m-%d')+str(contact_info.id)
  1019. if yz not in yz_list:
  1020. yz_list.append(yz)
  1021. data_list.append({"值班日期":d.duty_date,
  1022. "值班机构": dept_id_get_info(db,d.duty_unit).department_name,
  1023. "组织机构": department.department_name,
  1024. "值班岗位": position.position_name,
  1025. "值班人员": contact_info.name,
  1026. "职务": contact_info.position,
  1027. "联系电话": contact_info.mobile_phone,
  1028. "办公电话": contact_info.office_phone})
  1029. # 构造文件的完整路径
  1030. import pandas as pd
  1031. from io import BytesIO
  1032. # 将查询结果转换为 DataFrame
  1033. df = pd.DataFrame(data_list)
  1034. # 将 DataFrame 导出为 Excel 文件
  1035. output = BytesIO()
  1036. with pd.ExcelWriter(output, engine='openpyxl') as writer:
  1037. df.to_excel(writer, index=False)
  1038. # 设置响应头
  1039. output.seek(0)
  1040. from urllib.parse import quote
  1041. encoded_filename = f'值班人员{datetime.now().strftime("%Y%m%d%H%mi%s")}.xlsx'
  1042. encoded_filename = quote(encoded_filename, encoding='utf-8')
  1043. headers = {
  1044. 'Content-Disposition': f'attachment; filename*=UTF-8\'\'{encoded_filename}',
  1045. 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  1046. }
  1047. # 返回文件流
  1048. return StreamingResponse(output, headers=headers)
  1049. except HTTPException as e:
  1050. raise e
  1051. except Exception as e:
  1052. # 处理其他异常情况
  1053. raise HTTPException(status_code=500, detail=str(e))