
影刀RPA 合同全生命周期管理到期提醒与自动续约作者林焱 | 适用人群影刀RPA新手 | 难度★★★☆☆一、什么情况用这个公司签了一堆合同——供应商合同、客户合同、租赁合同、服务合同。每份合同有到期日、续约条款、付款节点。靠Excel管理合同快到期了没人知道供应商续约晚了导致服务中断客户合同过期了还在提供服务。用影刀RPA定时扫描合同台账 → 到期前自动提醒 → 根据续约规则自动发续约通知 → 更新台账状态。合同管理从「被动应对」变成「主动预警」。实际场景采购合同续约管理、客户服务合同到期提醒、租赁合同退租预警、付款节点自动通知。这篇文章能解决的问题合同到期分级提醒30天/7天/1天自动发送续约通知邮件合同付款节点自动提醒合同归档文件自动整理二、怎么做2.1 台账设计合同台账Excel合同编号合同名称签约方类型签署日期到期日期续约规则付款周期状态归档路径CT-001IT运维服务某科技公司供应商2023-06-012024-06-01自动续约年付生效中D:\合同\CT-001.pdf2.2 影刀主流程┌──────────────────────────────────────────────┐ │ ① 【读取Excel】 │ │ 读取合同台账 │ │ ↓ │ │ ② 【遍历列表】 │ │ 逐条检查合同状态 │ │ ↓ │ │ ③ 【条件判断】 │ │ 到期≤30天 → 高级提醒 │ │ 到期≤7天 → 紧急提醒 │ │ 到期≤1天 → 最后警告 │ │ 到期0天 → 标记为过期 │ │ ↓ │ │ ④ 【发送企业微信消息 邮件】 │ │ 分级推送提醒 │ │ ↓ │ │ ⑤ 【写入Excel】 │ │ 更新台账状态 │ └──────────────────────────────────────────────┘2.3 核心代码fromdatetimeimportdatetime,timedeltaimportjson# 从影刀Excel读取的数据contractscontracts_data todaydatetime.now().date()# 分级提醒配置ALERT_LEVELS[{days:30,level:提示,priority:普通},{days:7,level:警告,priority:重要},{days:1,level:紧急,priority:紧急},]alerts[]# 提醒列表expired[]# 已过期to_renew[]# 待续约forcontractincontracts:end_date_strcontract.get(到期日期,)ifnotend_date_str:continuetry:end_datedatetime.strptime(end_date_str,%Y-%m-%d).date()days_left(end_date-today).days# 分级提醒ifdays_left30ordays_left7ordays_left1:forlevelinALERT_LEVELS:ifdays_leftlevel[days]:alerts.append({**contract,days_left:days_left,level:level[level],priority:level[priority],})# 已过期ifdays_left0:expired.append({**contract,days_overdue:abs(days_left),})# 续约提醒到期前60天if0days_left60andcontract.get(续约规则)!自动续约:to_renew.append({**contract,days_left:days_left,})exceptValueError:print(f合同日期格式错误{contract.get(合同编号)})# 汇总result{check_date:today.strftime(%Y-%m-%d),total:len(contracts),alerts:alerts,expired:expired,to_renew:to_renew,}outputjson.dumps(result,ensure_asciiFalse)2.4 自动发送续约通知defgenerate_renewal_notice(contract):生成续约通知templatef尊敬的{contract[签约方]} 您好 贵司与我司签订的「{contract[合同名称]}」合同编号{contract[合同编号]} 将于{contract[到期日期]}到期距今还有{contract[days_left]}天。 根据合同约定续约规则为{contract.get(续约规则,双方协商)}如需续约请及时与我司联系 联系人张经理 电话138-0000-0000 邮箱zhangcompany.com 此致 敬礼 returntemplate# 在影刀中【遍历列表】→ to_renew中的每条合同 【发送邮件】 收件人{合同签约方邮箱}主题合同续约通知-{合同名称}正文{generate_renewal_notice(合同)}附件{合同归档路径}2.5 付款节点提醒如果合同有分期付款条款自动提醒付款defcheck_payment_schedule(contract):检查付款节点# 假设在台账中有一个「付款节点」字段格式# 2024-03-01:30%,2024-06-01:30%,2024-09-01:40%schedule_strcontract.get(付款节点,)ifnotschedule_str:return[]reminders[]todaydatetime.now().date()foriteminschedule_str.split(,):if:initem:date_str,amountitem.split(:)try:pay_datedatetime.strptime(date_str.strip(),%Y-%m-%d).date()days_left(pay_date-today).days# 付款前7天提醒if0days_left7:reminders.append({contract_no:contract[合同编号],pay_date:date_str.strip(),amount_ratio:amount.strip(),days_left:days_left,})exceptValueError:passreturnreminders三、有什么坑坑1合同台账数据来源分散合同可能来自采购部、法务部、业务部各自维护一份Excel信息不统一。解决方案先花时间整合一份主台账然后用影刀定期从各部门的Excel中抓更新。影刀本身就可以做「多源数据聚合」这件事。坑2续约规则不标准化有的合同是「自动续约」有的是「提前30天通知续约」有的是「到期终止」。如果台账里的续约规则是自由文本而非枚举值程序很难判断。建议标准化续约规则字段用下拉列表「自动续约」「需协商续约」「到期终止」「提前N天通知」。坑3合同文件归档路径变化合同PDF文件的存放路径经常变化——文件被移动了、重命名了、删除了。importosdefverify_contract_file(filepath):验证合同文件是否存在ifnotfilepath:returnFalseifnotos.path.exists(filepath):print(f⚠️ 合同文件不存在{filepath})returnFalsereturnTrue# 每次扫描时验证forcontractincontracts:ifnotverify_contract_file(contract.get(归档路径)):# 标记为需要补档contract[状态]缺档坑4提醒频率过高如果每份合同每天检查一次都发提醒相关人员会很快免疫——「狼来了」效应。控制频率同一份合同在同一个提醒级别只提醒一次。用一个Excel记录已发送的提醒# 检查今天是否已经给这份合同发过30天提醒sent_alerts{}foralert_recordinsent_today:keyf{alert_record[contract_no]}-{alert_record[days_left]}sent_alerts[key]Trueforalertinnew_alerts:keyf{alert[合同编号]}-{alert[days_left]}ifkeynotinsent_alerts:# 发送提醒send_alert(alert)# 记录已发送record_alert_sent(alert)坑5跨年合同日期判断跨年的合同日期计算可能因为年份变化出错。Python的datetime模块天生支持跨年计算不用担心。# Python自动处理跨年date1date(2024,12,25)date2date(2025,1,5)diff(date2-date1).days# 11正确总结合同管理的核心是台账 定时巡检。台账准、规则标准化影刀就能自动做到期提醒和续约通知。关键是要控制提醒频率同一合同同一级别只提醒一次。