
Grocy 1.14.0 新特性深度解析Recipes 菜谱模块如何打通库存与购物清单【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocyGrocy 1.14.02018-07-15是本项目发展史上具有里程碑意义的一次发布——它首次引入了Recipes菜谱功能将库存管理与居家做饭两个场景打通你可以把一组产品、数量与说明文字组织成一份菜谱随时查看所需原料是否全部在库并把缺失的原料一键加入购物清单。本文以 changelog/27_1.14.0_2018-07-15.md 为骨架结合当前仓库的数据库迁移脚本与 Recipes 相关源码还原该版本的核心改动并补充可直接落地的使用与扩展细节。版本速览1.14.0 带来了什么对照变更日志本次版本的核心内容可归纳为四类类别具体改动核心新功能引入Recipes菜谱把产品、数量与说明组织成菜谱一键查看原料库存匹配情况一键把缺失原料加入购物清单本地化新增挪威语Norwegian翻译由社区贡献者 BlizzWave 提供UI 改进表格列可拖拽重排购物清单页内嵌日历列排序与排序状态被记住侧边栏折叠状态被记住修复日期时间选择器边框激活子菜单时保持父级菜单展开自定义机制自定义 JS/CSS 文件名发生变更详见下文第 5 节其中Recipes 是整个 Grocy 从库存工具走向家庭管理平台的关键一步也是本文展开的重点。Recipes 功能全景从菜谱定义到一键补货数据模型菜谱与菜谱原料行从 migrations/0025.sql 可以看到该功能最初落库时的两张核心表recipes菜谱主表字段为id、name菜谱名、description说明文字、row_created_timestamprecipes_pos菜谱原料行字段为id、recipe_id所属菜谱、product_id对应产品、amount数量、note备注。也就是说1.14.0 的菜谱模型就是菜谱 一个名称 一段描述 若干原料行原料行通过product_id与产品主数据stockoverview 中的产品关联amount即所需数量。这份结构延续至今后续版本在此基础上不断加列增强见第 6 节。库存匹配逻辑recipes_fulfillment 视图菜谱原料是否齐备的判断并非写死在 PHP 里而是由数据库视图完成。同一迁移文件 migrations/0025.sql 中定义了recipes_fulfillment视图其核心计算逻辑为recipe_amount菜谱要求的数量stock_amount当前库存量来自stock_current视图need_fulfilledstock_amount recipe_amount时为 1否则为 0即该原料是否满足需求missing_amountstock_amount - recipe_amount为负时的绝对值即缺口数量amount_on_shopping_list该产品当前在购物清单上的数量含amount_autoadded自动追加部分need_fulfilled_with_shopping_list库存加购物清单合计是否满足需求。配套的recipes_fulfillment_sum视图则对每份菜谱做聚合只要有一行原料未满足整份菜谱的need_fulfilled就为 0并统计missing_products_count缺失原料种类数。这就是一眼看出菜谱是否齐备的底层来源。一键补缺把缺失原料加入购物清单变更日志承诺的把缺失的东西一键放到购物清单上由 RecipesService::AddNotFulfilledProductsToShoppingList 实现其流程为取该菜谱所有解析后的原料行recipes_pos_resolved过滤出属于当前菜谱、且不在excludedProductIds排除列表中的行计算需采购量missing_amount - amount_on_shopping_list已在清单上的部分不再重复加对购物清单上已存在的该产品条目执行累加金额更新否则新建条目记录product_id、amount、qu_id。对外暴露的 API 端点为POST /api/recipes/{recipeId}/add-not-fulfilled-products-to-shoppinglist见 routes.php 与 RecipesApiController.php该接口要求调用者具备PERMISSION_SHOPPINGLIST_ITEMS_ADD权限请求体可携带excludedProductIds数组实现部分排除。消耗菜谱与自产记账除了看缺什么1.14.0 的 Recipes 还支持按菜谱消耗库存。核心实现位于 RecipesService::ConsumeRecipe整个过程包裹在数据库事务中beginTransaction/commit/rollback任一原料消耗失败即整体回滚遍历每行原料当stock_amount 0时调用StockService::ConsumeProduct消耗库存若库存不足stock_amount recipe_amount则只消耗当前实际库存量若菜谱配置了产出产品product_id随后会通过StockService::AddProduct以TRANSACTION_TYPE_SELF_PRODUCTION自产事务类型把成品加回库存并写入菜谱名作为来源备注——这为后续自制果酱自制面包等场景奠定了数据基础。从 routes.php 看其 API 端点为POST /api/recipes/{recipeId}/consume并校验PERMISSION_STOCK_CONSUME权限见 RecipesApiController.php。配套页面与路由1.14.0 同期提供了完整的菜谱 UI当前仓库中对应页面包括GET /recipes菜谱概览页 recipes.blade.php展示菜谱及其原料匹配状态GET /recipe/{recipeId}菜谱编辑页 recipeform.blade.phpGET /recipe/{recipeId}/pos/{recipePosId}原料行编辑页 recipeposform.blade.phpGET /recipessettings菜谱设置页 recipessettings.blade.phpGET /recipe/{recipeId}/grocycode生成菜谱 Grocycode二维码图片实现扫一个码定位一份菜谱见 RecipesController::RecipeGrocycodeImage。路由注册集中在 routes.php页面渲染逻辑见 RecipesController。本次 UI 改进可记忆、可重排的表格体验1.14.0 的 UI 改动集中在交互记忆与表格操作上表格列可重排各列表格的列顺序支持拖拽调整排序状态被记住列排序方向与顺序在页面刷新后依然保留侧边栏折叠状态被记住收起/展开侧边栏后下次访问保持上次状态父级菜单保持展开当激活页面是某个子菜单项时其父级菜单项保持展开避免导航层级跳变购物清单页新增日历变更日志提到作者本人也认为有用的内嵌日历为购物计划提供日期参考修复日期时间选择器边框修正控件外观细节。这些属于前端交互层的打磨对应 public/viewjs 下的前端逻辑核心收益是让高频操作页面库存、购物清单、菜谱用起来更顺手。自定义 CSS/JS 注入机制与文件名变更1.14.0 变更了自定义样式与脚本的文件名。按当前 README.md 的说明该机制的最终形态为当data/custom_css.html文件存在时其内容会被注入到每个页面的/head之前当data/custom_js.html文件存在时其内容会被注入到每个页面的/body之前。页面布局层 default.blade.php 与 default.blade.php 分别通过file_exists(GROCY_DATAPATH . /custom_css.html)与custom_js.html判断并include注入。这意味着无需修改应用本体代码即可在data目录放置自定义 HTML/CSS/JS 片段实现品牌化、埋点或样式覆盖升级 Grocy 时自定义内容也不会丢失。1.14.0 正是把这些文件的命名约定固定下来的版本。多语言支持挪威语加入1.14.0 新增了挪威语翻译由 BlizzWave 贡献。Grocy 的本地化采用 gettext 体系翻译文件以.po形式存放于 localization 目录当前仓库已包含no/语言包内含strings.po、locales.po、permissions.po等后续版本也持续沿用了社区贡献翻译 独立 demo 站点的协作模式。从 1.14.0 到当前版本Recipes 模块的持续演进需要说明的是本文所引用的迁移脚本与源码来自当前仓库属于该功能历经多个版本演进后的形态。从源码结构看1.14.0 之后 Recipes 模块至少经历了以下增强可作为你阅读 services/RecipesService.php 与 migrations 目录时的参考线索原料行支持独立计量单位与换算migrations/0045.sql 为recipes_pos加入qu_id、only_check_single_unit_in_stock仅检查是否有任意数量在库、ingredient_group原料分组、not_check_stock_fulfillment不参与库存匹配检查并通过触发器在新增原料行时自动回填产品的qu_id_stock菜谱嵌套recipes_nestings一份菜谱包含另一份菜谱与产出产品/按份数recipes.product_id、base_servings/desired_servings能力从 RecipesService::CopyRecipe 的复制逻辑可窥一斑用餐计划Meal Plan模块RecipesService中定义了RECIPE_TYPE_MEALPLAN_DAY、RECIPE_TYPE_MEALPLAN_WEEK、RECIPE_TYPE_MEALPLAN_SHADOW等内部菜谱类型services/RecipesService.php对应的日历视图见 mealplan.blade.php其他 API 能力菜谱复制POST /api/recipes/{recipeId}/copy、匹配状态查询GET /api/recipes/{recipeId}/fulfillment、标签打印GET /api/recipes/{recipeId}/printlabel路由见 routes.php。小结Grocy 1.14.0 用一套简洁的菜谱 原料行数据模型撬动了库存查询、缺料补单、消耗记账三个核心流程其设计骨架视图计算匹配、事务化消耗、API 化补单在此后多个版本中持续复用与扩展。对于希望深入理解 Grocy 的读者建议按以下路径继续探索先读 migrations/0025.sql 与 migrations/0045.sql掌握菜谱相关表与视图的演进再读 services/RecipesService.php 与 controllers/Api/RecipesApiController.php理解补单、消耗、复制等操作的服务层实现最后对照 routes.php 与 RecipesController.php 把页面 → 路由 → 服务 → 数据库这条调用链串起来。若想在自建实例上体验只需将 Grocy 部署后访问/recipes创建菜谱并添加原料行再回到库存页补足库存即可直观看到recipes_fulfillment视图中need_fulfilled与missing_amount字段的实时变化。【免费下载链接】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),仅供参考