
后端企业应用【免费下载链接】erpnextFree and Open Source Enterprise Resource Planning (ERP)项目地址https://gitcode.com/GitHub_Trending/er/erpnext点击查看免费下载Bank Clearance Detail 是 ERPNext 会计模块Accounts中Bank Clearance银行清算工具的核心子表 DocType以表格字段的形式承载每一笔待清算交易的明细行。本文以该子表的字段定义与父表控制器的真实实现为骨架讲解它的数据结构、数据来源Journal Entry / Payment Entry / Purchase Invoice / POS 收款四类来源、Clearance Date 的批量回写流程与校验规则帮助读者掌握 ERPNext 银行清算工具背后的数据模型与调用链并能在实际对账场景中正确使用Get Payment Entries / Update Clearance Date操作。一、Bank Clearance Detail 是什么父表工具的行明细在 ERPNext 中Bank Clearance 是一个 Singleissingle: 1类型的工具文档用于更新银行交易的实际到账/清账日期父表 README 原文Tool to update realization dates for banking transactions。而 Bank Clearance Detail 正是它的行明细——子表 README 的一行描述直接点明了它的定位Detail of transaction for parent Bank Clearance.在父表 bank_clearance.json 中payment_entries字段被定义为{ allow_bulk_edit: 1, fieldname: payment_entries, fieldtype: Table, label: Payment Entries, options: Bank Clearance Detail }即父表的payment_entries支付条目表格字段其options直接指向Bank Clearance Detail二者构成一对多的主从关系。子表自身在 bank_clearance_detail.json 中被标记为istable: 1Table DocType不独立创建单据只作为行数据存在、editable_grid: 1网格内可编辑、quick_entry: 1与row_format: Dynamic。二、字段结构全景九个字段逐一解析子表的field_order与fields定义了 9 个字段共 2 列布局是整篇文章的数据核心。完整定义见 bank_clearance_detail.json字段明细如下字段名 (fieldname)标签 (label)字段类型 (fieldtype)关键属性说明payment_documentPayment DocumentLink → DocType—记录来源单据类型如 Journal Entry、Payment Entry、Purchase Invoice、Sales Invoicepayment_entryPayment EntryDynamic Link →payment_documentin_list_view: 1网格内 2 列动态链接字段根据payment_document指向具体单据名称旧字段名为voucher_idagainst_accountAgainst AccountDataread_only: 1in_list_view: 1宽 15对方科目/往来方供应商、客户等由系统填充不可手改amountAmountDataread_only: 1in_list_view: 1金额注意类型是 Data格式化字符串见下文借/贷方向说明旧字段名为debitposting_datePosting DateDateread_only: 1过账日期cheque_numberCheque NumberDataread_only: 1in_list_view: 1支票/参考号取自各来源单据的参考号字段cheque_dateCheque DateDateread_only: 1in_list_view: 1支票日期clearance_dateClearance DateDatein_list_view: 1唯一可编辑字段清账/实际到账日期用户在此输入新日期后批量回写来源单据几点值得注意的设计细节Dynamic Link 组合payment_entry使用Dynamic Link其options: payment_document表示链接目标类型由同行的payment_document字段动态决定——这是 ERPNext 中多类型单据引用的标准做法避免为每类单据单独建链接字段。类型注释bank_clearance_detail.py 中的DF.DynamicLink与之一致。amount 是 Data 而非 Currency金额字段被定义为Data且read_only因为父控制器在填充时会把数值格式化为带借/贷方向的展示字符串详见第三节因此这里不需要货币数值语义。旧字段名痕迹多个字段保留oldfieldnamevoucher_id、against_account、debit、posting_date、cheque_number、cheque_date、clearance_date表明该子表自 2013 年creation: 2013-02-22以来历经字段演进oldfieldname用于历史数据迁移兼容。权限与只读策略父表为read_only: 1、hide_toolbar: 1仅授予Accounts User角色create/read/write/share子表本身permissions为空Table 类型不单独配置权限随父文档权限走所有明细字段默认只读仅clearance_date开放编辑确保用户只能修改清算日期而不能篡改交易事实。三、数据从哪来get_payment_entries 与 hooks 调用链子表行数据由父表 bank_clearance.py 中的白名单方法get_payment_entriesL42–L90批量填充。其核心逻辑frappe.whitelist() def get_payment_entries(self): if not (self.from_date and self.to_date): frappe.throw(_(From Date and To Date are Mandatory)) if not self.account: frappe.throw(_(Account is mandatory to get payment entries)) entries [] precision cint(frappe.db.get_default(currency_precision)) or 2 for method_name in frappe.get_hooks(get_payment_entries_for_bank_clearance): entries ( frappe.get_attr(method_name)( self.from_date, self.to_date, self.account, self.bank_account, self.include_reconciled_entries, self.include_pos_transactions, ) or [] ) entries sorted(entries, keylambda k: getdate(k[posting_date])) self.set(payment_entries, []) ... for d in entries: row self.append(payment_entries, {}) amount flt(d.get(debit, 0)) - flt(d.get(credit, 0)) ... formatted_amount fmt_money(abs(amount), precision, d.account_currency) d.amount formatted_amount (_(Dr) if amount 0 else _(Cr)) d.posting_date getdate(d.posting_date) d.pop(credit); d.pop(debit); d.pop(account_currency) row.update(d)要点Hook 驱动方法通过frappe.get_hooks(get_payment_entries_for_bank_clearance)遍历所有注册的取数函数支持多应用扩展。当前仓库在 hooks.py 注册了默认实现get_payment_entries_for_bank_clearance ( erpnext.accounts.doctype.bank_clearance.bank_clearance.get_payment_entries_for_bank_clearance )四类来源单据bank_clearance.pyL183–L391 的get_payment_entries_for_bank_clearanceJournal Entry日记账分录L188–L229按account与name分组聚合取cheque_no/cheque_date、借贷合计、against_account、clearance_date过滤docstatus 1且is_opening NoPayment Entry付款单L231–L303覆盖paid_from account或paid_to account两种情况通过Case表达式将付款额、税费、收款额折算为 debit/credit并取reference_no/reference_date作为支票号/支票日期Purchase Invoice已付款L305–L341is_paid 1且cash_bank_account account的采购发票取bill_no作为支票号POS 收款Sales Invoice PaymentL343–L382仅当勾选include_pos_transactions时查询取reference_no与收款金额。过滤已清算条目默认不勾选include_reconciled_entries只取clearance_date为空含 MySQL 的0000-00-00/ Postgres 的 NULL的未清算交易查询语句中对数据库方言做了兼容处理。金额方向debit - credit为正则追加 Dr借为负则追加 Cr贷金额以fmt_money按账户币种格式化后存入 Data 类型的amount字段——这也是字段定义中 amount 用 Data 的原因。排序结果按posting_date升序排列后逐行append(payment_entries, ...)写入子表。四、Clearance Date 更新流程与校验规则用户填写各行clearance_date后点击Update Clearance Date调用父控制器update_clearance_datebank_clearance.py L92–L180。流程分三步1. 行级校验L99–L132def validate_entry(d): is_valid True if not d.payment_document: invalid_document.append(str(d.idx)) is_valid False if d.clearance_date and d.cheque_date and getdate(d.clearance_date) getdate(d.cheque_date): invalid_cheque_date.append(str(d.idx)) is_valid False return is_valid规则有两类① 每行必须存在payment_document来源类型否则报错Payment document required for row(s)② 清算日期不得早于支票日期clearance_date cheque_date视为非法报错Clearance date must be after cheque date for row(s)。非法行会以msgprint汇总列出行号idx并中止本次更新。2. 收集待更新行L111–L116通过校验且clearance_date有值或勾选了include_reconciled_entries的行才进入entries_to_update若没有任何待更新行提示Clearance Date not mentioned。3. 逐行回写来源单据L138–L180Sales Invoice 特例若payment_document Sales Invoice更新的是 POS 收款子表Sales Invoice Payment中匹配parent payment_entry、account self.account、amount 0记录的clearance_date使用frappe.db.set_value并在销售发票上追加评论其他单据通过frappe.get_lazy_doc(d.payment_document, d.payment_entry)取得来源单据调用payment_entry.db_set(clearance_date, d.clearance_date)回写注释明确说明using db_set to trigger notification即借 db_set 触发更新通知同时记录评论Clearance date changed from {old} to {new} via Bank Clearance Tool更新完成后重新调用self.get_payment_entries()刷新子表并提示Clearance Date updated。注意方法开头执行self.check_permission(write)与父表仅授Accounts User写权限的配置呼应。五、客户端交互与使用步骤前端脚本 bank_clearance.js 定义了完整交互表单加载onload自动带入公司默认银行账户default_bank_account到account字段from_date/to_date默认设为当月的第一天与最后一天账户筛选set_queryaccount只能选择account_type为 Bank/Cash 且非分组is_group: 0的科目bank_account只能选择is_company_account: 1的银行账户按钮逻辑refresh表单disable_save()工具型 Single 文档不保存始终显示主按钮Get Payment Entries当payment_entries有数据时追加Update Clearance Date主按钮调用方式两个按钮均通过frappe.call({ method, doc: frm.doc })调用上文的白名单方法返回后frm.refresh()刷新表格。典型使用流程在会计 → 银行清算Bank Clearance工具中选择银行账户默认自动带出确认起始/截止日期点击Get Payment Entries系统按第三节的四类来源把未清算交易逐行填充进 Bank Clearance Detail 子表需要看到历史已清算条目时勾选Include Reconciled Entries需要纳入 POS 收款时勾选Include POS Transactions逐行核对并填写实际到账的Clearance Date不得早于支票日期点击Update Clearance Date系统校验后批量回写来源单据日记账、付款单、采购发票或 Sales Invoice Payment的clearance_date并留下审计评论。六、设计要点小结主从结构清晰Bank ClearanceSingle 工具文档→payment_entriesTable 字段→ Bank Clearance Detailistable子表是 ERPNext 工具型 Single 明细子表的典型范式只读快照 单点编辑明细行除clearance_date外全部read_only保证来源交易信息不被篡改用户只需维护清算日期这一个状态动态链接解耦payment_documentLink→DocTypepayment_entryDynamic Link组合让一个子表承载多种单据类型而无需扩表Hook 扩展点取数逻辑挂在get_payment_entries_for_bank_clearancehook 上其他应用可追加自己的数据来源校验与审计闭环清算日期 ≥ 支票日期、必填来源类型等行级校验加上changed from X to Y via Bank Clearance Tool评论为对账操作保留完整可追溯记录。相关文件索引子表定义 子表控制器 父表控制器 父表定义 客户端脚本 Hook 注册。赞分享后端企业应用【免费下载链接】erpnextFree and Open Source Enterprise Resource Planning (ERP)项目地址https://gitcode.com/GitHub_Trending/er/erpnext点击查看免费下载相关推荐MCP Inspector工具列表动态更新机制深度解析MCP Inspector工具列表动态更新机制深度解析 还在为MCP服务器工具列表的实时同步问题烦恼吗本文将深入剖析MCP Inspector如何实现工具列表开发工具MCP Clients调试器Gramophone项目架构分析从应用层到底层模块的完整设计Gramophone项目架构分析从应用层到底层模块的完整设计 Gramophone是一款基于Android Media3和Material Design库构建rippled 账本处理机制深入解析生命周期、账本流、数据结构与账本清理器rippled 账本处理机制深入解析生命周期、账本流、数据结构与账本清理器 导读 本文以 rippledXRP Ledger 服务器实现的 Ledger区块链上一篇3步解决CUDA编译难题让你的llama.cpp在NVIDIA GPU上飞起来下一篇Windows 10终极瘦身指南一键禁用无用服务提升系统性能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考