
grocy 2.6.0 版本全解析库存转移、扫描模式、冷冻/解冻与自制产品四大新功能实战指南【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocy导读grocy 2.6.02020-01-31 发布是 grocy 在库存管理能力上的一次重大升级围绕更快地录入、更精确地管理、更自由地流转三条主线带来了库存转移与库存条目编辑、扫描模式、自制产品、冷冻/解冻四个核心新功能同时覆盖了购物清单、菜谱、膳食计划、日历、API 等多个模块的改进与修复。本文以官方变更日志changelog/55_2.6.0_2020-01-31.md为主体骨架结合 grocy 仓库中的实际源码实现StockService.php、StockApiController.php、RecipesService.php、config-dist.php 等逐项拆解每个功能的使用方法、底层调用链与配置参数帮助读者完整掌握 2.6.0 的能力并顺利升级迁移。一、库存转移与库存条目编辑1.1 功能入口与使用场景2.6.0 之前grocy 中把一批商品从一个位置搬到另一个位置只能通过消费 购入两步曲线完成。2.6.0 引入了真正意义上的库存转移Transfer侧边栏新增Transfer菜单项用于转移产品在库存总览页Stock overview每行产品的 more/context 菜单中提供快捷入口库存总览页头部新增Stock entries按钮每行产品的 more 菜单中也有快捷方式可查看每个产品背后的明细库存条目stock entries并支持直接编辑这些条目。对应的页面路由定义在 routes.php$group-get(/stockentries, [StockController::class, Stockentries]); $group-get(/transfer, [StockController::class, Transfer]); $group-get(/stockentry/{entryId}, [StockController::class, StockEntryEditForm]);视图文件分别为 transfer.blade.php、stockentries.blade.php 与 stockentryform.blade.php。1.2 底层实现TransferProduct 的完整调用链转移操作最终落到StockService::TransferProduct()services/StockService.php其核心逻辑如下前置校验产品必须存在且处于激活状态源位置与目标位置都必须存在否则抛出异常皮重Tare weight限制当前版本对启用皮重处理的产品尚不支持转移源码中会抛出Transferring tare weight enabled products is not yet possible数量校验待转移数量不能大于源位置的当前库存量$amount $productStockAmountAtFromLocation时抛错条目选择默认转移该产品的所有库存条目若传入$specificStockEntryId非default则只转移指定stock_id的特定条目事务日志以uniqid()生成transactionId分别写入一条TRANSACTION_TYPE_TRANSFER_FROM负数量与一条转入记录正数量两条记录共享同一个correlation_id保证可追溯、可撤销。1.3 对应的 REST APIStockApiController.php 暴露了两个转移端点路由见 routes.php方法路由说明POST/stock/products/{productId}/transfer按产品 ID 转移POST/stock/products/by-barcode/{barcode}/transfer按条码转移支持 Grocycode可从条码中解析出特定库存条目请求体示例JSON{ amount: 3, location_id_from: 1, location_id_to: 4, stock_entry_id: optional-specific-stock-entry-id }其中amount、location_id_from、location_id_to为必填缺失时分别抛出An amount is required、A transfer from location is required、A transfer to location is requiredstock_entry_id可选。接口内部对请求体做了GetParsedAndFilteredRequestBody过滤且该操作需要User::PERMISSION_STOCK_TRANSFER权限。与转移配套的还有库存条目编辑能力GET /stock/entry/{entryId}—— 获取单个库存条目PUT /stock/entry/{entryId}—— 编辑库存条目的数量、保质期、位置、价格、开封状态、购入日期、备注等字段对应 StockService.php 的EditStockEntry。提示本功能由社区贡献者 kriddles 完成变更日志中特别致谢。二、扫描模式Scan Mode连续扫码零输入2.1 功能概述扫描模式解决的是批量入库/出库时反复手工输入的痛点开启后只需一个接一个地扫码无需手动录入并伴有音频反馈。在purchase购入与consume消费页面新增开关按钮启用后每次切换/扫描产品后数量自动填充为1如果所有字段都能自动填充例如购入时产品已设置默认保质期交易会自动提交若无法自动填充会显示警告由用户补全缺失信息后提交扫码成功、交易成功/失败时均有音频反馈。2.2 前端实现细节开关与状态显示逻辑位于 public/viewjs/purchase.js点击#scan-mode-button会切换#scan-mode复选框并在按钮上切换btn-success/btn-danger样式、显示 on/off 状态文本。核心的自动提交逻辑ScanModeSubmit()同文件 public/viewjs/purchase.js在单件模式下将数量固定为 1若存在用户设置scan_mode_purchase_enabled见 config-dist.php扫码后触发Grocy.UISound.BarcodeScannerBeep()播放蜂鸣音当字段无法完全自动填充时弹出toastr.warning(Scan mode is on but not all required fields could be populated automatically)提示补全。2.3 用户级开关设置扫描模式是一个按用户记忆的偏好设置默认关闭定义在 config-dist.php 的用户默认设置区DefaultUserSetting(scan_mode_consume_enabled, false); // 消费页扫描模式 DefaultUserSetting(scan_mode_purchase_enabled, false); // 购入页扫描模式用户可以在显示设置中手动开启也可以在购买/消费页通过开关按钮即时切换。音频文件位于 public/uisounds 目录4 个 mp3覆盖扫码蜂鸣、成功与失败提示音。三、自制产品Self Produced Products菜谱自动回填库存3.1 功能说明自制产品功能让按菜谱消耗原料与生产成品入库形成闭环每个菜谱recipe可以关联一个产出产品product该产出产品必须设置默认保质期Default best before date当执行Consume all ingredients needed by this recipe按菜谱消耗全部原料时如果菜谱关联了产出产品系统会按每份按购入数量单位计向库存添加一个单位的产出产品且价格基于菜谱原料成本自动计算。3.2 源码级验证核心实现位于 RecipesService.php 的ConsumeRecipe()开启数据库事务beginTransaction遍历recipes_pos_resolved中的每个原料位调用StockService::ConsumeProduct(...)消耗原料注意原料库存不足时按实际库存量消耗的处理$amount $recipePosition-stock_amount事务提交后读取菜谱的product_id若菜谱关联了产出产品!empty($productId)则调用StockService::AddProduct($productId, $amount, null, StockService::TRANSACTION_TYPE_SELF_PRODUCTION, date(Y-m-d), $recipeResolvedRow-costs_per_serving, ...)入库——注意这里使用了专属交易类型TRANSACTION_TYPE_SELF_PRODUCTION且价格直接取自recipes_resolved视图计算的每份成本costs_per_serving产出数量按desired_servings期望份数计算对于膳食计划影子菜谱RECIPE_TYPE_MEALPLAN_SHADOW则会回溯原始菜谱并按其recipe_servings产出。值得一提的是该功能还推动了膳食计划页直接添加产品的能力见下文第五部分两者配合可以模拟今天做 4 份意面 - 自动消耗原料 - 入库 4 份成品的完整家庭生产流程。四、冷冻/解冻Freeze/Thaw位置联动保质期4.1 功能说明为支持冰箱/冰柜场景2.6.0 引入了位置与保质期的联动机制产品新增选项Default best before days after freezing/thawing冷冻/解冻后的默认保质期天数用于定义冷冻或解冻后保质期如何变化位置location新增选项Is freezer是否为冰柜当产品在冰柜位置与非冰柜位置之间转移时保质期自动按规则调整提供子功能开关FEATURE_FLAG_STOCK_PRODUCT_FREEZING不需要时可关闭默认值为true。该选项在 config-dist.php 中的定义Setting(FEATURE_FLAG_STOCK_PRODUCT_FREEZING, true);4.2 保质期变化的四条规则从 StockService.php 的TransferProduct内部实现可提炼出完整规则场景源位置目标位置新保质期规则冷冻非冰柜is_freezer 0冰柜is_freezer 1若default_best_before_days_after_freezing 0当前日期 N 天若等于-1直接设为2999-12-31视为永久保存解冻冰柜is_freezer 1非冰柜is_freezer 0若default_best_before_days_after_thawing 0当前日期 N 天其余情况——保质期保持不变注意冷冻分支要求default_best_before_days_after_freezing 0 || -1才生效 0表示不调整解冻分支则仅当 0时生效。此外购入入库时StockService.php如果目标位置是冰柜同样会按冷冻规则计算保质期。4.3 与标签打印的联动在上述转移过程中如果启用了标签打印机GROCY_FEATURE_FLAG_LABEL_PRINTER GROCY_LABEL_PRINTER_RUN_SERVER且产品设置了auto_reprint_stock_label 1、保质期确实发生变化系统会自动调用WebhookRunner向标签打印 Webhook POST 新保质期信息含 Grocycode、产品详情、库存条目与due_date实现冻品换标的自动化。4.4 位置表单中的配置是否为冰柜选项位于位置编辑表单 locationform.blade.php勾选后该位置的is_freezer字段即为 1。五、膳食计划改进Meal Plan2.6.0 对膳食计划页做了多项增强每日备注在每一天列头部的添加按钮下拉菜单中可为当天添加备注直接添加产品同样在该下拉菜单中可直接添加产品与自制产品功能配合使用模拟生产某道菜卡路里显示每份的卡路里现在也会显示每日成本与卡路里汇总每一天列头部会显示该日的总成本与总卡路里新的周起始日配置新增MEAL_PLAN_FIRST_DAY_OF_WEEK配置项。5.1 MEAL_PLAN_FIRST_DAY_OF_WEEK 配置详解在 config-dist.php 中定义// Set this if you want to have a different start day for the weekly meal plan view, // leave empty to use CALENDAR_FIRST_DAY_OF_WEEK (see above) // Needs to be a number where Sunday 0, Monday 1 and so forth // Can also be set to -1 to dynamically start the meal plan week on today Setting(MEAL_PLAN_FIRST_DAY_OF_WEEK, );默认值空字符串表示沿用CALENDAR_FIRST_DAY_OF_WEEK因此未配置时行为不变取值范围-1到6的整数其中周日 0、周一 1以此类推校验逻辑见 helpers/ConfigurationValidator.php当值不为空且不是-1..6的数字时会抛出Invalid value for MEAL_PLAN_FIRST_DAY_OF_WEEK后续演进在 4.0.0 中该设置被扩展为可设-1以动态以今天为每周起点见 changelog/70_4.0.0_2023-07-29.md并在 views/mealplan.blade.php 中通过GROCY_MEAL_PLAN_FIRST_DAY_OF_WEEK注入前端。膳食计划页对应视图为 views/mealplan.blade.php前端逻辑在 public/viewjs/mealplan.js。六、其他模块改进速览6.1 购物清单新增紧凑视图Compact view更适合购物途中使用头部新增 Compact view 按钮且移动设备 / 屏幕宽度 768px 时自动启用Filter by status 下拉新增仅显示未完成未划掉条目的过滤选项修复了FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS设为false时某些操作后购物清单显示为空的问题对应 config-dist.php 中的Setting(FEATURE_FLAG_SHOPPINGLIST_MULTIPLE_LISTS, true)。6.2 菜谱按菜谱消费时若某原料缺货但其子产品subproduct有库存现在会改而消耗子产品此前直接无法消费添加/编辑菜谱原料改为对话框dialog方式不再整页跳转由 kriddles 贡献。6.3 日历iCal 日历导出中的膳食计划事件正文现在包含指向对应膳食计划周的链接。6.4 任务修复了编辑已有任务时强制要求填写截止日期的问题。6.5 库存细节修复交易购入/消费等发生后产品卡片product card现在也会即时刷新产品字段卡路里kcal支持小数库存盘点页InventoryNew amount现在预填当前库存量修复启用Allow partial units in stock时盘点页无法输入部分数量的问题修复购入时皮重处理 不同购入/库存单位组合下最小数量校验错误的问题修复FEATURE_FLAG_STOCK_LOCATION_TRACKING设为false时产品卡片加载异常的问题修复Add as barcode to existing product工作流在不切换页面的情况下第二次无法执行的问题。七、API 变更与兼容性说明7.1 新增/增强的端点GET /stock响应现在包含产品对象本身新增product字段由 gsacre 贡献GET /stock/products/{productId}/entries新增查询参数include_sub_products当给定产品是父产品时可一并返回其子产品的库存条目filter_var(..., FILTER_VALIDATE_BOOLEAN)解析见 StockApiController.php。默认false不传时行为不变为库存转移与库存条目编辑新增了对应端点见本文第一部分表格。7.2 修复的 API 问题修复/stock/barcodes/external-lookup/{barcode}路由缺少barcode路由参数导致不可用的问题感谢 Mikhail5555 与 beetle442002修正/stock/volatile端点的响应类型描述。完整的 API 文档可参考仓库根目录的 grocy.openapi.json。八、通用改进与升级注意事项8.1 交互与性能新增用户显示设置保持屏幕常亮可始终或仅在全屏卡片如菜谱展示时默认关闭对应 config-dist.php 的keep_screen_on/keep_screen_on_when_fullscreen_card略微优化了表格加载与搜索性能lwis当前激活的侧边栏菜单项始终保持在可视区域内侧边栏条目按边框分组并适度缩小减少空间浪费调整/移除部分动画并用Animate.css替换 jQuery UI 动画提升响应速度修复表格通用搜索字段误搜索首列多数表格首列只有按钮/菜单的问题修复FEATURE_FLAG_CALENDAR关闭时侧边栏膳食计划菜单不可见的问题lwis集成友好产品编辑页支持GET参数closeAfterCreation保存后自动关闭窗口受浏览器限制仅当窗口由 JavaScript 打开时生效Forceu。8.2 部署与配置修复update.sh的换行符错误DOS 换行改为 Unix内部变更Demo 模式改为通过设置MODE判断取值production/dev/demo/prerelease不再依赖data/demo.txt文件是否存在见 config-dist.php——若你曾用该文件切换 demo 模式升级后需改为在配置中设置MODE配置优先级config-dist.php/data/settingoverrides下的同名 .txt 文件 前缀为GROCY_的环境变量如GROCY_BASE_URL 配置文件中的默认值变更日志新增RSS 订阅。8.3 新增本地化语言2.6.0 新增三种语言翻译匈牙利语Hungarian、巴西葡萄牙语Portuguese (Brazil)、斯洛伐克语Slovak。对应翻译文件已存在于 localization/hu、localization/pt_BR、localization/sk_SK 目录chore_assignment_types、chore_period_types、component_translations、demo_data、locales、permissions、stock_transaction_types、strings、userfield_types 共 9 类 .po 文件。九、升级到 2.6.0 的实践建议升级前备份数据库本版本涉及stock_log新增correlation_id、transaction_id等字段以及 recipes 表新增product_id字段通过迁移脚本自动完成请确认 migrations 目录的 0001~当前版本迁移可正常执行评估新配置项在 config-dist.php 基础上按需调整重点关注FEATURE_FLAG_STOCK_PRODUCT_FREEZING默认 true不需要冷冻联动可设 falseMEAL_PLAN_FIRST_DAY_OF_WEEK需要调整膳食计划周起始日时配置取值 -1~6测试新 API调用/stock/products/{productId}/transfer与PUT /stock/entry/{entryId}前确认操作用户具备PERMISSION_STOCK_TRANSFER/PERMISSION_STOCK_EDIT权限体验扫描模式在购入/消费页开启扫描模式开关配合默认保质期配置实现全自动提交大幅提升批量扫码效率配置冷冻联动为冰柜位置勾选 Is freezer并为相关产品设置default_best_before_days_after_freezing/default_best_before_days_after_thawing-1 表示冷冻后视为永久保存0 表示不调整转移时保质期将自动重算。参考资源变更日志原文changelog/55_2.6.0_2020-01-31.md转移/编辑核心实现services/StockService.php转移/编辑 APIcontrollers/Api/StockApiController.php菜谱消耗与自产services/RecipesService.php路由定义routes.php全部配置项与默认值config-dist.php配置校验helpers/ConfigurationValidator.php前端扫描模式逻辑public/viewjs/purchase.js【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考