
后端企业应用【免费下载链接】erpnextFree and Open Source Enterprise Resource Planning (ERP)项目地址https://gitcode.com/GitHub_Trending/er/erpnext点击查看免费下载Item Price 是 ERPNext 中负责记录商品Item在特定价格列表Price List中的售价或进价的核心单据其官方定义见 erpnext/stock/doctype/item_price/README.mdPrice of the Item in a particular Price List。本文从该定义出发结合仓库中 item_price.py、item_price.json 及 get_item_details.py 的源码实现完整讲解 Item Price 的字段含义、保存校验、去重规则、查询取价与自动建价机制并给出可运行的测试用例证据帮助你在销售单、采购单、报价单中正确配置和维护商品价格。Item Price 是什么在 ERPNext 的定价体系中价格并不是直接挂在商品档案上的而是以价格列表Price List为单位独立维护。Item Price 就是连接二者的桥梁一条 Item Price 记录 一个商品Item Code 一个价格列表Price List 一个单价Rate。这样的设计带来两个直接好处一套商品多种价格同一商品可以在标准售价表批发价表促销价表等多个价格列表中拥有不同价格实现面向不同客户群、不同渠道的差异化定价。买卖双向价格分离每个价格列表都带有buying/selling属性Item Price 会自动继承价格列表的买卖方向从而区分进价与售价两套价格体系。在 DocType 定义中见 item_price.json该单据的description为Log the selling and buying rate of an Itemdocument_type为 Setuptitle_field为item_name并使用autoname: hash随机命名同时开启了allow_import: 1与quick_entry: 1支持从数据导入工具批量导入价格表单中也有对应入口链接见 item_price.js 中的bulk_import_help字段。Item Price 的完整字段说明以下字段定义均取自 item_price.json按表单中的 Section 分组说明。商品信息区Item Details字段类型必填说明item_codeLink → Item是商品编码设置了search_index与全局搜索索引列表视图、标准筛选均可见uomLink → UOM是计量单位默认从item_code.stock_uom自动带出fetch_if_empty: 1即默认与商品主单位一致packing_unitInt否每 UOM 需买入或卖出的数量字段描述原文Quantity that must be bought or sold per UOM用于包装单位校验item_nameData否只读商品名称保存时自动从 Item 带出brandLink → Brand否只读品牌自动从 Item 带出item_descriptionText Editor否只读商品描述自动从 Item 带出价格列表区Price List字段类型必填说明price_listLink → Price List是所属价格列表设置search_index、全局搜索与标准筛选customerLink → Customer否客户专用价格仅当selling 1时显示depends_on且加粗显示supplierLink → Supplier否供应商专用价格仅当buying 1时显示buyingCheck否只读是否为采购价格自动继承价格列表属性sellingCheck否只读是否为销售价格自动继承价格列表属性currencyLink → Currency否只读币种自动从price_list.currency带出price_list_rateCurrency是单价即本记录的核心价格值batch_noLink → Batch否批次专用价格可针对特定批次单独定价有效期与其他字段类型默认值说明valid_fromDateToday价格生效起始日valid_uptoDate空价格失效日为空表示长期有效lead_time_daysInt0交货周期天noteText—备注referenceData—引用字段保存时由系统自动写入客户或供应商见下文保存时的自动填充与校验逻辑Item Price 的保存逻辑集中在 item_price.py 的validate()方法中依次执行以下步骤1. 商品与计量单位校验validate_item商品必须已存在于 Item 单据中否则抛出Item {0} not found.若指定了uom则该 UOM 必须出现在该商品的 UOM 换算明细UOM Conversion Detail中否则抛出UOM {0} not found in Item {1}。2. 日期范围校验调用框架的validate_from_to_dates(valid_from, valid_upto)确保valid_from不晚于valid_upto。3. 价格列表属性回填update_price_list_details按price_list查询启用状态的 Price List读取其buying、selling、currency三个属性并回填到本记录。若价格列表不存在或已被禁用则抛出The price list {0} does not exist or is disabled。这保证了 Item Price 的买卖方向与币种永远与所属价格列表一致无法人为修改三个字段在表单中均为只读。4. 商品详情回填update_item_details自动从 Item 读取item_name与description写入只读字段避免表单里手动维护与商品档案不一致的冗余数据。5. 变体模板商品禁价validate_item_template若商品被标记为has_variants即它是变体模板而非具体变体则禁止为其创建 Item Price抛出Item Price cannot be created for the template item {item_code}。同时表单端在 item_price.js 的setup中通过filters: { has_variants: 0 }从源头过滤可选商品。6. 重复记录校验check_duplicates这是防止价格记录冗余的关键机制。系统以item_code price_list为基准联合以下维度进行去重数据类字段uom、valid_from、valid_upto、customer、supplier、batch_no数值类字段packing_unit查询逻辑使用 frappe Query Builder 动态拼装当字段有值时按等值匹配当字段为空时则匹配该字段为空或为 0的既有记录对空值也参与比对避免插入无意义的重复行。一旦命中重复抛出ItemPriceDuplicateItem自定义 ValidationError提示文案为Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, Batch, UOM, Qty, and Dates。需要特别说明的是空值也参与去重。但测试test_empty_duplicate_validation表明仅当其余维度完全一致时才判定重复若改变price_list_rate之外的关键维度例如清空 customer则可以正常插入。7. 保存前的引用字段维护before_saveselling为真时reference customerbuying为真时reference supplier仅销售selling 且非 buying时清空supplier仅采购buying 且非 selling时清空customer。这保证了销售价格只绑定客户、采购价格只绑定供应商的语义reference字段则用于列表视图与筛选时快速辨识该记录属于哪个客户/供应商。表单交互与智能过滤item_price.js 提供了表单侧的三项自动化onload 自动带值通过frm.add_fetch在选中 price_list 后自动填充buying、selling、currency选中 item_code 后自动填充item_name、item_description、uom。价格列表动态过滤选中商品后根据 Item 的is_sales_item/is_purchase_item属性动态限定可选的 Price List——纯销售商品只显示销售价格列表selling: 1纯采购商品只显示采购价格列表buying: 1。批次联动batch_no字段仅显示属于当前item_code的批次。此外item_price_list.js 在列表视图中隐藏了系统生成的名称列hide_name_column: true因为 Item Price 使用 hash 随机命名对用户没有业务意义。交易单据中的自动取价机制Item Price 的最终价值体现在业务单据销售订单、销售发票、采购订单、报价单等的取价环节。核心入口是 get_item_details.py 中的get_price_list_rate_for()与get_item_price()。取价优先级从精确到兜底get_item_price()见 get_item_details.py按以下优先级查找 Item Price 记录基础条件item_code匹配、price_list匹配、uom为空或等于单据 UOM批次条件优先匹配当前batch_no其次匹配无批次的价格客户/供应商条件优先精确匹配当前客户或供应商的专用价格其次是既无客户也无供应商的通用价格同时查询并排序客户/供应商专用的排前面日期条件仅返回valid_from transaction_date valid_upto的有效价格空日期视为无限制排序兜底valid_from为空的排在前、valid_from较新的排前、批次/UOM 非空的排前最后以name倒序作为唯一决胜键保证 MariaDB 与 PostgreSQL 上结果一致。get_price_list_rate_for()get_item_details.py在此基础上补充两个关键逻辑包装单位校验若记录设置了packing_unit则要求desired_qty % packing_unit 0即采购/销售数量必须是包装单位的整数倍check_packing_list见 get_item_details.py不满足则放弃该价格UOM 换算若找到的价格以 stock_uom 计价而单据使用其他 UOM则按conversion_factor换算单价price_list_rate × conversion_factor。变体回退与自动建价在get_price_list_rate()get_item_details.py中还有两处重要行为变体回退若当前商品变体查不到价格且它存在variant_of父模板则继续用父模板商品编码查询价格币种换算最终单价 price_list_rate × plc_conversion_rate / conversion_rate即价格列表币种与单据币种之间的换算自动建价当查不到价格时若满足Stock Settings 中的auto_insert_price_list_rate_if_missing已开启、价格列表币种与单据币种一致、用户有 Item Price 写入权限等条件则调用insert_item_price()get_item_details.py自动插入一条新的 Item Price若已有记录且update_existing_price_list_rate开启则直接更新现有记录的price_list_rate否则在交易日期新建一条带有效期的价格。这一机制让录单据时顺手生成价格成为可能但需注意它受库存设置开关的约束。测试用例行为验证清单test_item_price.py 与 test_records.json 用自动化测试固化了以上全部行为可作为功能清单逐一核对测试方法验证点test_template_item_price变体模板商品has_variants: 1保存 Item Price 抛错test_duplicate_item相同 item_code price_list 重复记录抛出ItemPriceDuplicateItemtest_dates_validation_errorvalid_from晚于valid_upto时校验失败test_invalid_item/test_invalid_price_list不存在的商品或价格列表保存失败test_price_in_a_qty/test_price_with_no_qty传入 qty10 时返回 20.0不传 qty 时返回 Nonetest_prices_at_date/test_prices_at_invalid_date/test_prices_outside_of_date按交易日期命中有效期内的价格超出有效期或不合法日期返回 Nonetest_lowest_price_when_no_date_provided不提供日期时取无日期限制长期有效的价格test_empty_duplicate_validation清空客户维度后允许插入新价格且取价返回新值 21test_addition_of_new_fields回归验证 supplier/customer/uom/lead_time_days 等字段存在测试固件test_records.json展示了典型的记录形态例如{ doctype: Item Price, item_code: _Test Item, price_list: _Test Price List, price_list_rate: 100, valid_from: 2017-04-18, valid_upto: 2017-04-26 }以及客户专用价customer: _Test Customeruom: _Test UOM和采购价supplier: _Test Supplier等变体可直接作为手工录入时的参考样例。权限与数据管理根据 item_price.json 的permissions配置Item Price 的完整读写权限授予两个角色Sales Master Manager销售主数据经理Purchase Master Manager采购主数据经理两者均拥有 create / read / write / delete / import / export / print / report / share 全部权限即谁维护销售主数据、谁维护采购主数据的职责划分。结合allow_import: 1企业可以通过数据导入工具Data Import Tool入口见表单内的Import in Bulk链接路径为/app/data-import-tool/Item Price批量导入数千条价格借助quick_entry: 1在弹窗中快速录入单条价格利用index_web_pages_for_search: 1让价格信息可被站内搜索检索到。小结Item Price 是整个 ERPNext 定价体系的数据基石理解它的关键在于记住四条主线一对多结构一个商品在多个价格列表中可有多条价格记录价格列表决定买卖方向与币种多层取价优先级批次/客户/供应商专用价 通用价日期有效期裁剪UOM 与包装单位换算模板变体回退自动维护与自动建价商品详情、买卖属性自动回填录单时可根据设置自动插入或更新价格严格的保存校验模板商品禁价、多维去重、日期范围、商品与价格列表存在性检查全部由 item_price.py 的validate()链路保证。如需深入排查取价不符合预期的问题建议按顺序检查价格列表是否启用、价格记录是否在有效期内、是否存在客户/供应商专用价覆盖了通用价、数量是否满足包装单位、单据币种与价格列表币种是否一致以及 Stock Settings 中自动建价相关的两个开关auto_insert_price_list_rate_if_missing、update_existing_price_list_rate。赞分享后端企业应用【免费下载链接】erpnextFree and Open Source Enterprise Resource Planning (ERP)项目地址https://gitcode.com/GitHub_Trending/er/erpnext点击查看免费下载相关推荐一次装对用 EIM 完成 ESP-IDF 与工具链安装的四种路径一次装对用 EIM 完成 ESP IDF 与工具链安装的四种路径 你是一个文章写手你负责为开源项目写专业易懂的文章。这篇文章解决ESP IDF 到底怎么装物联网嵌入式Civitai 完整指南如何从找到 AI 模型到一键部署Civitai 完整指南如何从找到 AI 模型到一键部署 Civitai 是一个开源 AI 模型平台聚集了模型、文本反转textual inversion后端前端AI 应用daisyUI价格表完整产品定价与购买指南daisyUI价格表完整产品定价与购买指南 daisyUI作为最受欢迎的免费开源Tailwind CSS组件库提供了丰富的付费产品和模板来帮助开发者快速构建前端UI组件上一篇WarcraftHelper完整指南让经典魔兽争霸3完美适配现代系统下一篇微信小程序二维码生成终极指南5分钟快速上手weapp-qrcode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考