hrms 培训反馈(Training Feedback)邮件通知模板与配置深度解析
发布时间:2026/10/2 8:03:45 锦皓数字建站
邮件通知模板与配置深度解析`)
企业应用后端前端移动开发【免费下载链接】hrmsOpen Source HR and Payroll Software项目地址https://gitcode.com/GitHub_Trending/hr/hrms点击查看免费下载本篇指南以 hrms开源 HR 与薪资软件中内置的 Training Feedback 标准通知为线索完整拆解其通知定义Notification JSON、邮件正文模板Jinja/HTML、收件人机制与底层培训数据流转。读完你不仅能逐行理解该通知模板的每个占位符与配置字段还能掌握 Frappe 框架下基于文档字段派发邮件通知的标准做法以及 Training Event → Training Result → Training Feedback 三张单据之间的状态联动规则。一、通知模板在 hrms 培训流程中的定位在 hrms 中培训Training相关的单据与通知分散在 hrms/hr/doctype/ 目录下其中与培训反馈收集直接相关的三张核心单据是单据作用关键源码/定义Training Event培训事件主表登记事件名称、类型、地点、起止时间与参与者training_event.py、training_event.jsonTraining Event Employee培训事件子表逐人记录考勤Present/Absent与状态Open/Invited/Completed/Feedback Submittedtraining_event_employee.jsonTraining Result培训结果单提交后触发本通知training_result.pyTraining Feedback培训反馈单员工提交后状态回写为 Feedback Submittedtraining_feedback.py本篇文章讨论的通知文件位于 hrms/hr/notification/training_feedback/该目录共 5 个文件各自职责如下training_feedback.json—— Notification 单据的完整定义消息内容、收件人、触发事件等training_feedback.md—— 邮件正文模板的源文件与 JSON 中message字段内容一致training_feedback.py—— 可选的通知上下文钩子get_context当前为空实现training_feedback.html—— 另一份参考用的邮件模板以doc前缀方式引用单据字段__init__.py—— 空文件标识包结构。二、通知定义文件training_feedback.json 字段逐项解读Frappe 框架中通知本身也是一种 DocTypeNotification。training_feedback.json给出了这条内置通知的完整配置关键字段如下{ attach_print: 0, channel: Email, creation: 2017-08-11 03:17:11.769210, days_in_advance: 0, docstatus: 0, doctype: Notification, document_type: Training Result, enabled: 1, event: Submit, is_standard: 1, message: h3{{_(\Training Event\)}}/h3\np{{ message }}/p\n\nh4{{_(\Details\)}}/h4\n{{_(\Event Name\)}}: a href\{{ event_link }}\{{ name }}/a\nbr{{_(\Event Location\)}}: {{ location }}\nbr{{_(\Start Time\)}}: {{ start_time }}\nbr{{_(\End Time\)}}: {{ end_time }}\nbr{{_(\Attendance\)}}: {{ attendance }}\n, name: Training Feedback, recipients: [ { email_by_document_field: employee_emails } ], subject: Please Share your Feedback For {{ doc.training_event }} }字段含义与配置要点字段取值说明doctypeNotification通知记录本身是 Frappe 的 Notification 单据nameTraining Feedback通知名称即这条标准通知的唯一标识is_standard1标准通知随应用安装自动部署到站点enabled1通知处于启用状态channelEmail发送渠道为邮件Frappe 通知还支持 Slack、System Notification 等渠道document_typeTraining Result监听对象Training Result 单据发生指定事件时触发eventSubmit触发事件Training Result 提交submit时触发。可选的框架事件还包括 New、Save、Value Change、Days Before、Days After 等attach_print0不随邮件附加单据的 PDF 打印件days_in_advance0仅用于按日期提前触发的事件Days Before/Days After此处无实际作用recipients[0].email_by_document_fieldemployee_emails收件人来源从 Training Result 单据的employee_emails字段读取收件邮箱subjectPlease Share your Feedback For {{ doc.training_event }}邮件主题。注意主题里使用doc.前缀引用提交单据的字段doc.training_event而正文模板用的是裸变量详见第四节message见下文第三节邮件正文模板即training_feedback.md的内容JSON 中为转义后的字符串形式要点通知的触发对象是Training Result而不是 Training Event。也就是说当 HR 将某次培训的结果单提交Submit后系统自动向该结果单关联员工的邮箱发送请提交培训反馈的邮件。三、邮件正文模板逐行拆解training_feedback.mdtraining_feedback.md的完整原文如下本文完整保留并逐行展开h3{{_(Training Event)}}/h3 p{{ message }}/p h4{{_(Details)}}/h4 {{_(Event Name)}}: a href{{ event_link }}{{ name }}/a br{{_(Event Location)}}: {{ location }} br{{_(Start Time)}}: {{ start_time }} br{{_(End Time)}}: {{ end_time }} br{{_(Attendance)}}: {{ attendance }}逐行说明h3{{_(Training Event)}}/h3—— 邮件标题段。{{ _(...) }}是 Frappe 的国际化i18n翻译函数Jinja 渲染时会按当前站点语言从翻译表取词。该通知涉及的字符串Training Event、Event Name、Event Location、Start Time、End Time、Attendance 等在 hrms/locale/ 下的各语言.po文件如zh.po、zh_TW.po、de.po等中均有对应翻译条目验证了通知模板的多语言能力。p{{ message }}/p—— 正文首段输出通知上下文中的message变量。该变量由 Frappe 通知框架在渲染消息时注入用于承载说明性文字。h4{{_(Details)}}/h4—— 详情小标题。{{_(Event Name)}}: a href{{ event_link }}{{ name }}/a—— 事件名称行。event_link为指向培训事件记录的链接地址name为事件名称。从源码结构看Training Event 采用按字段自动命名autoname: field:event_nameevent_name即事件名见 training_event.json 的autoname配置name即事件记录名与event_name相同。br{{_(Event Location)}}: {{ location }}—— 培训地点对应 Training Event 的location字段必填见training_event.json中location的reqd: 1。br{{_(Start Time)}}: {{ start_time }}—— 开始时间对应 Training Event 的start_timeDatetime类型、必填。br{{_(End Time)}}: {{ end_time }}—— 结束时间对应 Training Event 的end_timeDatetime类型、必填。br{{_(Attendance)}}: {{ attendance }}—— 参与者的考勤状态对应 Training Event Employee 子表中的attendance字段取值Present/Absent见 training_event_employee.json。模板中占位符与底层字段的映射关系汇总模板变量含义对应字段/来源message正文提示语Frappe 通知框架注入的上下文变量event_link培训事件记录链接指向 Training Event 表单的 URLname事件名称Training Event 的event_nameautoname 字段location培训地点Training Event.locationstart_time开始时间Training Event.start_timeend_time结束时间Training Event.end_timeattendance考勤状态Training Event Employee.attendancePresent/Absent四、上下文变量来源与两个值得注意的实践问题4.1 get_context 钩子当前为空实现training_feedback.py提供了标准的上下文钩子但目前是空实现def get_context(context): # do your magic here pass在 Frappe 通知机制中get_context(context)允许为消息模板注入自定义上下文变量。当前为空意味着模板中message、event_link、name、location等变量依赖框架默认上下文与关联单据数据提供若某些变量未出现在渲染上下文中Jinja 会将其渲染为空串邮件中对应位置留白。需要为模板补充数据如按参与员工定制考勤信息时可在get_context中填充context[...]后由模板引用。4.2 主题用doc.前缀、正文用裸变量写法的对比观察同一通知的两处模板写法可以发现一个对比邮件主题JSON 中的subject使用了{{ doc.training_event }}显式引用提交单据Training Result上的training_event字段邮件正文training_feedback.md使用{{ event_link }}、{{ name }}等裸变量未加doc.前缀。4.3 同目录参考模板的推荐写法training_feedback.html 是同一目录下的另一份参考模板它展示了更显式、可追溯的写法p{{ _(Hello) }},/p pYou attended training {{ frappe.utils.get_link_to_form( Training Event, doc.training_event) }}/p p{{ _(Please share your feedback to the training by clicking on Training Feedback and then New) }}/p这段模板直接通过frappe.utils.get_link_to_form(Training Event, doc.training_event)生成培训事件的可点击链接并把操作引导进入 Training Feedback、点击 New 新建反馈写进邮件正文。对比可见前者.md依赖注入变量、字段更省后者.html显式引用单据字段、可读性更强。实际部署时若遇到正文占位符渲染为空可参考.html的做法改用doc.前缀字段与frappe.utils.get_link_to_form组合。五、底层数据流从培训事件到反馈提交的状态机通知只是最后一公里要真正理解它需要看懂背后三张单据如何联动。以下链路均有源码佐证。5.1 Training Event参与者与邮箱的初始化training_event.py 中def validate(self): self.set_employee_emails() self.validate_period() def set_employee_emails(self): self.employee_emails , .join(get_employee_emails([d.employee for d in self.employees])) def validate_period(self): if time_diff_in_seconds(self.end_time, self.start_time) 0: frappe.throw(_(End time cannot be before start time)) def on_update_after_submit(self): self.set_status_for_attendees()set_employee_emails()遍历子表employees通过 ERPNext 的get_employee_emails工具函数erpnext.setup.doctype.employee.employee拼装出逗号分隔的员工邮箱串写入employee_emails隐藏字段validate_period()校验结束时间不得早于开始时间on_update_after_submit()中set_status_for_attendees()依据event_statusScheduled/Completed/Cancelled见training_event.json批量更新参与者状态事件 Completed 时考勤为 Present 且尚未提交反馈的员工状态置为 Completed事件 Scheduled 时全部重置为 Open。5.2 Training Result触发通知并回写参与者状态training_result.pydef validate(self): training_event frappe.get_doc(Training Event, self.training_event) if training_event.docstatus ! 1: frappe.throw(_({0} must be submitted).format(_(Training Event))) self.employee_emails , .join(get_employee_emails([d.employee for d in self.employees])) def on_submit(self): training_event frappe.get_doc(Training Event, self.training_event) training_event.status Completed for e in self.employees: for e1 in training_event.employees: if e1.employee e.employee: e1.status Completed break training_event.save()要点validate()要求关联的 Training Event 必须已提交docstatus 1同时自动填充employee_emails——这正是通知收件人email_by_document_field取值的来源on_submit()提交结果单时把 Training Event 中对应参与者的状态批量置为 Completed形成状态闭环Training Result 提交时Notification 监听Submit事件即被触发向employee_emails中的地址发送本模板邮件。5.3 Training Feedback校验规则与状态回写training_feedback.py 定义了员工填写反馈时的业务约束def validate(self): training_event frappe.get_doc(Training Event, self.training_event) if training_event.docstatus ! 1: frappe.throw(_({0} must be submitted).format(_(Training Event))) emp_event_details frappe.db.get_value( Training Event Employee, {parent: self.training_event, employee: self.employee}, [name, attendance], as_dictTrue, ) if not emp_event_details: frappe.throw(_(Employee {0} not found in Training Event Participants.).format(...)) if emp_event_details.attendance Absent: frappe.throw(_(Feedback cannot be recorded for an absent Employee.)) def on_submit(self): # 将参与者的状态更新为 Feedback Submitted frappe.db.set_value(Training Event Employee, employee, status, Feedback Submitted) def on_cancel(self): # 取消反馈时回退为 Completed frappe.db.set_value(Training Event Employee, employee, status, Completed)三条核心规则培训事件必须已提交提交者必须是该事件的参与者考勤为 Absent 的员工不允许记录反馈。反馈提交submit后参与者状态变为Feedback Submitted取消则回退为Completed。整个生命周期可归纳为HR 创建并提交Training Event员工邮箱自动汇入employee_emails事件完成后 HR 提交Training Result参与者状态置为 Completed同时触发 Training Feedback 通知向员工发送反馈邀请邮件员工点击邮件中的链接进入Training Feedback新建反馈提交后状态变为 Feedback Submitted收集闭环完成。六、收件人机制employee_emails 的自动填充通知配置中recipients[0].email_by_document_field employee_emails意味着收件人完全来自单据字段。这个字段在两处被自动维护Training Event 的validate()见 training_event.pyTraining Result 的validate()见 training_result.py。两者都调用 ERPNext 的get_employee_emails(employees)将员工列表转成邮箱串。因此只要在事件/结果单中维护好参与者子表employees邮箱地址无需手工录入通知发送时框架自动从employee_emails字段解析收件人一次向全部参与者群发同一封反馈邀请。七、测试用例对业务规则的验证test_training_feedback.py 用两个用例把上面第五节总结的规则固化为自动化测试可作为理解通知背后业务约束的权威依据test_employee_validations_for_feedback员工未登记为培训事件参与者时创建反馈应抛出frappe.ValidationError将参与者考勤置为 Absent 后同样应被拒绝test_training_feedback_status反馈提交后Training Event Employee 的status应更新为Feedback Submitted。测试还演示了搭建场景的标准套路create_training_program(Basic Training)创建培训项目、make_employee(...)创建员工、create_training_event(...)创建事件并submit()、将event_status置为 Completed 后保存对应training_event.py的set_status_for_attendees逻辑。八、与 Training Scheduled 通知的对比hrms/hr/notification/目录下还内置了另一条培训相关通知 training_scheduled培训安排通知其模板 training_scheduled.md 与反馈通知形成鲜明对照Training Scheduled模板基于doc上下文doc.event_name、doc.introduction、doc.location并使用 Jinja 条件语句按起止日期是否同一天分别渲染日期时间段或起止时间还通过frappe.utils.get_datetime格式化日期通过frappe.utils.get_link_to_form生成事件链接Training Feedback模板则全部使用裸变量event_link/name/location/start_time/end_time/attendance。两者对比可以总结出 hrms 团队两种模板组织风格的并存一种是上下文变量注入式简练依赖框架注入一种是doc 字段直引式显式、可控、便于排错。对于希望二次开发通知模板的读者推荐以 Training Scheduled 的写法为参照在 Feedback 通知中改用doc前缀与frappe.utils.get_link_to_form可显著降低占位符解析失败的风险。小结hrms 的 Training Feedback 通知是一个配置 模板 数据流三位一体的典型范本training_feedback.json定义了监听 Training Result 提交事件、按employee_emails字段群发的规则training_feedback.md提供了内嵌国际化标签的 HTML 邮件正文而 Training Event、Training Result、Training Feedback 三张单据的校验与提交逻辑training_event.py、training_result.py、training_feedback.py保证了只有真实参与者、考勤在场者才能反馈的业务约束测试用例 test_training_feedback.py 则让这些规则可持续验证。掌握这条通知的配置与数据链路后你可以在 hrms 内快速复刻类似的单据事件驱动邮件通知能力。赞分享企业应用后端前端移动开发【免费下载链接】hrmsOpen Source HR and Payroll Software项目地址https://gitcode.com/GitHub_Trending/hr/hrms点击查看免费下载相关推荐HRMS 培训日程邮件通知Training Scheduled模板解析与底层实现指南HRMS 培训日程邮件通知Training Scheduled模板解析与底层实现指南 导读 在 Frappe/HRMShrms中培训日程已排定Tr企业应用后端前端移动开发INFINI Console邮件通知SMTP配置与邮件模板INFINI Console邮件通知SMTP配置与邮件模板 概述 INFINI Console作为一款轻量级的多集群、跨版本统一Elasticsearch/O后端数据库可观测性告警运维SBJson 5开发者深度指南从源码解析到自定义扩展实现SBJson 5开发者深度指南从源码解析到自定义扩展实现 SBJson 5是一款高效可靠的JSON处理框架专为iOS和macOS开发者设计。本指南将带您深入上一篇文本驱动CAD如何用自然语言重新定义机械设计工作流下一篇3步完成InvokeAI部署新手也能快速上手的AI绘画终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。