duty.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. from fastapi import APIRouter, Request, Depends, HTTPException, Query, BackgroundTasks
  2. from sqlalchemy.exc import IntegrityError
  3. from fastapi.responses import HTMLResponse, FileResponse
  4. from fastapi.responses import JSONResponse
  5. from database import get_db
  6. from sqlalchemy import text, exists, and_, or_, not_
  7. from sqlalchemy.orm import Session
  8. from models import *
  9. import json
  10. import random
  11. from sqlalchemy import create_engine, select
  12. from typing import Optional
  13. from utils.StripTagsHTMLParser import *
  14. from common.db import db_event_management, db_user, db_area, db_emergency_plan
  15. from common.security import valid_access_token
  16. import traceback
  17. from utils import *
  18. from datetime import datetime, timedelta
  19. from common import YzyApi
  20. from common.db import db_dict
  21. from urllib.parse import quote
  22. import base64
  23. from config import settings
  24. from extensions import logger
  25. import os
  26. from exceptions import *
  27. import openpyxl
  28. router = APIRouter()
  29. '''
  30. @router.get("/duty_by_day")
  31. async def duty_by_day(
  32. day: str,
  33. db: Session = Depends(get_db),
  34. user_id = Depends(valid_access_token)
  35. ):
  36. try:
  37. data = {}
  38. shift_status = 0
  39. handover_time = None
  40. current_time = datetime.now().time()
  41. date = datetime.strptime(day, "%Y-%m-%d")
  42. # 人员
  43. user_row = db_user.get_user_info(db, user_id)
  44. dept_id = user_row.dept_id
  45. # 默认值
  46. data['users'] = {
  47. "user1": "-",
  48. "user2": "-",
  49. "user3": "-",
  50. "user4": "-"
  51. }
  52. # 当前用户的同一个部门的值班
  53. where = and_(DutySchedule.duty_date == date,DutySchedule.del_flag!='2')
  54. # where = and_(where, DutyShift.dept_id == dept_id)
  55. subquery = db.query(
  56. DutySchedule.duty_date,
  57. DutySchedule.shift_type,
  58. func.max(DutySchedule.update_time).label("latest_create_time")
  59. ).filter(DutySchedule.del_flag != '2').group_by(
  60. DutySchedule.duty_date,
  61. DutySchedule.shift_type
  62. ).subquery()
  63. row = db.query(DutySchedule).filter(where)
  64. row = row.join(
  65. subquery,
  66. and_(
  67. DutySchedule.duty_date == subquery.c.duty_date,
  68. DutySchedule.shift_type == subquery.c.shift_type,
  69. DutySchedule.update_time == subquery.c.latest_create_time
  70. )
  71. ).all()
  72. shift_id = [info.id for info in row]
  73. if len(shift_id)>0:
  74. from .schedule import duty_id_get_user_id,user_id_get_info
  75. user_info = {"user1": [],
  76. "user2": "-",
  77. "user3": [],
  78. "user4": "-"}
  79. for d in shift_id:
  80. user_data = []
  81. user_list = duty_id_get_user_id(db, d)
  82. for user_info1 in user_list:
  83. contact_info = user_id_get_info(db, user_info1.personnel_id)
  84. if user_info1.position_id ==1:
  85. user_info['user1'].append(contact_info.name)
  86. if user_info1.position_id ==8:
  87. user_info['user3'].append(contact_info.name)
  88. # user_info = get_model_dict(row)
  89. user_info['user1'] = '、'.join(user_info['user1'])
  90. user_info['user3'] = '、'.join(user_info['user3'])
  91. data['users'] = user_info
  92. # 提醒事项
  93. where = and_(DutyNotify.del_flag == '0', DutyNotify.notify_type == '1', DutyNotify.shift_id.in_(shift_id))
  94. rows = db.query(DutyNotify).filter(where).all()
  95. items = []
  96. for row in rows:
  97. items.append({
  98. "text": row.notify_content,
  99. "time": get_datetime_str(row.create_time)
  100. })
  101. data['remainds'] = items
  102. # 待办事项
  103. where = and_(DutyNotify.del_flag == '0', DutyNotify.notify_type == '2', DutyNotify.shift_id.in_(shift_id))
  104. rows = db.query(DutyNotify).filter(where).all()
  105. items = []
  106. for row in rows:
  107. items.append({
  108. "text": row.notify_content,
  109. "time": get_datetime_str(row.create_time)
  110. })
  111. data['todos'] = items
  112. data['shift_id'] = shift_id
  113. data['shift_status'] = shift_status
  114. data['handover_time'] = ''
  115. # 目前不知道有什么用
  116. data['days'] = []
  117. return {
  118. "code": 200,
  119. "msg": "查询成功",
  120. "data": data
  121. }
  122. except AppException as e:
  123. return {
  124. "code": e.code,
  125. "msg": e.msg
  126. }
  127. except Exception as e:
  128. traceback.print_exc()
  129. # 处理异常
  130. raise HTTPException(status_code=500, detail=str(e))
  131. '''
  132. @router.get("/my_calendar_by_month")
  133. async def calendar_by_month(
  134. date: str = Query(None, description="月份"),
  135. db: Session = Depends(get_db),
  136. user_id=Depends(valid_access_token)
  137. ):
  138. the_year = datetime.now().year
  139. the_month = datetime.now().month
  140. if date is not None and date != '':
  141. arr = date.split("-")
  142. the_year = arr[0]
  143. the_month = arr[1]
  144. try:
  145. from utils.ry_system_util import user_id_get_user_info
  146. from .schedule import mobile_phone_get_dept_id,get_duty_unit_id_list
  147. from common.enc import mpfun
  148. now_user_info = user_id_get_user_info(db, user_id)
  149. if now_user_info:
  150. user_where = (DutySchedule.duty_unit == mobile_phone_get_dept_id(db, mpfun.dec_data(now_user_info.phonenumber),
  151. get_duty_unit_id_list(db)))
  152. else:
  153. return {
  154. "code": 200,
  155. "msg": "查询成功",
  156. "data": []
  157. }
  158. # user_where = or_(DutyShift.leader_id == user_id, DutyShift.primary_staff_id == user_id,
  159. # DutyShift.secondary_staff_id == user_id, DutyShift.standby_staff_id == user_id)
  160. where = and_(func.extract('year', DutySchedule.duty_date) == the_year,
  161. func.extract('month', DutySchedule.duty_date) == the_month)
  162. where = and_(where, user_where,DutySchedule.del_flag != '2')
  163. rows = db.query(DutySchedule.duty_date).distinct().filter(where).all()
  164. data = []
  165. for row in rows:
  166. data.append({
  167. "date": row.duty_date,
  168. "color": "a2d7f1"
  169. })
  170. return {
  171. "code": 200,
  172. "msg": "查询成功",
  173. "data": data
  174. }
  175. except AppException as e:
  176. return {
  177. "code": e.code,
  178. "msg": e.msg
  179. }
  180. except Exception as e:
  181. traceback.print_exc()
  182. # 处理异常
  183. raise HTTPException(status_code=500, detail=str(e))
  184. # @router.get("/duty_by_day")
  185. # async def duty_by_day(
  186. # day: str,
  187. # db: Session = Depends(get_db),
  188. # user_id=Depends(valid_access_token)
  189. # ):
  190. # try:
  191. # data = {}
  192. # shift_id = 0
  193. # shift_status = 0
  194. # handover_time = None
  195. #
  196. # current_time = datetime.now().time()
  197. # date = datetime.strptime(day, "%Y-%m-%d")
  198. #
  199. # # 人员
  200. # user_row = db_user.get_user_info(db, user_id)
  201. # dept_id = user_row.dept_id
  202. #
  203. # # 默认值
  204. # data['users'] = {
  205. # "user1": "-",
  206. # "user2": "-",
  207. # "user3": "-",
  208. # "user4": "-"
  209. # }
  210. #
  211. # # 当前用户的同一个部门的值班
  212. # where = and_(DutyShift.shift_date == date, DutyShift.start_time < current_time)
  213. # # where = and_(where, DutyShift.dept_id == dept_id)
  214. # row = db.query(DutyShift).filter(where).first()
  215. # if row is not None:
  216. # shift_id = row.shift_id
  217. # shift_status = row.shift_status
  218. # handover_time = row.handover_time
  219. #
  220. # user_info = get_model_dict(row)
  221. # user_info['user1'] = db_user.get_nick_name_by_id(db, user_info['leader_id'])
  222. # user_info['user2'] = db_user.get_nick_name_by_id(db, user_info['primary_staff_id'])
  223. # user_info['user3'] = db_user.get_nick_name_by_id(db, user_info['secondary_staff_id'])
  224. # user_info['user4'] = db_user.get_nick_name_by_id(db, user_info['standby_staff_id'])
  225. #
  226. # data['users'] = user_info
  227. #
  228. # # 提醒事项
  229. # where = and_(DutyNotify.del_flag == '0', DutyNotify.notify_type == '1', DutyNotify.shift_id == shift_id)
  230. # rows = db.query(DutyNotify).filter(where).all()
  231. # items = []
  232. # for row in rows:
  233. # items.append({
  234. # "text": row.notify_content,
  235. # "time": get_datetime_str(row.create_time)
  236. # })
  237. # data['remainds'] = items
  238. #
  239. # # 待办事项
  240. # where = and_(DutyNotify.del_flag == '0', DutyNotify.notify_type == '2', DutyNotify.shift_id == shift_id)
  241. # rows = db.query(DutyNotify).filter(where).all()
  242. # items = []
  243. # for row in rows:
  244. # items.append({
  245. # "text": row.notify_content,
  246. # "time": get_datetime_str(row.create_time)
  247. # })
  248. # data['todos'] = items
  249. #
  250. # data['shift_id'] = shift_id
  251. # data['shift_status'] = shift_status
  252. # data['handover_time'] = get_datetime_str(handover_time)
  253. #
  254. # # 目前不知道有什么用
  255. # data['days'] = []
  256. #
  257. # return {
  258. # "code": 200,
  259. # "msg": "查询成功",
  260. # "data": data
  261. # }
  262. #
  263. # except AppException as e:
  264. # return {
  265. # "code": e.code,
  266. # "msg": e.msg
  267. # }
  268. #
  269. # except Exception as e:
  270. # traceback.print_exc()
  271. # # 处理异常
  272. # raise HTTPException(status_code=500, detail=str(e))
  273. # 暂时没用
  274. # @router.get("/my_calendar_by_month")
  275. # async def calendar_by_month(
  276. # date: str = Query(None, description="月份"),
  277. # db: Session = Depends(get_db),
  278. # user_id = Depends(valid_access_token)
  279. # ):
  280. # the_year = datetime.now().year
  281. # the_month = datetime.now().month
  282. # if date is not None and date != '':
  283. # arr = date.split("-")
  284. # the_year = arr[0]
  285. # the_month = arr[1]
  286. #
  287. # try:
  288. # user_where = or_(DutyShift.leader_id == user_id, DutyShift.primary_staff_id == user_id, DutyShift.secondary_staff_id == user_id, DutyShift.standby_staff_id == user_id)
  289. # where = and_(func.extract('year', DutyShift.shift_date) == the_year, func.extract('month', DutyShift.shift_date) == the_month)
  290. # where = and_(where, user_where)
  291. # rows = db.query(DutyShift.shift_date).distinct().filter(where).all()
  292. # data = []
  293. # for row in rows:
  294. # data.append({
  295. # "date": row.shift_date,
  296. # "color": "a2d7f1"
  297. # })
  298. # return {
  299. # "code": 200,
  300. # "msg": "查询成功",
  301. # "data": data
  302. # }
  303. #
  304. # except AppException as e:
  305. # return {
  306. # "code": e.code,
  307. # "msg": e.msg
  308. # }
  309. #
  310. # except Exception as e:
  311. # traceback.print_exc()
  312. # # 处理异常
  313. # raise HTTPException(status_code=500, detail=str(e))
  314. #
  315. # 新增提醒或者待办
  316. @router.post("/add_notify")
  317. async def create_by_city_to_area(
  318. db: Session = Depends(get_db),
  319. body = Depends(remove_xss_json),
  320. user_id = Depends(valid_access_token)
  321. ):
  322. try:
  323. shift_id = body['shift_id']
  324. notify_type = body['notify_type']
  325. notify_content = body['notify_content']
  326. new_notify = DutyNotify(
  327. shift_id = shift_id,
  328. notify_type = notify_type,
  329. notify_content = notify_content,
  330. create_time = datetime.now(),
  331. del_flag = '0',
  332. recorded_by = user_id
  333. )
  334. db.add(new_notify)
  335. db.commit()
  336. db.refresh(new_notify)
  337. new_notify_id = new_notify.id
  338. return {
  339. "code": 200,
  340. "msg": "事项创建成功",
  341. "data": new_notify_id
  342. }
  343. except AppException as e:
  344. return {
  345. "code": e.code,
  346. "msg": e.msg
  347. }
  348. except Exception as e:
  349. traceback.print_exc()
  350. # 处理异常
  351. raise HTTPException(status_code=500, detail=str(e))
  352. # 交班
  353. @router.post("/handover")
  354. async def handover(
  355. db: Session = Depends(get_db),
  356. body = Depends(remove_xss_json),
  357. user_id = Depends(valid_access_token)
  358. ):
  359. try:
  360. shift_id = body['shift_id']
  361. where = and_(DutyShift.shift_id == shift_id)
  362. row = db.query(DutyShift).filter(where).first()
  363. if row is None:
  364. raise AppException(1, "班次不存在")
  365. if row.shift_status == 1:
  366. raise AppException(1, "班次已交班,不用重复操作")
  367. row.shift_status = 1
  368. row.handover_time = datetime.now()
  369. row.handover_user_id = user_id
  370. db.commit()
  371. return {
  372. "code": 200,
  373. "msg": "交班成功",
  374. "data": shift_id
  375. }
  376. except AppException as e:
  377. return {
  378. "code": e.code,
  379. "msg": e.msg
  380. }
  381. except Exception as e:
  382. traceback.print_exc()
  383. # 处理异常
  384. raise HTTPException(status_code=500, detail=str(e))
  385. # 值班表查询
  386. @router.get("/duty_book_by_area")
  387. async def duty_book_by_year_and(
  388. year: str,
  389. area: str,
  390. db: Session = Depends(get_db)
  391. ):
  392. try:
  393. data = []
  394. where = and_(DutyBook.del_flag == '0', DutyBook.year == year, DutyBook.area_code == area)
  395. rows = db.query(DutyBook).filter(where).order_by(DutyBook.month.asc()).all()
  396. for row in rows:
  397. file_url = ""
  398. file_row = db.query(DutyFile).filter(and_(DutyFile.del_flag == '0', DutyFile.from_scenario == 'duty_book', DutyFile.foreign_key == row.id)).first()
  399. if file_row is not None:
  400. file_url = file_row.storage_file_name
  401. data.append({
  402. "id": row.id,
  403. "name": get_month_text(row.month)+"月份",
  404. "name2": get_month_text(row.month)+"月份排班表.xlsx",
  405. "time": row.create_time.strftime("%m-%d %H:%M"),
  406. "url": file_url
  407. })
  408. return {
  409. "code": 200,
  410. "msg": "交班成功",
  411. "data": data
  412. }
  413. except AppException as e:
  414. return {
  415. "code": e.code,
  416. "msg": e.msg
  417. }
  418. except Exception as e:
  419. traceback.print_exc()
  420. # 处理异常
  421. raise HTTPException(status_code=500, detail=str(e))
  422. # 上传排班表
  423. @router.post("/upload_duty_book")
  424. async def upload_duty_book(
  425. db: Session = Depends(get_db),
  426. body = Depends(remove_xss_json),
  427. user_id = Depends(valid_access_token)
  428. ):
  429. try:
  430. dept_id = 0
  431. user_row = db.query(SysUser).filter(SysUser.user_id == user_id).first()
  432. dept_id = user_row.dept_id
  433. area = body['area']
  434. year = body['year']
  435. month = body['month']
  436. # 先导入附件
  437. # 附件
  438. if 'files' not in body:
  439. raise AppException(500, "请上传值班表")
  440. # 从1号开始
  441. date = datetime.strptime(year + "-" + month + "-01", "%Y-%m-%d")
  442. users = []
  443. fileName = body['files'][0]
  444. users = import_duty_book_from_file(int(year), int(month), date, fileName)
  445. if len(users) == 0:
  446. raise AppException(500, "无法获取值班人员")
  447. # 标记之前的导入已删除
  448. old_book_id = 0
  449. where = and_(DutyBook.del_flag == '0', DutyBook.year == year, DutyBook.area_code == area)
  450. row = db.query(DutyBook).filter(where).order_by(DutyBook.month.asc()).first()
  451. if row is not None:
  452. old_book_id = row.id
  453. row.del_flag = '2'
  454. db.commit()
  455. # 新建导入
  456. new_book = DutyBook(
  457. year = year, month = month, area_code = area,
  458. recorded_by = user_id, create_time = datetime.now(), del_flag = '0'
  459. )
  460. db.add(new_book)
  461. db.commit()
  462. db.refresh(new_book)
  463. new_book_id = new_book.id
  464. for (date, item) in users.items():
  465. onduty_leader = item['onduty_leader']
  466. onduty_user = item['onduty_user']
  467. new_shift = DutyShift(
  468. shift_date = date,
  469. # 目前只是值班一整天
  470. start_time = "00:00",
  471. end_time = "23:59",
  472. leader_id = 0,
  473. primary_staff_id = 0,
  474. onduty_leader = onduty_leader,
  475. onduty_user = onduty_user,
  476. # Excel没用到这两个字段
  477. secondary_staff_id = -1,
  478. standby_staff_id = -1,
  479. duty_type = "综合值班",
  480. shift_status = 0,
  481. handover_user_id = 0,
  482. handover_time = None,
  483. dept_id = -1, # 这个字段没用
  484. area_code = area,
  485. del_flag = '0',
  486. book_id = new_book_id
  487. )
  488. db.add(new_shift)
  489. db.commit()
  490. # 标记之前的值班信息已删除
  491. where = and_(DutyShift.del_flag == '0', DutyShift.book_id == old_book_id)
  492. db.query(DutyShift).filter(where).update({"del_flag": '2'})
  493. db.commit()
  494. new_file = DutyFile(
  495. file_name=fileName["name"],
  496. storage_file_name=fileName["url"],
  497. file_path=f'/data/upload/mergefile/uploads/{fileName["url"]}',
  498. file_size=os.path.getsize(f'/data/upload/mergefile/uploads/{fileName["url"]}'),
  499. foreign_key=str(new_book_id),
  500. from_scenario="duty_book",
  501. update_time=datetime.now(),
  502. create_time=datetime.now(),
  503. create_by=user_id,
  504. create_dept=dept_id,
  505. del_flag='0',
  506. status=0,
  507. )
  508. db.add(new_file)
  509. db.commit()
  510. db.refresh(new_file)
  511. return {
  512. "code": 200,
  513. "msg": "上传成功",
  514. "data": new_file.id
  515. }
  516. except AppException as e:
  517. return {
  518. "code": e.code,
  519. "msg": e.msg
  520. }
  521. except Exception as e:
  522. traceback.print_exc()
  523. # 处理异常
  524. raise HTTPException(status_code=500, detail=str(e))
  525. def import_duty_book_from_file(year: int, month: int, date: datetime, fileName: dict) -> dict:
  526. file_path = f'/data/upload/mergefile/uploads/{fileName["url"]}'
  527. wb = openpyxl.load_workbook(file_path)
  528. ws = wb.active
  529. rows = []
  530. for row in ws.iter_rows(values_only=True):
  531. rows.append(list(row))
  532. print(list(row))
  533. users = {}
  534. while date.month == month:
  535. day = datetime.strftime(date, "%m月%d日")
  536. for x in range(len(rows)):
  537. row = rows[x]
  538. for y in range(len(row)):
  539. cell = row[y]
  540. if cell == day:
  541. try:
  542. # 带班领导
  543. onduty_leader = rows[x+1][y]
  544. # 值班人员
  545. onduty_user = rows[x+2][y]
  546. if onduty_leader is None:
  547. raise AppException(500, "无法获取"+day+"的带班领导")
  548. if onduty_user is None:
  549. raise AppException(500, "无法获取"+day+"的值班人员")
  550. # date1 = date.strftime("%Y-%m-%d")
  551. users[date] = {"day": day, "onduty_leader": onduty_leader, "onduty_user": onduty_user}
  552. except Exception as e:
  553. raise AppException(500, "无法获取"+day+"的值班人员")
  554. break
  555. date = date + timedelta(days=1)
  556. return users