""" 待办工单推送。 对应文档接口:2、推送待办工单列表 """ import asyncio import json from typing import Optional, Union import pandas as pd from sqlalchemy import select, desc from tornado.httpclient import HTTPResponse, HTTPRequest import dock import models from dock.oa import oa_api_request from models.dcm_push_status import DcmPushStatus from models.dcm_task import DcmTask from paste.core.logging import echo_log from paste.util import udict from paste.web import requests DcmTaskMapping = { DcmTask.id.key: 'gdId', DcmTask.task_num.key: 'taskNum', DcmTask.other_task_num.key: 'otherTaskNum', DcmTask.bundle_deadline_time.key: 'bundleDeadlineTimeStr', DcmTask.rollback_deadline.key: 'rollbackDeadlineStr', DcmTask.event_src_name.key: 'eventSrcName', DcmTask.rec_type_name.key: 'recTypeName', DcmTask.event_type_name.key: 'eventTypeName', DcmTask.main_type_name.key: 'mainTypeName', DcmTask.sub_type_name.key: 'subTypeName', DcmTask.urgency_level.key: 'urgencyLevel', DcmTask.event_desc.key: 'eventDesc', DcmTask.address.key: 'address', DcmTask.processing_deadline.key: 'disposalTimeLimit', DcmTask.district_name.key: 'districtName', DcmTask.new_inst_cond_name.key: 'newInstCondName', DcmTask.case_closure_condition.key: 'closingConditions', DcmTask.reporter_name.key: 'reporterName', DcmTask.reporter_contact.key: 'reporterContact', DcmTask.reply_intime.key: 'replyIntime', DcmTask.first_depart_name.key: 'firstDepartName', DcmTask.second_depart_name.key: 'secondDepartName', DcmTask.bundle_warning_time.key: 'bundleWarningTimeStr', DcmTask.act_ard_state_name.key: 'actArdStateName', DcmTask.operation.key: 'operateType', } """ 数据推送映射关系。 """ async def after_push_order_request(response: HTTPResponse, retry_queue: asyncio.Queue[HTTPRequest]): """ 工单推送请求响应后的处理程序。 :param response: 响应对象 :param retry_queue: 重试队列 """ body = response.body.decode() echo_log(body) body_data = json.loads(body) code = udict.get_by_path(body_data, 'code') message = udict.get_by_path(body_data, 'msg') if code == 200: dcm_task_id_list = getattr(response.request, "dcm_task_id_list", []) dcm_task_push_data = [ { DcmPushStatus.dcm_task_id.key: dcm_task_id, DcmPushStatus.push_task_status.key: 1 } for dcm_task_id in dcm_task_id_list ] dcm_task_push_df = pd.DataFrame(dcm_task_push_data) await DcmPushStatus.save_batch(dcm_task_push_df) echo_log(f"推送企业待办成功.") else: echo_log(f"推送企业待办失败:{message}") if retry_queue: echo_log(f"企业待办重试队列中有:{retry_queue.qsize()} 个请求在等待.") async def push_order(fetch_size: int = 50, batch_size: int = 10, task_id: Optional[Union[str, int, list[Union[str, int]]]] = None): """ 推送待办数据及其数据。 :param fetch_size: 本次推送数量 :param batch_size: 分批时,每批大小 :param task_id: 待办任务 ID 可选 """ # 根据条件获取目标任务 ID 列表(支持指定 task_id 或分页获取) task_query = select( DcmTask.id, DcmTask.task_num, DcmTask.other_task_num, DcmTask.bundle_deadline_time, DcmTask.rollback_deadline, DcmTask.event_src_name, DcmTask.rec_type_name, DcmTask.event_type_name, DcmTask.main_type_name, DcmTask.sub_type_name, DcmTask.urgency_level, DcmTask.event_desc, DcmTask.address, DcmTask.processing_deadline, DcmTask.district_name, DcmTask.new_inst_cond_name, DcmTask.case_closure_condition, DcmTask.reporter_name, DcmTask.reporter_contact, DcmTask.reply_intime, DcmTask.first_depart_name, DcmTask.second_depart_name, DcmTask.bundle_warning_time, DcmTask.act_ard_state_name, DcmTask.operation ).order_by( desc(DcmTask.act_id) ) if task_id: if isinstance(task_id, list): task_query = task_query.where(DcmTask.id.in_(task_id)) echo_log(f"本次推送待办列表:{task_id} 的数据...") else: task_query = task_query.where(DcmTask.id == task_id) echo_log(f"本次推送待办:{task_id} 的数据...") else: task_query = task_query.limit(fetch_size) echo_log(f"本次推送前 {fetch_size} 条待办数据...") # if apps.get_active_env() == 'prod': # # 生产环境只推送 DcmTaskProcessInfo.action_time > 2026-05-18 00:00:00 的待办工单 # # 构建子查询:查找满足条件的 DcmTaskProcessInfo # subquery = select(DcmTaskProcessInfo.dcm_task_id).where( # DcmTaskProcessInfo.dcm_task_id == DcmTask.id, # DcmTaskProcessInfo.action_time > '2026-05-18 00:00:00' # ).group_by( # DcmTaskProcessInfo.dcm_task_id # ).order_by( # desc(DcmTaskProcessInfo.action_time) # ) # task_query = task_query.where(exists(subquery)) dcm_task_df = await DcmTask.query_as_df(task_query) # 格式化三个时间字段为 yyyy-MM-dd HH:mm:ss dcm_task_df[DcmTask.bundle_deadline_time.key] = ( pd.to_datetime( dcm_task_df[DcmTask.bundle_deadline_time.key], unit='ms', errors='coerce' ).dt.strftime('%Y-%m-%d %H:%M:%S') ) dcm_task_df[DcmTask.rollback_deadline.key] = ( pd.to_datetime( dcm_task_df[DcmTask.rollback_deadline.key], unit='ms', errors='coerce' ).dt.strftime('%Y-%m-%d %H:%M:%S')) dcm_task_df[DcmTask.bundle_warning_time.key] = ( pd.to_datetime( dcm_task_df[DcmTask.bundle_warning_time.key], unit='ms', errors='coerce' ).dt.strftime('%Y-%m-%d %H:%M:%S')) # 格式化为字符串 dcm_task_df[DcmTask.id.key] = dcm_task_df[DcmTask.id.key].astype(str) # 代码转义 reply_intime_map = { '0': '无需回复', '1': '待回复', '2': '已回复', '3': '超时未回复', '4': '无需回复已恢复', } dcm_task_df[DcmTask.reply_intime.key] = dcm_task_df[DcmTask.reply_intime.key].astype(str).map( lambda x: reply_intime_map.get(x, x) ) urgency_level_map = { '0': '正常', '1': '紧急', } dcm_task_df[DcmTask.urgency_level.key] = dcm_task_df[DcmTask.urgency_level.key].astype(str).map( lambda x: urgency_level_map.get(x, x) ) dcm_task_df[DcmTask.operation.key] = dcm_task_df[DcmTask.operation.key].str.split(',') # 处理数据映射,适应接口推送 mapped_df = dcm_task_df.rename(columns=DcmTaskMapping) # 这里把空数据都换成 None,以便存入数据库时是 null mapped_df.replace(models.EmptyInDF + models.EmptyDatetimeInDF, '', inplace=True) echo_log(f"正在准备请求队列...") # 构建请求队列 dcm_push_queue = asyncio.Queue() # 向队列中填充请求对象 for start in range(0, len(mapped_df), batch_size): batch_df: pd.DataFrame = mapped_df.iloc[start:start + batch_size] push_list = batch_df.to_dict('records') push_request = await oa_api_request.get_push_order_request(push_list) setattr(push_request, "dcm_task_id_list", batch_df['gdId'].unique().tolist()) await dcm_push_queue.put(push_request) # 并发提交推送请求 echo_log(f"开始推送待办数据...") await requests.async_concurrency( dcm_push_queue, con_count=dock.CONCURRENCY_COUNT, retry=dock.MAX_RETRY_COUNT, after_request=after_push_order_request ) echo_log(f"待办数据推送已经完成...") async def push_full_order(fetch_size: int = 50, batch_size: int = 10, task_id: Optional[Union[str, int, list[Union[str, int]]]] = None): from dock.oa_dcm import oa_push_order_detail, oa_push_process_info, oa_push_attachment, \ oa_push_more_info, oa_push_extend_info, oa_upload await push_order(fetch_size, batch_size, task_id) await oa_push_order_detail.push_order_detail(fetch_size, task_id) await oa_push_process_info.push_process_info(fetch_size, task_id) await oa_upload.upload_with_attachment(fetch_size, task_id) await oa_push_attachment.push_attachment(fetch_size, task_id) await oa_push_more_info.push_more_info(fetch_size, task_id) await oa_push_extend_info.push_extend_info(fetch_size, task_id) async def push_sign_order(): """ 推送并签收工单。 """ from dock.oa_dcm import oa_push_order_detail, oa_push_process_info, oa_push_attachment, \ oa_push_more_info, oa_push_extend_info, oa_upload, oa_sign_task # TODO: 查询得到要推送的工单ID列表 task_id_list = [] if task_id_list: await push_order(task_id=task_id_list) await oa_push_order_detail.push_order_detail(task_id=task_id_list) await oa_push_process_info.push_process_info(task_id=task_id_list) await oa_upload.upload_with_attachment(task_id=task_id_list) await oa_push_attachment.push_attachment(task_id=task_id_list) await oa_push_more_info.push_more_info(task_id=task_id_list) await oa_push_extend_info.push_extend_info(task_id=task_id_list) # 推送结束后,签收工单 await oa_sign_task.sign_task(task_id=task_id_list) if __name__ == "__main__": from paste.core import aio_pool _runner = aio_pool.get_aio_runner() _runner(push_order(task_id=2054174091254042627))