Skip to main content Grocy - ERP beyond your fridge
r/grocy icon

r/grocy

5.5K members
8 online

Google Cloud Hosting for Grocy Google Cloud Hosting for Grocy

I installed grocy using the brilliant guidelines by u/Tallyrald earlier this year and it's all been going great... until last month when I got charged for services. It was only £0.11, so I can handle that, and we were warned that Google may change things up in future so it wouldn't always be free.

Did this happen to anyone else in November? Was it just a fluke that my project bounced around various servers last month raising costs? Do I need to change some settings on my compute engine? Answers on a postcard...


🔥 ATOM TOKYO -Shinjuku- | Japan's #1 Dance Club | 4,000 Weekly Guests | Open 10PM


Help with Printing shopping cart Help with Printing shopping cart

Hello there, we have been using Grocy to track our medical supplies in a volunteer fire station for the past 9 months or so and it have worked really good for us, never again braking stock on any of the esencial items, so a really big thanks to the developers.

We make monthly reports on all the items that are in stock, quantities and how much we need to buy. Until now I was doing that manually but just recently discover that the print screen command on the browser in fact makes a spacial format for this... but it shows empty every time, I've tried in both chrome and safari and the result is always the same (see de photo). Any ideas if this is a bug or am I doing something wrong? even the notes I put at the bottom of the page are missing.

Thanks for your help in advance.


Grocery store receipt integrations Grocery store receipt integrations

I was looking into the 4 common stores I use and was wondering if anyone had some integrations setup somehow. One benefit is price tracking which I do not normally use when doing Purchase.

Safeway, Costco, Grocery Outlet, Whole Foods

Each store uses different methods, with Costco using JSON but custom item numbers, Safeway with nice JSON and meta data like sale prices, Whole Foods (Amazon) presenting HTML, and Grocery Outlet being the worst were the items are only on a receipt PDF served from Google (OCR and processing needed).

There is also the challenge of the item names or barcodes not aligning with the DB and getting new items, so I realize the full workflow is not trivial.


iOS Update: Grocy Mobile 3.0 iOS Update: Grocy Mobile 3.0

It took way longer than expected, but here it is: Grocy Mobile 3.0 🎉

This is a 100% free and open source client for accessing Grocy on iOS/iPadOS devices, using a native interface. But first, some screenshots:

Grocy Mobile 3.0 is build on the foundations of the previous versions, but is completely new in design, navigation and technology. It embraces the new Liquid Glass design, bringing a haptic feel to the app. Every view was updated and touched on many parts, to make for a better experience.

One of the biggest changes is the integration of Core Data in the app. This acts as an offline storage for the data, so you can look it up even with no connection (for interaction it is still needed of course). This allows to build new features in the future.

The user logins are now saved in a database as well, allowing for storing multiple accounts (your old login should be converted, so no re-login is needed).

Leveraging the Localizable feature, translations got way easier. So now way more languages are supported (🇺🇸🇩🇪🇫🇷🇳🇱🇵🇱🇨🇿🇮🇹🇨🇳🇵🇹🇧🇷🇳🇴🇩🇰🇭🇺🇹🇼🇫🇮🇯🇵🇺🇦🇬🇷🇬🇧🇪🇪🇮🇱🇰🇷🇷🇴🇸🇰🇸🇮🇹🇷🇱🇹🇮🇳). They are not all 100% yet, but a big step forward.

Last but not least, many bugs and inconsistencies were fixed.

You can get the App here: https://apps.apple.com/us/app/grocy-mobile/id1567803209

If there is a problem with the App, you can create an issue at the Github of the project.



Unlock our limited time offer- $1.99/first month


New product addition error: 502 Bad Gateway New product addition error: 502 Bad Gateway

I am getting desperate. I installed grocy on my unraid server and it worked great. I added all the Masterdata (products, Units, etc.) with no problem. And now, since two days, I cannot add new products anymore. I always get the error message "502 Bad Gateway", and even if I do this locally, with the local IP Adress without cloudflare tunnel. New Users I can add, or Units and Locations. I already deleted the app and re-installed it and copied the data directory. But same result. What is wrong? I don't understand. It took me so much hours to add all the products. Did anyone has the same issue and a solution?



Stock entries takes forever to load Stock entries takes forever to load

Relatively to the rest of the menu navigation, the Stock Entries page took so long to load I didn’t even realize it worked until one day I just left the page on the phone. Apache2 uses 100% CPU for 18 seconds to produce a page with one or more entries. It happens on desktop and iOS. I’m using a Raspberry pi 3 bare metal Linux install.

Should I turn up debug logging? I’m not sure how to do that. Or is storage speed off the SSD an issue? What can I do if anything to speed up this process?



Learn Japanese by speaking with AI characters


Error on installing Grocy in Home Assistant Error on installing Grocy in Home Assistant

I added Grocy as Add-on in Home Assistant. I also added it in HACS and now want to add it as an integration. But when I fill in the fields for Grocy API URL, Grocy API and Port I always get "Something went wrong". I tried multiple things but nothing works. I've set the port in the add-on configuration to 9192.

  • hostname from the add-on (with and without http:// and https://

  • link when I go to browser in Home Assistant

  • my Home Assistant link

  • different ports in the integration setup (9192, 80, 443)

Further I followed the instructions EXACTLY. What am I doing wrong? I think the problem is that I don't know for sure where to find my Grocy-API-URL.


Is Grocy available for Linux? If not, what alternative software to use? Is Grocy available for Linux? If not, what alternative software to use?

Hello everyone, first post here (just find out about this incredible tool called Grocy).

Grocy and Linux.

I know I have three options to use it right now:

  1. Grocy for Docker (through browser), via LinuxServer (Docker) https://hub.docker.com/r/linuxserver/grocy

  2. using a compatibility layer (Wine, Bottles, WInBoat) and install Grocy DESKTOP for Widows. https://github.com/grocy/grocy-desktop/releases/tag/v2.14.0

  3. using another program (native Linux or via Docker):

--

Other Reference URLs:

--

I would prefer to use something for desktop at first and only then using as real server (eg. using a VPS and accessing it from other devices).

What about dependencies' Which one should check I have installed?

What do you suggest (as a user and as a developer)? What is your experience with Grocy or other food-management software?



need_fulfilled_with_shopping_list is 1, even with empty inventory and shopping list need_fulfilled_with_shopping_list is 1, even with empty inventory and shopping list

Hey r/grocy!

I stumbled upon grocy a week or two ago and have really been enjoying it so far. All in all, I'm extremely happy with my setup so far, but I'm really confused with just one feature--

  • When all missing recipe items have “Only check if any amount is in stock” enabled, even when stock and shopping list are empty, the button to add a recipe's missing ingredients to the shopping list (recipe-shopping-list btn) is disabled, and need_fulfilled_with_shopping_list is 1.

  • Replicable on the demo by

    • removing all stock / shopping list items for a recipe

    • enabling “Only check if any amount is in stock” for each ingredient

Going through the migrations, it appears that the logic is here:

File: grocy/migrations/0160.sql (https://github.com/grocy/grocy/blob/68b4abfac42f80523d9aba22b5a5efd5a5d62211/migrations/0160.sql#L13)

CASE 
    WHEN ROUND(
        IFNULL(sc.amount_aggregated, 0) + 
        (
            CASE 
                WHEN r.not_check_shoppinglist = 1 THEN 0 
                ELSE IFNULL(sl.amount, 0) 
            END * p.qu_factor_purchase_to_stock
        ), 
        2
    ) >= ROUND(
        CASE 
            WHEN rp.only_check_single_unit_in_stock = 1 THEN 0.00000001
            ELSE 
                CASE 
                    WHEN rnr.recipe_id = rnr.includes_recipe_id THEN 
                        rp.amount * (r.desired_servings * 1.0 / r.base_servings * 1.0)
                    ELSE 
                        rp.amount * (r.desired_servings * 1.0 / r.base_servings * 1.0) * 
                        (rnr.includes_servings * 1.0 / rnrr.base_servings * 1.0)
                END
        END, 
        2
    ) 
    THEN 1 
    ELSE 0 
END AS need_fulfilled_with_shopping_list

With this, the thought is that when rp.only_check_single_unit_in_stock = 1, ROUND(0.00000001, 2) evaluates to 0, and even with an empty shopping list and inventory, a recipe will return need_fulfilled_with_shopping_list = 1 (0 >= 0).

Any ideas why this is the case?


A new, more powerful QuickBooks on the Intuit Platform saves you time with agentic AI. Sign Up Today!

Outdo the way you do business with Intuit Quickbooks

media poster


Any way to insert prices into Grocy without logging pucharse? Any way to insert prices into Grocy without logging pucharse?

I have access to live prices at stores I usually do my shopping at, is there any existing way to add price information without modifying stock? I'd imagined that I will be able to just run a cron job to fetch price from store API and update it in Grocy. I'd like to have my shopping list price show most accurate estimates possible and maybe code a thing that will try to split my lists into store specific sections based on where it's the cheapest.


Is it possible to create a custom user field that only applies to a specific product type instead of all products? Is it possible to create a custom user field that only applies to a specific product type instead of all products?

It doesn’t seem to be possible, but I just wanted to check if I’m missing something.

Suppose I want to track wine in my cellar. I can create a product category called “Wine” and individual products to represent different vintages. However, I’d like to track the vintage year in a separate field that only applies to wine products.

Is there any way to create a custom field that’s specific to a product category (like “Wine”) rather than being global for all products?

I understand I can create an entirely custom entity, but then I lose product functionality that is built in...



Using meal plan to add items to shopping list, how to add cumulative missing amounts? Using meal plan to add items to shopping list, how to add cumulative missing amounts?

Hi,

I see that this issue gets posted about a lot:

Feature Request: Cumulative missing amounts (from multiple recipes) on shopping list #840

I have some rudimentary programming skills and am considering writing a sql query that will do what I want, but I want to make sure there isn't already a simpler work around that I'm just missing.

What I'd like to be able to do:

  1. Use the meal planner on the web app to make a meal plan for a set time period, e.g. a week.

  2. Inventory my kitchen then automatically generate a shopping list from the meal plan with a click of a button, without having to manually sum products from different recipes or change any minimum stock amounts.

  3. Add additional items to shopping list using "Add products that are below defined min. stock amount" from the stock actions drop down menu on the shopping this. This will add items like ketchup that I want to always keep stocked above a certain level, even if that item isn't on that weeks meal plan.

For step 2, I can't use the "Put missing products on shopping list" button on the header of the meal plan page because the missing amounts are checked on a per recipe level. For example if I have 12 eggs in stock, 1 recipe on the meal plan that calls for 8 eggs and another recipe on the meal plan that calls for 10 eggs, no eggs will be added to the shopping list because neither recipe has more than 12 eggs. In order to make sure I have enough eggs for everything on the meal plan, I have to manually sum the eggs from both recipes.

I can see that the software is functioning as intended and that this isn't a bug, but the software would be much more useful for me if I I didn't have to manually sum the products from all the recipes being used in a week.

I've tried the "Do not check against the shopping list when adding missing items to it" on the edit recipe page, but it doesn't change the behavior, nor would I expect it to. The problem is the per recipe checking, not whether the shopping list is being checked first.

I've also tried the "Disable stock fulfillment checking for this ingredient" checkbox on the edit recipe ingredient page of both recipes, and I've tried the "Disable stock fulfillment checking for this ingredient" on the edit product page, and neither of these changed the behavior.

Before I try to write a sql query, is there a simpler way to do this that I'm just missing? I have read feature request #840 and some of its duplicates, as well as some of the other posts on reddit, and I've not found what I'm looking for. Sorry if I just missed it.


The #1 most played Idler game on Steam


Check out Restoqit, a companion app for Grocy Check out Restoqit, a companion app for Grocy

Hey everyone, I wanted to share a project I'm using with my Grocy setup. It's called Restoqit, and it's a simple, self-hosted app that pulls in your Grocy data using URL and API key.

It's a great way to get a quick overview of what's expiring, what's low on stock, and what's on your grocery list. It's designed to make it super easy to see what you need to buy without having to dig through Grocy's menus.

If you're looking for a simple companion app, you can find it here:

https://github.com/KenWeTech/Restoqit


[Release] Grocy Shopping List Bridge for Obsidian [Release] Grocy Shopping List Bridge for Obsidian
[Release] Grocy Shopping List Bridge

I just finished building my very first Obsidian plugin, and I’m excited to share it here.

It connects Obsidian with Grocy - a self-hosted grocery and household management system (think: open-source grocery list, meal planner, inventory tracker).

If you keep recipes in your vault, this plugin lets you send the ingredients directly into your Grocy shopping list with a single click.

Features:

  • Parses ## Ingredients sections from your notes automatically
    → includes nested subheadings like ### Sauce, #### Marinade
    → stops before the next top-level heading (e.g. ## Directions)

  • Smart ingredient normalization:

    • 1 large egg → eggs

    • 3 cloves garlic (minced) → garlic

  • Fuzzy product matching against Grocy’s product database

  • Configurable auto-matching thresholds and fallback options

  • Free-text items when no product is found

  • Manual overrides with inline annotations:

    • (grocy_id: 42)

    • (grocy: jalapeño)

    • <!-- grocy_id: 42 --> ← stays hidden if you use Recipe View

  • Ribbon button + command palette support

  • Wife-Approved! My wife loves the simplicity of making shopping lists now.

The plugin is available at my Gitea instance.

This is my first plugin for Obsidian, so I’d really appreciate any feedback or ideas for improvements. Hope this helps anyone else who’s using Grocy to keep their kitchen and shopping organized!

31 票の賛成票 10 件のコメント

Export Data from Android app Export Data from Android app

Hi,

the SD Card of my Raspi on which my Grocy server was installed( Docker Image on Kodi, on Open Elec ) is broken and the last Backup of the grocy db i found is from December 2024. I know - no backup, no pity - but i still have all the Data in my grocy android app ( 3.8.1). Is there a possibility to export the data stored in the app? or sync it with a new grocy server and move it to there?
Thanks for your help


Paperless-ngx receipts automated import into Grocy possible development... Paperless-ngx receipts automated import into Grocy possible development...

I'm still early in my dev for this but what would you guys think of an automated Paperless-ngx to Grocy import? I'm trying to develop one for the past two weeks and I have working prototype but its not ready at all for use. However, before I continue and consider dropping it out to others to test, I'd like some feedback first. So what do you think? This is what it does so far to give you a bit of an idea:

  • Per receipt line item import into Grocy stock with receipt pricing and store info.

  • Ability to recognise non-grocery items

  • Mapping of Grocy products to abbreviated receipt line items via a log and mapping file. (a bit of extra manual work in the beginning)

  • Ability to do trial runs using environment flags to avoid incorrect imports in the beginning or in the event of new store receipt items (still needs more work here to deal with rejected items properly)

Again, your thoughts would be greatly appreciated.


Go global with a Dubai business, no relocation required.


grocy in Windows XAMPP grocy in Windows XAMPP

Hi all,

i am trying to install grocy on a XAMPP Apache Server on my Windows 10 machine. Unfortunatly i always get to the 404-not found page when trying to enter grocy.

I just want to run the server on a pc and then connect the android app via wifi with it, no need for a domain or internet access.

i followed the install guide, copied config-dist.php to config.php, experimented with URL-Rewritting on true/false (ChatGPT thought it could be the problem), emptied the viewcache-folder (also one of ChatGPTs ideas)

but no matter if i try to reach http://localhost/grocy/public or directly http://localhost/grocy/public/index.php it always ends up in 404

I skipped the website-root step since i didn't found how to do it in xampp, but to my understanding it should just have something to do if you need a subdomain to lead directly to grocy

can someone help me please?


Moving the installation from Docker to Proxmox-LXC: ERR_TOO_MANY_REDIRECTS Moving the installation from Docker to Proxmox-LXC: ERR_TOO_MANY_REDIRECTS

Hello everyone,

Situation: Docker is running on LXC in Proxmox (whether that's a good idea or not is another matter 😉). Among other things, Grocy is running inside it. Now I wanted to extract Grocy from the Docker-LXC and run it in a standalone LXC using the helper scripts from https://community-scripts.github.io/ProxmoxVE/scripts?id=grocy.

So far, so good. The installation went well and I was able to log into the new Grocy-LXC using 'admin':'admin'.

Then I copied the data folder from the Docker-LXC and overwrote it in the new Grocy-LXC. After that, I cleared the data/viewcache folder (it’s still empty), and when I access the IP of the Grocy-LXC, I get the error message: ERR_TOO_MANY_REDIRECTS

I didn’t see any URLs or similar in the grocy.db. What am I doing wrong?

Config.php

// When running grocy in a subdirectory, this should be set to the relative path, otherwise empty

// It needs to be set to the part (of the URL) AFTER the document root,

// if URL rewriting is disabled, including index.php

// Example with URL Rewriting support:

// Root URL = https://example.com/grocy

// => BASE_PATH = /grocy

// Example without URL Rewriting support:

// Root URL = https://example.com/grocy/public/index.php/

// => BASE_PATH = /grocy/public/index.php

Setting('BASE_PATH', '');

// The base URL of your installation,

// should be just "/" when running directly under the root of a (sub)domain

// or for example "https://example.com/grocy" when using a subdirectory

Setting('BASE_URL', '/');

Thanks for your help!

Best regards,
Syl


Automatic consumption rates Automatic consumption rates

Hi! My boss has put me onto this app and I have had a little look through it, but thought it would be best to ask here as I see the community seems pretty active. We are looking for something that can track my bosses medical usage; I am part of his care team, and we have a very large inventory of medical supplies. We use a lot of medication every day, so manually consuming the items through the app would just take too long, so I was wondering if there is any feature where the items can have a consumption rate added; some items are consumed 5-10 times daily, others daily, others weekly and so on. I have had a look for an app/ program that tracks stock and has automated consumption, but cannot find anything at this point. If anyone has had any similar scenarios solved through Grocy or any ideas that would be much appreciated! Thanks!



Free admission until midnight🔥 The best nightclub in Shinjuku🔥 5,000 guests every week! Dance, drink, and celebrate in a luxurious setting!



iOS App - is there only one? iOS App - is there only one?

Hello everyone,

a few days ago I installed grocy on my home assistant OS and the iOS app on my iPhone. The iOS app is outdated, does not support my server version, is buggy and does not have a useful waf.

I just installed the android app on a pixel phone which is a work testing device. And wow! This is how I imagine a grocy app! And now my question is: Is there another grocy iOS app or is there only the one which is mentioned at https://grocy.info/addons ? I read somethin about PantryParty but it seems not to be supported (or availalabe) anymore.

Thank you for your help


Error 400: no such column: "no_own_stock=1 products can't be added to stock" - should this be a string literal in single-quotes?` Error 400: no such column: "no_own_stock=1 products can't be added to stock" - should this be a string literal in single-quotes?`

So first of all, fantastic work with grocy. It's really been helpful with the chores and the shopping list in our life.

I've started using it not a long time ago (maybe some months). Currently running version: 4.5.0

Version 	4.5.0
Released on 	2025-03-28 vor 5 Monaten
PHP Version 	8.3.23
SQLite Version 	3.50.2
Database Version 	253
OS 	FreeBSD 13.5-RELEASE-p1 FreeBSD 13.5-RELEASE-p1 releng/13.5-n259164-784f05cb815f HOSTPOINT amd64
Client 	Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0

I'm also using https://github.com/patzly/grocy-android for more convenient use on my phone.

However, grocy started acting weird not a long time ago. First I'd thought it might be the app not working properly, since I'm using a "too new" version of grocy which is currently not supported by the app. (AFAIK up and until v4.3.0 is supported in the app)

However, things got weird when I started up the web-UI in my Browser on my PC. When trying to do add items on my shopping list to stock after buying them, grocy also acted weird.

With no visible error available I opened up DevTools and the Network-Tab to investigate a little more. And there it was: A Code 400, after pressing "Submit" with the message:

error_message	`SQLSTATE[HY000]: General error: 1 no such column: "no_own_stock=1 products can't be added to stock" - should this be a string literal in single-quotes?`

So before opening this post, I've looked through some available GitHub issues and in some of them which had a similar error than mine, it was told to execute the Database-Migration by clicking on the Logo in the upper left corner. So I did that, however, nothing changed.

And to see if a possible update has fixed the issue, I've ran the ./update.sh just today evening. Unfortunately, this also didn't help.

I'm also not able to restart the apache-server or the complete FreeBSD host, since grocy is running on a managed hosting of a web hosting-provider.

I would be glad if I could get some assistance in this case and maybe a theory on how this error could've possibly occurred, since I'm pretty sure, that after the initial setup and configuration, I didn't change anything on the servers end.




Round here,all my dawgs stay drippin‘ Neck got Jade piece swagin’ Lai Tsai


Diverging colors between plot markers and plot lines Diverging colors between plot markers and plot lines

Is this by design that the plot markers do not have the same color as the plot lines ?

In my instance and also in the official demo instance it is the case. See attached screenshot. DemoSupermarket2 uses a light green for the plot line, but something blueish for the markers, as visible in the mouse hint. And DemoSupermarket1 has a lavender plot line with greenish markers.

This confuses me a lot when the mouse hint pops up ...


Open Food Facts in the Product Tab - Custom JS Open Food Facts in the Product Tab - Custom JS

So, I saw this issue come through yesterday, and realized that it was related to the issue I had a while back, so I decided to take a stab at it before my ChatGPT Plus membership expires. :D

The Issue:

When using the "Purchase" tab to create a new product, they Open Food Facts lookup plugin returns data on a barcode. But it creates and saves a product and then opens it for editing, instead of just filling in the data and waiting for you to save it. So what's the issue with that? Well, because it defaults to the Quantity Unit to either your default or Piece if there is no default.

Why is this an issue? Normally, it wouldn't be. A default defaulting to the default is exactly what a default should do! But because it saves it before letting you edit it, that means you either need to change your default before you look up your item each time, e.g., do all your cans at once, then all your cartons, etc; or you need to create a conversion after the fact. My ADHD self kept forgetting to do that, and having to go in after the fact and make conversions drives me batty. I am fully aware this is a me issue.

Also, I tend to want to make products and then stock products in a separate work flow as well. So...

The solution:

A bit of custom JS added to custom_js.html that adds a Open Food Facts lookup button to the Products page. It brings in the data:

  • Names the product

  • Adds ingredients to the description

  • Adds the image URL to the description (because browser side image/file handling is rough, but I'm open to ideas!)

  • Tries to guess the default location (customizable array)

  • Adds the brand to the custom userfield Brand

  • Adds the Open Food Facts categories to the custom userfield OFFcategories

Is the code a hot mess? I dunno, ChatGPT 5 wrote it and the internet is losing it's collective mind about the model switch. So maybe? Does it work like 98% of the time for me? Yes. So, good enough, although if anyone has any cool ideas to improve it, I would love to hear them!

The Code:

<script>
document.addEventListener('DOMContentLoaded', () => {
  // ---- run ONLY on .../product/new (universal, resilient to double/trailing slashes) ----
  const isNewProductPage = () => {
    const path = location.pathname.toLowerCase().replace(/\/+/g, '/'); // collapse //
    const clean = path !== '/' ? path.replace(/\/$/, '') : path;       // trim trailing /
    const parts = clean.split('/').filter(Boolean);
    return parts.length >= 2 &&
           parts[parts.length - 2] === 'product' &&
           parts[parts.length - 1] === 'new';
  };
  if (!isNewProductPage()) return;

  const form = document.querySelector('form#product-form');
  const nameInput = form?.querySelector('input#name.form-control');
  if (!form || !nameInput) return;

  // ---------- tiny helpers ----------
  const $ = (sel, root = form) => root.querySelector(sel);
  const fire = (el, type) => el && el.dispatchEvent(new Event(type, { bubbles: true }));
  const setValue = (el, val) => {
    if (!el || val == null) return;
    el.value = String(val);
    fire(el, 'input'); fire(el, 'change');
  };
  const waitForElm = (selector, root = form) => new Promise(resolve => {
    const found = (root || document).querySelector(selector);
    if (found) return resolve(found);
    const obs = new MutationObserver(() => {
      const el = (root || document).querySelector(selector);
      if (el) { obs.disconnect(); resolve(el); }
    });
    obs.observe(root || document, { childList: true, subtree: true });
  });
  const escapeHtml = s => String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
  const toParagraphHtml = plain =>
    '<p>' + escapeHtml(plain).replace(/\n{2,}/g, '</p><p>').replace(/\n/g, '<br>') + '</p>';
  const setUF = async (name, value) => {
    if (!value) return;
    const el = await waitForElm(`#userfields-form [data-userfield-name="${CSS.escape(name)}"].userfield-input`, form);
    setValue(el, value);
  };

  // ---------- description ----------
  const setDescription = async (appendText) => {
    if (!appendText) return;
    const ta = await waitForElm('#description', form);
    const group = ta.closest('.form-group') || form;
    const wys = group.querySelector('.note-editable[contenteditable="true"]');

    const existingPlain = (wys ? wys.innerText : (ta.value || '')).trim();
    const newPlain = existingPlain ? `${existingPlain}\n\n${appendText}` : appendText;

    setValue(ta, newPlain);
    if (wys) {
      wys.innerHTML = toParagraphHtml(newPlain);
      fire(wys, 'input'); fire(wys, 'change');
    }
  };

  // ---------- location guesser ----------
  const RULES = [
    { loc: 'Freezer',      keys: ['frozen', 'ice cream', 'frozen pizza', 'frozen vegetables', 'freezer'] },
    { loc: 'Fridge',       keys: ['refrigerated', 'dairy', 'milk', 'cheese', 'yogurt', 'sour cream', 'butter', 'eggs', 'deli', 'juice', 'kimchi', 'sauerkraut'] },
    { loc: 'Pantry',       keys: ['canned', 'cereal', 'pasta', 'rice', 'beans', 'shelf stable', 'baking', 'soup', 'snacks', 'condiments', 'sauce', 'broth', 'oil'] },
    { loc: 'Spices',       keys: ['spice', 'seasoning', 'herb', 'spices'] },
    { loc: 'Under Sink',   keys: ['cleaner', 'detergent', 'dish soap', 'bleach', 'disinfectant', 'surface cleaner'] },
    { loc: 'Laundry Room', keys: ['laundry', 'fabric softener', 'stain remover', 'dryer sheets'] },
    { loc: 'Garage',       keys: ['charcoal', 'propane', 'bulk pack', 'paper towels', 'storage', 'water case'] },
  ].map(r => ({
    ...r,
    rx: new RegExp(r.keys.map(k => k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'), 'i')
  }));

  const guessLocation = (p, name) => {
    const big = [
      p?.categories, p?.categories_tags?.join(', '),
      p?.labels, p?.labels_tags?.join(', '),
      p?.packaging, p?.packaging_tags?.join(', '),
      p?.stores, p?.brands, name
    ].filter(Boolean).join(' | ');
    for (const r of RULES) if (r.rx.test(big)) return r.loc;
    return '';
  };

  // ---------- cached getLocationSelect ----------
  let cachedLocationSelect;
  const getLocationSelect = async () => {
    if (cachedLocationSelect && document.body.contains(cachedLocationSelect)) {
      return cachedLocationSelect; // still in DOM
    }
    // 1) direct ids/names
    const direct = $('#location_id') || $('select[name="location_id"]');
    if (direct) { cachedLocationSelect = direct; return direct; }

    // 2) label "Default location"
    const lbl = Array.from(form.querySelectorAll('label'))
      .find(l => /default\s*location/i.test(l.textContent || ''));
    if (lbl?.htmlFor) {
      const s = $('#' + CSS.escape(lbl.htmlFor));
      if (s?.tagName === 'SELECT') { cachedLocationSelect = s; return s; }
    }

    // 3) any select whose options include known locations
    const known = /^(Freezer|Fridge|Garage|Laundry Room|Pantry|Spices|Under Sink)$/i;
    const fallback = Array.from(form.querySelectorAll('select'))
      .find(s => Array.from(s.options).some(o => known.test(o.text.trim())));
    if (fallback) cachedLocationSelect = fallback;
    return fallback || null;
  };

  const selectLocationByText = async (text) => {
    if (!text) return;
    const sel = await getLocationSelect();
    if (!sel) return;
    const want = text.toLowerCase();
    const opt = Array.from(sel.options).find(o => o.text.trim().toLowerCase() === want);
    if (opt) { sel.value = opt.value; fire(sel, 'change'); }
  };

  // ---------- button ----------
  const makeButton = () => {
    const b = document.createElement('button');
    b.type = 'button';
    b.className = 'btn btn-outline-secondary btn-sm';
    b.style.marginLeft = '0.75rem';
    b.textContent = 'Lookup on Open Food Facts';
    return b;
  };

  const heading = document.querySelector('#page-content h2.title') || document.querySelector('h2.title');
  const btn = makeButton();
  if (heading) heading.insertAdjacentElement('afterend', btn);
  else (nameInput.closest('.form-group')?.querySelector('label[for="name"]') ?? nameInput).insertAdjacentElement('afterend', btn);

  // ---------- OFF -> form ----------
  const applyOFFToForm = async (p) => {
    const name = p.product_name || p.product_name_en || p.generic_name || p.generic_name_en || '';
    setValue($('#name'), (name || '').trim());

    const brand = (p.brands || '').split(',').map(s => s.trim()).filter(Boolean)[0] || '';
    await setUF('Brand', brand);

    const ingredients =
      p.ingredients_text || p.ingredients_text_en ||
      (Array.isArray(p.ingredients) ? p.ingredients.map(i => i.text || i.id || '').filter(Boolean).join(', ') : '') || '';
    await setDescription(ingredients ? `Ingredients: ${ingredients}` : '');

    const img = p.image_front_url || p.image_url;
    await setDescription(img ? `Image (OFF): ${img}` : '');

    // categories -> OFFcategories (strip "en:" etc)
    const categoriesList = Array.isArray(p.categories_tags)
      ? p.categories_tags.map(t => t.replace(/^[a-z]{2}:/i, '')).join(', ')
      : (p.categories || '');
    await setUF('OFFcategories', categoriesList);

    // guess location
    const guessed = guessLocation(p, name);
    await selectLocationByText(guessed);

    // no alert popup
  };

  // ---------- click ----------
  btn.addEventListener('click', async () => {
    const code = (prompt('Scan or enter a barcode to look up on Open Food Facts:') || '').trim();
    if (!code) return;

    btn.disabled = true;
    const txt = btn.textContent;
    btn.textContent = 'Looking up…';
    try {
      const r = await fetch(`https://world.openfoodfacts.net/api/v2/product/${encodeURIComponent(code)}`);
      if (!r.ok) throw new Error(`HTTP ${r.status}`);
      const j = await r.json();
      if (j?.product) await applyOFFToForm(j.product);
      else alert('No product found on Open Food Facts for that barcode.');
    } catch (e) {
      console.error(e);
      alert('Open Food Facts lookup failed. Try again or check the barcode.');
    } finally {
      btn.disabled = false;
      btn.textContent = txt;
    }
  });
});
</script>

I'm developing an Object Spreadsheet Importer - Any interest? I'm developing an Object Spreadsheet Importer - Any interest?

Hello all, I am working on developing an object importer using Gemini and Grocy's API. I seem to remember this coming up in the community before, especially for new users, and wanted to gauge general interest to see if anyone would want a public release. I'm planning on having options to import:

  • Locations

  • Product Groups

  • Products

  • Quantity Units

Essentially you'll have the Field names in Grocy translating to JSON. If there's enough interest I could add on other objects as well. And it runs in Docker! Curious to hear thoughts or if anyone has additional ideas for what to add to this.

Here's a screenshot of what I have so far.


Is there something wrong in my setup or are these common bugs? Is there something wrong in my setup or are these common bugs?

I set up Grocy running on a Raspberry Pi 5 running Home Asssistant using the Grocy plugin. I followed all the setup steps and everything seemed fine.

However, I am running into several issues all the time that make it rather hard to use:

  • Every time I try to login to connect the Grocy app (Android) to my server it throws an "Invalid Grocy instance" error, but pressing try again will always fix it the second time around (this only needs to be done once given the long-access tokens, but I have ran into it several times now trying to debug these issues.

  • Any time I edit a product in the app and I try to access its details again it shows "An error has occurred" with the following message:

Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject

org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
at org.json.JSON.typeMismatch(JSON.java:112)
at org.json.JSONObject.<init>(JSONObject.java:172)
at org.json.JSONObject.<init>(JSONObject.java:185)
at xyz.zedler.patrick.grocy.helper.DownloadHelper$$ExternalSyntheticLambda8.onResponse(R8$$SyntheticClass:10)
at xyz.zedler.patrick.grocy.model.Location$3$$ExternalSyntheticLambda1.onResponse(R8$$SyntheticClass:1)
at xyz.zedler.patrick.grocy.web.CustomStringRequest$$ExternalSyntheticLambda0.onResponse(R8$$SyntheticClass:17)
at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:11)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:27)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:257)
at android.os.Looper.loop(Looper.java:342)
at android.app.ActivityThread.main(ActivityThread.java:9634)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:619)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
  • When I try to add a new location in the web UI it does nothing unless I specifically right-click the add button and open the link in a new tab.

  • If I try to edit a product via the web UI it never works and instead get this:

"error_message":"Method not allowed. Must be one of: OPTIONS","error_details":{"stack_trace":"#0 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/Middleware\/RoutingMiddleware.php(44): Slim\\Middleware\\RoutingMiddleware->performRouting()\n#1 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(129): Slim\\Middleware\\RoutingMiddleware->process()\n#2 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/Middleware\/ErrorMiddleware.php(77): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()\n#3 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(129): Slim\\Middleware\\ErrorMiddleware->process()\n#4 \/var\/www\/grocy\/middleware\/CorsMiddleware.php(27): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()\n#5 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(280): Grocy\\Middleware\\CorsMiddleware->__invoke()\n#6 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(73): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()\n#7 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/App.php(209): Slim\\MiddlewareDispatcher->handle()\n#8 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/App.php(193): Slim\\App->handle()\n#9 \/var\/www\/grocy\/app.php(133): Slim\\App->run()\n#10 \/var\/www\/grocy\/public\/index.php(45): require_once('...')\n#11 {main}","file":"\/var\/www\/grocy\/packages\/slim\/slim\/Slim\/Middleware\/RoutingMiddleware.php","line":79}}"error_message":"Method not allowed. Must be one of: OPTIONS","error_details":{"stack_trace":"#0 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/Middleware\/RoutingMiddleware.php(44): Slim\\Middleware\\RoutingMiddleware->performRouting()\n#1 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(129): Slim\\Middleware\\RoutingMiddleware->process()\n#2 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/Middleware\/ErrorMiddleware.php(77): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()\n#3 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(129): Slim\\Middleware\\ErrorMiddleware->process()\n#4 \/var\/www\/grocy\/middleware\/CorsMiddleware.php(27): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()\n#5 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(280): Grocy\\Middleware\\CorsMiddleware->__invoke()\n#6 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/MiddlewareDispatcher.php(73): Psr\\Http\\Server\\RequestHandlerInterface@anonymous->handle()\n#7 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/App.php(209): Slim\\MiddlewareDispatcher->handle()\n#8 \/var\/www\/grocy\/packages\/slim\/slim\/Slim\/App.php(193): Slim\\App->handle()\n#9 \/var\/www\/grocy\/app.php(133): Slim\\App->run()\n#10 \/var\/www\/grocy\/public\/index.php(45): require_once('...')\n#11 {main}","file":"\/var\/www\/grocy\/packages\/slim\/slim\/Slim\/Middleware\/RoutingMiddleware.php","line":79}}
  • Images I add to products are not displaying, neither on the web UI or the app.

  • When I change views the app regularly reports "offline" at the top randomly (disappears after switching views again usually).

  • The app log seems to report this error a lot:

MainActivity: createWebSocketClient: onException: homeassistant.local
  • The app quite regularly crashes as well.

Are all these issues common? I really cannot find much on them to be honest. It does seem to be that trying to access grocy directly (so using http://<raspberry-pi-ip>:<grocy-port>) seems to work a lot better then trying it through Home Assistant (which contains Ingress)


Import recipes from grocy to mealie Import recipes from grocy to mealie

Hi all,

I recently started testing mealie for recipe management, since grocy did not really meet the WAF in my case.

I am a lazy guy and did not want to migrate all recipes manually to mealie, so I wrote a short (quick & dirty) script to import all my recipes to mealie. You will have to do some cleanup after the import, but probably you're faster this way than copy & pasting everything.

you will find the script here, it's packed with a small dockerfile to run it in docker.
https://github.com/heig/Grocy-to-Mealie

Maybe somebody else will find this useful :)

Have a nice sunday everybody!


Metal 3D Printing Service – Fast,Precise,Affordable.


help with recipe-buddy for grocy desktop for a not so tech savy person help with recipe-buddy for grocy desktop for a not so tech savy person

Just to start off i am loving grocy so far.
I don't know enough to be able to host grocy myself so when i seen the desktop version i downloaded it and got it working how i want.

I have noticed that there is an add-on called recipe-buddy which looks like what i need, but the problem is i have no idea how to install it and get it working with the desktop version.

If someone was able to simplify the process for a not so tech savy person that would be great



Grocy do not start after power outage Grocy do not start after power outage

Hello

I've been having a problem with Grocy since yesterday.

It no longer starts automatically when the computer is restarted. Everything was working fine until now. But we had a power outage during the night and it hasn't worked since. I can access the computer, which I set up with the latest version of Ubuntu before installing Grocy, without any problems using Real VNC. The IP address hasn't changed either.

When I look in the folders, I can't find any reference to Grocy or Docker.

Does anyone have any advice, or do I need to reinstall Grocy?

Many thanks in advance from Sweden.

Jörg


Display default shop on shopping list? Display default shop on shopping list?

Hi I'm looking for a way to show the default store as column on the shopping list.
It would obviously be very convenient to sort or filter the list by the store you are currently at.

I know I can do it through the use of custom Userfields but those become separate entries when creating and managing products.
So far I haven't seen the default store be used anywhere, which I don't really understand since the shopping list seems like the perfect place for it.

I would really appreciate any help!


Some initial thoughts and questions, after initial Grocy setup Some initial thoughts and questions, after initial Grocy setup

Hi all,

so we're a family of four with a badly overstocked kitchen and second freezers and fridges in the basement, and in bad need of some kind of management to avoid buying the twelfth packet of spicy walnuts just because they were on special offer. Some previously tried "Food / inventory management" apps didn't quite cut it or were not multiuser capable.

Enter Grocy :-)

First things first: Setting up via the linuxserver Docker image was a breeze. I got it running within 10 minutes, including (!) local HTTPS using a forwarding configuration with Caddyserver on my home Raspberry Pi.
Thank you for providing good documentation and setup instructions and making this work! :-)

But I do have some questions, improvement ideas, and I also think I found some bugs - but some may well be misunderstandings on my part. I'd appreciate any comments. Thanks!

For the record, I'm running Grocy 4.5.0 of 2025-03-28 on PHP 8.3.19, SQLite 3.48.0, DB version 253, on a Linux ARM 64bit architecture (Raspi 4b) as a Docker image. Clients are Android phones and Linux / Mac desktops with Firefox.

So here are my questions and ideas.

  1. I use the built-in barcode scanner feature to identify products. This works surpirisingly well (if you orient the barcode vertically...). However, all special characters - accents, umlauts, "ß" from all scanned product names are missing when submitting to OpenFoodFacts. Rapsöl becomes "Rapsl", Süßkartoffeln are "Skartoffeln" and Kürbiskerne are "Krbiskerne". Is this a known bug or a settings issue?

  2. When I scan a product that I already have scanned before, I would expect Grocy just to add an entry to this product. instead, I get an error message popup, and when I tap on it, I see the (API?) JSON response is "{ error_message: "Product \"Chiasamen\" already exists!" }". Again, known bug or settings issue?

  3. The toaster messages, e.g. after saving, or after creating a new entry, stay on the screen for quite a while and on mobile devices they are in the way of scanning the next product when doing batch scans. Can we have them fade out more quickly, or - better - move to the screen bottom?

  4. Despite language settings, date values seem to be only accepted in the "YYYY-MM-DD" format. I know this but for my kids it was a hassle when we went through our first batch of food items.
    Also, the cursor seems to auto-jump to the next input field when *it thinks* the date is finished - but sometimes you make a mistake, and this way you cannot correct it.
    Can we also enter dates in other formats, like DD.MM.YYYY, or make this configurable somewhere?

  5. I could not correct spelling or other mistakes in product names when entering a purchase. The error message was something like "You must enter a valid product", which is at best a bit misleading because I just MADE the entry "valid" :-)
    Maybe it is possible to add a renaming feature: if a valid product is selected and then the name is changed, make it invalid (red border) but add a small "Rename product" link below the input field which renames the product accordingly and then reselects it so the choice is valid again?

  6. Sometimes, when scanning a barcode, the scan code (number) is just put into the "Product" input field as it is, and no modal window is shown with choices on how to act with this number (like online lookup etc). I could not reproduce this 100%, but it may be a race issue, when quickly scanning barcoes in succession. Known issue?

  7. From the inventory view, when I click on a product, then on "Inventory" (Bestandsanzeige), *then* on any item in the list, I get smaller and smaller modal dialog windows stacked on top of each other and the last view is simply unusable. At least when opening the last edit view the screen should revert to a full view. IMHO. Or am I missing something here?

  8. I entered about 100 products with the unit "piece" because I did not (yet) know about custom units. Now I have added "g" and "ml" as units, I'd like to correct this. However, the editor view does not allow me to change the unit of measure to anything else than "piece" - neither in the product view, barcode editor, nor in the purchase view. What am i missing?

  9. Reassigning a lot of products to a new category, or reassigning a lot of products to a new default location, seems to be quite cumbersome, as you have to edit each product separately. Am I overlooking some multi-edit or "select, then batch-update" feature?

  10. When batch-scanning a lot of products, two features would have been incredibly helpful for the process efficiency:
    a) a way of also scanning the best before date instead of having to enter it, and
    b) a way of entering/scanning multiple amount & best before date combinations for one product in one dialog, and Grocy then automatically creating multiple entries for this product. I can elaborate on this if there is interest - I saw the process in the "Speisekammer" App, and I quite liked the flow.

  11. When batch-entering products on a mobile device, it would be incredibly helpful if the "Save" button was always visible. Most of the time the dialogs were too large for the screen and the save button was off screen and had to be found. But initially I just wanted to scan the barcode and enter a location, product group, and a best before date, nothing more.

That's it for now.
Any help and/or comments would be highly appreciated! :-)


Sick of stale shoes?! Try FUSED footwear!




I'm struggling to make any API calls from outside my Home Assistant environment using tools like cURL or Postman. I'm struggling to make any API calls from outside my Home Assistant environment using tools like cURL or Postman.

Hello Grocy community,

I'm working on an exciting automation project and could really use some help regarding API access.

My Goal:

I've developed a script that extracts product lists from Brazilian tax receipts (NFC-e) after grocery shopping. My aim is to use the Grocy API to automatically add these products to my inventory and create new product entries, significantly streamlining my home inventory management.

My Setup:

I run Grocy as an add-on within Home Assistant. My Home Assistant instance is accessible externally via a Cloudflare domain (ha.example.com).

The Problem:

I'm struggling to make any API calls from outside my Home Assistant environment using tools like cURL or Postman. Here's what I'm experiencing:

  • Working: I can successfully test all API endpoints (e.g., /api/system/info, /api/products) directly from the Grocy Swagger UI panel provided by my installation. When I execute commands there, I get 200 OK responses with my data.

  • Not Working (401 Unauthorized): Whenever I try to use the exact same API key and endpoint path in cURL or Postman (both using the external Cloudflare domain and my local HA IP), I consistently receive a 401 Unauthorized error.

Example cURL commands (tokens masked):

# Attempting with external domain (HA + Grocy tokens)
curl -X 'GET' \
  'https://ha.example.com/api/hassio_ingress/YOUR_INGRESS_ID/api/system/info' \
  -H 'accept: application/json' \
  -H 'GROCY-API-KEY: YOUR_GROCY_API_KEY' \
  -H 'Authorization: Bearer YOUR_HA_LONG_LIVED_TOKEN'

# Attempting with local IP (HA + Grocy tokens)
curl -X 'GET' \
  'http://192.168.2.14:8123/api/hassio_ingress/YOUR_INGRESS_ID/api/system/info' \
  -H 'accept: application/json' \
  -H 'GROCY-API-KEY: YOUR_GROCY_API_KEY' \
  -H 'Authorization: Bearer YOUR_HA_LONG_LIVED_TOKEN'

What I've already confirmed:

  • My Grocy API Key is valid (works in Swagger UI).

  • My Home Assistant Long-Lived Access Token is valid (I can access http://192.168.2.14:8123/api/ successfully with it).

  • The Grocy add-on is NOT exposing its port directly (e.g., 9192) on my local network.

My Question:

Is there a specific limitation or a recommended method for using Grocy's API endpoints externally (outside the Home Assistant UI) when Grocy is run as an add-on and accessed via Home Assistant Ingress? Am I missing a header, or is direct API access via Ingress not intended for external tools like cURL/Postman?

Any guidance on how to properly authenticate or a workaround for this scenario would be greatly appreciated! Thanks in advance for your time and help!

🇧🇷 Versão em Português

Buscando orientação: Automatizar inventário do Grocy via script externo (NFC-e) - Problemas de acesso à API via Home Assistant Ingress

Olá, comunidade Grocy,

Estou trabalhando em um projeto de automação empolgante e gostaria muito de uma ajuda em relação ao acesso à API.

Meu Objetivo:

Desenvolvi um script que extrai listas de produtos de notas fiscais brasileiras (NFC-e) após as compras de supermercado. Meu objetivo é usar a API do Grocy para adicionar automaticamente esses produtos ao meu inventário e criar novas entradas de produtos, simplificando significativamente a gestão do meu estoque doméstico.

Minha Configuração:

Eu utilizo o Grocy como um add-on dentro do Home Assistant. Minha instância do Home Assistant é acessível externamente via um domínio do Cloudflare (ha.example.com).

O Problema:

Estou com dificuldades para fazer qualquer chamada à API de fora do meu ambiente Home Assistant, usando ferramentas como cURL ou Postman. O que estou experienciando é o seguinte:

  • Funcionando: Consigo testar todos os endpoints da API (ex: /api/system/info, /api/products) diretamente pelo painel do Swagger UI do Grocy, que é disponibilizado na minha instalação. Quando executo os comandos lá, obtenho respostas 200 OK com meus dados.

  • Não Funcionando (401 Unauthorized): Sempre que tento usar a exata mesma chave de API e o caminho do endpoint no cURL ou Postman (tanto usando o domínio externo do Cloudflare quanto o IP local do meu HA), eu consistentemente recebo um erro 401 Unauthorized.

Exemplos de comandos cURL (tokens mascarados):

# Tentativa com domínio externo (tokens do HA + Grocy)
curl -X 'GET' \
  'https://ha.example.com/api/hassio_ingress/SEU_ID_INGRESS/api/system/info' \
  -H 'accept: application/json' \
  -H 'GROCY-API-KEY: SUA_CHAVE_API_GROCY' \
  -H 'Authorization: Bearer SEU_TOKEN_LONG_LIVED_DO_HA'

# Tentativa com IP local (tokens do HA + Grocy)
curl -X 'GET' \
  'http://192.168.2.14:8123/api/hassio_ingress/SEU_ID_INGRESS/api/system/info' \
  -H 'accept: application/json' \
  -H 'GROCY-API-KEY: SUA_CHAVE_API_GROCY' \
  -H 'Authorization: Bearer SEU_TOKEN_LONG_LIVED_DO_HA'

O que já confirmei:

  • Minha chave de API do Grocy é válida (funciona no Swagger UI).

  • Meu Long-Lived Access Token do Home Assistant é válido (consigo acessar http://192.168.2.14:8123/api/ com ele com sucesso).

  • O add-on Grocy NÃO está expondo sua porta diretamente (ex: 9192) na minha rede local.

Minha Pergunta:

Existe alguma limitação específica ou um método recomendado para usar os endpoints da API do Grocy externamente (fora da interface do Home Assistant) quando o Grocy é executado como um add-on e acessado via Home Assistant Ingress? Estou perdendo algum cabeçalho ou o acesso direto à API via Ingress não é destinado a ferramentas externas como cURL/Postman?

Qualquer orientação sobre como autenticar corretamente ou uma solução alternativa para este cenário seria muito apreciada! Agradeço antecipadamente pelo seu tempo e ajuda!


Unable to change Quantity Unit of Product after saving Product Unable to change Quantity Unit of Product after saving Product

I noticed this issue was brought up before, but the person reporting it had a difficult time explaining/reproducing the issue. After I create a new product having the Quantity Unit "Pack", which I often do by mistake since it's the default, I am unable to edit the product and change the Quantity Unit to any of the other defined Quantity Units. I was able to easily reproduce the issue in the demo instance. If you go into Manage Master Data -> Products and edit RyuujinZero's Test Product, clicking the "Quantity unit stock", "Default quantity unit purchase", "Default quantity unit consume", or "Quantity unit for prices" dropdowns will only give you the option to select Pack (which is what I set it to when creating the product) and nothing else.

I'm not sure if I understand the developer's response in the initial post, but it seems like the only ways to go about correcting this is to either configure a conversion from one quantity unit to another or recreate the product entirely, unless I'm wrong. This issue isn't really about converting to another unit, but correcting the unit picked in the first place.


Multiple Instances Multiple Instances

Is anyone running multiple instances? If so, what has been your deciding factor on what lands in what instance? I'm toying with how to split out different items. I'm not sure that I want to track all my medicines and bandages and cleaners in with everything else.

It feels like there is 1 too few levels of product (product > Parent Product > Product Group >Parent Product Group) coupled with the lack of a persistent filter in the stock makes me wonder if a separate instance would be better. Or maybe there is a way to have the filter persist when jumping into and out of products, and I just missed it!

Thoughts?


AI that runs entirely on your Mac




Unable to Render Recipes or Meal Plan Unable to Render Recipes or Meal Plan

Symptom

I get a timeout when trying to load Recipes or Meal plan blades.

Stacktrace

The only error I can get out of PHP is that it timed out after 30s on this line: https://github.com/grocy/grocy/blob/6b18b0a7beba96435f6f7a9f23210c6683bb478f/services/DatabaseService.php#L102

I don't think that's where it's actually happening

SQLite

If I open up the sqlite database and try to replicate the queries, I can get a query that never returns.

First I created a function named grocy_user_setting(in_value) to mimic the dynamic function registered in the sqlite driver by the app. I gave it the following code (I ony have 1 user and its id is 1):

select value from user_settings where user_id = 1 and key = $in_value;

Running this function results in the following (the only time I see anything use this function):

select grocy_user_setting('stock_due_soon_days')
grocy_user_setting('stock_due_soon_days')
5

Then I started rendering views to see which would/wouldn't render.

Succeeds

  • recipes_nestings_resolved

  • meal_plan_internal_recipe_relation

  • products_volatile_status (used by pos_resolved)

  • products_current_substitutions (used by pos_resolved)

  • stock_current (used by pos_resolved)

  • products_current_price (used by pos_resolved)

Does not succeed

These views just spin forever and never resolve

  • recipes_pos_resolved

  • recipes_resolved

  • recipes_missing_product_counts (layers on top of of pos_resolved)

Deployment Method

I'm running on bare metal using the php app, php 8.2

Version 	4.5.0
Released on 	2025-03-28 2 months ago
PHP Version 	8.2.28
SQLite Version 	3.48.0
Database Version 	253

I've also restored my backup to the linux-server/grocy-docker and validated the error still ocurrs (though since it seems to be in the sqlite db that makes sense).

I've restored my backup from last month when this definitely did work and it no longer can load either (???). I validated that the db entries were all older than 1mo so the db was properly restored. (both in 4.4 and 4.5)

Extra debug info

Here's the query plan (I don't know enough to understand it)

<details> <summary>recipes_pos_resolved explain</summary>

addr	opcode	p1	p2	p3	p4	p5	comment
0	Init	0	7672	0		0	
1	Explain	1	0	0	COMPOUND QUERY	0	
2	Explain	2	1	0	LEFT-MOST SUBQUERY	0	
3	OpenEphemeral	356	25	0	k(25,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B)	0	
4	InitCoroutine	1	66	5		0	
5	Explain	5	2	0	CO-ROUTINE r1	0	
6	OpenPseudo	193	2	4		0	
7	OpenEphemeral	357	4	0		0	
8	Explain	8	5	0	SETUP	0	
9	OpenRead	358	18	0	k(1,)	0	
10	Explain	10	8	207	SCAN recipes USING COVERING INDEX sqlite_autoindex_recipes_1	0	
11	Rewind	358	20	3	0	0	
12	IdxRowid	358	3	0		0	
13	IdxRowid	358	4	0		0	
14	Integer	1	5	0		0	
15	Integer	0	6	0		0	
16	MakeRecord	3	4	7		0	
17	NewRowid	357	8	0		0	
18	Insert	357	7	8		8	
19	Next	358	12	0		1	
20	Rewind	357	65	0		0	
21	NullRow	193	0	0		0	
22	RowData	357	2	0		0	
23	Delete	357	0	0		0	
24	Column	193	0	9		0	
25	Column	193	1	10		0	
26	Column	193	2	11		0	
27	Column	193	3	12		0	
28	Yield	1	0	0		0	
29	Explain	29	5	0	RECURSIVE STEP	0	
30	OpenRead	195	44	0	5	0	
31	Explain	31	29	216	SCAN r1	0	
32	Once	0	46	0		0	
33	Explain	33	29	0	CREATE AUTOMATIC INDEX ON recipes_nestings(includes_recipe_id, recipe_id, servings)	0	
34	OpenAutoindex	359	4	0	k(4,B,,,)	0	
35	Explain	35	29	0	BLOOM FILTER ON rn (includes_recipe_id=?)	0	
36	Blob	10000	13	0		0	
37	Rewind	195	46	0		0	
38	Column	195	2	14		0	
39	Column	195	1	15		0	
40	Column	195	4	16	1	0	
41	Rowid	195	17	0		0	
42	MakeRecord	14	4	7		0	
43	FilterAdd	13	0	14	1	0	
44	IdxInsert	359	7	0		16	
45	Next	195	38	0		3	
46	Explain	46	29	53	SEARCH rn USING AUTOMATIC COVERING INDEX (includes_recipe_id=?)	0	
47	Column	193	0	18		0	
48	IsNull	18	64	0		0	
49	Affinity	18	1	0	C	0	
50	Filter	13	64	18	1	0	
51	SeekGE	359	64	18	1	0	
52	IdxGT	359	64	18	1	0	
53	Column	359	1	3		0	
54	Column	193	1	4		0	
55	Column	359	2	7	1	0	
56	Column	193	2	8		0	
57	Multiply	8	7	5		0	
58	Column	193	3	8		0	
59	Add	19	8	6		0	
60	MakeRecord	3	4	8		0	
61	NewRowid	357	7	0		0	
62	Insert	357	8	7		8	
63	Next	359	52	0		0	
64	Goto	0	20	0		0	
65	EndCoroutine	1	0	0		0	
66	Goto	0	466	0		0	
67	Once	0	465	0		0	
68	Explain	68	2	0	MATERIALIZE stock_current	0	
69	OpenEphemeral	197	9	0		0	
70	Explain	70	68	0	COMPOUND QUERY	0	
71	Explain	71	70	0	LEFT-MOST SUBQUERY	0	
72	OpenEphemeral	360	9	0	k(9,B,B,B,B,B,B,B,B,B)	0	
73	Noop	361	8	0		0	
74	Integer	0	22	0		0	
75	Null	0	25	25		0	
76	Gosub	24	313	0		0	
77	OpenRead	210	93	0	19	0	
78	OpenRead	362	113	0	k(3,,,)	0	
79	OpenRead	208	93	0	19	0	
80	OpenRead	207	93	0	22	0	
81	OpenRead	363	106	0	k(5,,,,,)	2	
82	OpenRead	209	97	0	9	0	
83	OpenRead	364	116	0	k(4,,,,)	2	
84	Explain	84	71	193	SCAN p USING INDEX ix_products_performance2	0	
85	Rewind	362	156	27	0	0	
86	DeferredSeek	362	0	210		0	
87	Column	362	1	27	1	0	
88	Ne	19	155	27	BINARY-8	84	
89	Explain	89	71	45	SEARCH p_sub USING INTEGER PRIMARY KEY (rowid=?)	0	
90	IdxRowid	362	28	0		0	
91	SeekRowid	208	155	28		0	
92	IdxRowid	362	27	0		0	
93	Rowid	208	29	0		0	
94	Ne	29	155	27		83	
95	Column	208	4	29	1	0	
96	Ne	19	155	29	BINARY-8	84	
97	Explain	97	71	45	SEARCH p_parent USING INTEGER PRIMARY KEY (rowid=?)	0	
98	Column	362	0	30		0	
99	ClrSubtype	30	0	0		0	
100	SeekRowid	207	155	30		0	
101	Column	207	4	29	1	0	
102	Ne	19	155	29	BINARY-8	84	
103	Explain	103	71	54	SEARCH s USING COVERING INDEX ix_stock_performance1 (product_id=?)	0	
104	IdxRowid	362	31	0		0	
105	SeekGE	363	155	31	1	0	
106	IdxGT	363	155	31	1	0	
107	IdxRowid	362	29	0		0	
108	Column	363	0	27		0	
109	Ne	27	154	29	BINARY-8	83	
110	Explain	110	71	59	SEARCH qucr USING INDEX ix_cache__quantity_unit_conversions_resolved_performance1 (product_id=? AND from_qu_id=? AND to_qu_id=?) LEFT-JOIN	0	
111	Integer	0	32	0		0	
112	IdxRowid	362	33	0		0	
113	Column	208	8	34		0	
114	Column	207	8	35		0	
115	Affinity	34	2	0	CC	0	
116	SeekGE	364	150	33	3	0	
117	IdxGT	364	150	33	3	0	
118	DeferredSeek	364	0	209		0	
119	Integer	1	32	0		0	
120	Column	362	0	26		0	
121	ClrSubtype	26	0	0		0	
122	Compare	25	26	1	k(1,B)	0	
123	Jump	124	128	124		0	
124	Gosub	23	160	0		0	
125	Move	26	25	1		0	
126	IfPos	22	316	0		0	
127	Gosub	24	313	0		0	
128	Column	363	3	29		0	
129	Column	209	8	48		0	
130	NotNull	48	132	0		0	
131	Real	0	48	0	1	0	
132	Multiply	48	29	27		0	
133	AggStep	0	27	43	sum(1)	1	
134	Column	363	2	27		0	
135	CollSeq	49	0	0	BINARY-8	0	
136	AggStep	0	27	44	min(1)	1	
137	Column	208	18	27		0	
138	AggStep	0	27	45	count(1)	1	
139	Column	207	21	27	1	0	
140	CollSeq	49	0	0	BINARY-8	0	
141	AggStep	0	27	46	max(1)	1	
142	Column	363	3	27		0	
143	AggStep	0	27	47	sum(1)	1	
144	If	49	148	0		0	
145	Column	210	18	36		0	
146	IdxRowid	362	37	0		0	
147	Column	209	8	38		0	
148	Integer	1	21	0		0	
149	Next	364	117	1		0	
150	IfPos	32	154	0		0	
151	NullRow	209	0	0		0	
152	NullRow	364	0	0		0	
153	Goto	0	119	0		0	
154	Next	363	106	0		0	
155	Next	362	86	0		1	
156	Gosub	23	160	0		0	
157	Goto	0	316	0		0	
158	Integer	1	22	0		0	
159	Return	23	0	0		0	
160	IfPos	21	162	0		0	
161	Return	23	0	0		0	
162	AggFinal	43	1	0	sum(1)	0	
163	AggFinal	44	1	0	min(1)	0	
164	AggFinal	45	1	0	count(1)	0	
165	AggFinal	46	1	0	max(1)	0	
166	AggFinal	47	1	0	sum(1)	0	
167	Le	50	161	47		80	
168	Copy	25	51	0		0	
169	ClrSubtype	51	0	0		0	
170	BeginSubrtn	0	60	0		0	
171	Explain	171	71	0	CORRELATED SCALAR SUBQUERY 113	0	
172	Null	0	61	61		0	
173	Integer	1	62	0		0	
174	Null	0	63	64		0	
175	OpenRead	365	106	0	k(5,,,,,)	2	
176	Explain	176	171	54	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=?)	0	
177	NotNull	36	180	0		0	
178	SCopy	37	65	0		0	
179	Goto	0	181	0		0	
180	SCopy	36	65	0		0	
181	ClrSubtype	65	0	0		0	
182	IsNull	65	189	0		0	
183	Affinity	65	1	0	C	0	
184	SeekGE	365	189	65	1	0	
185	IdxGT	365	189	65	1	0	
186	Column	365	3	27		0	
187	AggStep	0	27	64	sum(1)	1	
188	Next	365	185	0		0	
189	AggFinal	64	1	0	sum(1)	0	
190	Copy	64	61	0		0	
191	DecrJumpZero	62	192	0		0	
192	Return	60	171	1		0	
193	Copy	61	52	0		0	
194	NotNull	52	196	0		0	
195	Integer	0	52	0		0	
196	SCopy	43	53	0		0	
197	BeginSubrtn	0	68	0		0	
198	Explain	198	71	0	CORRELATED SCALAR SUBQUERY 114	0	
199	Null	0	69	69		0	
200	Integer	1	70	0		0	
201	Null	0	71	73		0	
202	OpenRead	212	49	0	7	0	
203	OpenRead	366	106	0	k(5,,,,,)	2	
204	Explain	204	198	62	SEARCH stock USING INDEX ix_stock_performance1 (product_id=?)	0	
205	NotNull	36	208	0		0	
206	SCopy	37	74	0		0	
207	Goto	0	209	0		0	
208	SCopy	36	74	0		0	
209	ClrSubtype	74	0	0		0	
210	IsNull	74	222	0		0	
211	Affinity	74	1	0	C	0	
212	SeekGE	366	222	74	1	0	
213	IdxGT	366	222	74	1	0	
214	DeferredSeek	366	0	212		0	
215	Column	212	6	76		0	
216	NotNull	76	218	0		0	
217	Integer	0	76	0		0	
218	Column	366	3	77		0	
219	Multiply	77	76	75		0	
220	AggStep	0	75	73	sum(1)	1	
221	Next	366	213	0		0	
222	AggFinal	73	1	0	sum(1)	0	
223	Copy	73	69	0		0	
224	DecrJumpZero	70	225	0		0	
225	Return	68	198	1		0	
226	SCopy	69	66	0		0	
227	Function	2	66	54	round(2)	0	
228	NotNull	54	230	0		0	
229	Integer	0	54	0		0	
230	SCopy	44	55	0		0	
231	BeginSubrtn	0	78	0		0	
232	Explain	232	71	0	CORRELATED SCALAR SUBQUERY 115	0	
233	Null	0	79	79		0	
234	Integer	1	80	0		0	
235	Null	0	81	82		0	
236	OpenRead	367	106	0	k(5,,,,,)	2	
237	Explain	237	232	53	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
238	NotNull	36	241	0		0	
239	SCopy	37	83	0		0	
240	Goto	0	242	0		0	
241	SCopy	36	83	0		0	
242	ClrSubtype	83	0	0		0	
243	IsNull	83	251	0		0	
244	Integer	1	84	0		0	
245	Affinity	83	1	0	C	0	
246	SeekGE	367	251	83	2	0	
247	IdxGT	367	251	83	2	0	
248	Column	367	3	85		0	
249	AggStep	0	85	82	sum(1)	1	
250	Next	367	247	0		0	
251	AggFinal	82	1	0	sum(1)	0	
252	Copy	82	79	0		0	
253	DecrJumpZero	80	254	0		0	
254	Return	78	232	1		0	
255	Copy	79	56	0		0	
256	NotNull	56	258	0		0	
257	Integer	0	56	0		0	
258	BeginSubrtn	0	87	0		0	
259	Explain	259	71	0	CORRELATED SCALAR SUBQUERY 116	0	
260	Null	0	88	88		0	
261	Integer	1	89	0		0	
262	Null	0	90	91		0	
263	OpenRead	368	106	0	k(5,,,,,)	2	
264	Explain	264	259	99	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
265	OpenEphemeral	369	1	0	k(1,B)	0	
266	Explain	266	259	0	CORRELATED LIST SUBQUERY 117	0	
267	OpenRead	216	93	0	19	0	
268	OpenRead	370	113	0	k(3,,,)	2	
269	Explain	269	266	52	SEARCH p USING COVERING INDEX ix_products_performance2 (<expr>=? AND active=?)	0	
270	NotNull	36	273	0		0	
271	SCopy	37	94	0		0	
272	Goto	0	274	0		0	
273	SCopy	36	94	0		0	
274	ClrSubtype	94	0	0		0	
275	IsNull	94	284	0		0	
276	Integer	1	95	0		0	
277	SeekGE	370	284	94	2	0	
278	IdxGT	370	284	94	2	0	
279	DeferredSeek	370	0	216		0	
280	IdxRowid	370	97	0		0	
281	MakeRecord	97	1	96	C	0	
282	IdxInsert	369	96	97	1	0	
283	Next	370	278	1		0	
284	Rewind	369	294	0		0	
285	Column	369	0	92		0	
286	IsNull	92	293	0		0	
287	Integer	1	93	0		0	
288	SeekGE	368	293	92	2	0	
289	IdxGT	368	293	92	2	0	
290	Column	368	3	96		0	
291	AggStep	0	96	91	sum(1)	1	
292	Next	368	289	0		0	
293	Next	369	285	0		0	
294	AggFinal	91	1	0	sum(1)	0	
295	Copy	91	88	0		0	
296	DecrJumpZero	89	297	0		0	
297	Return	87	259	1		0	
298	Copy	88	86	0		0	
299	NotNull	86	301	0		0	
300	Integer	0	86	0		0	
301	SCopy	38	98	0		0	
302	NotNull	98	304	0		0	
303	Integer	1	98	0		0	
304	Multiply	98	86	57		0	
305	Le	50	308	45		80	
306	Integer	1	58	0		0	
307	Goto	0	309	0		0	
308	Integer	0	58	0		0	
309	SCopy	46	59	0		0	
310	MakeRecord	51	9	98		0	
311	IdxInsert	360	98	51	9	0	
312	Return	23	0	0		0	
313	Null	0	36	47		0	
314	Integer	0	21	0		0	
315	Return	24	0	0		0	
316	Explain	316	70	0	UNION USING TEMP B-TREE	0	
317	Noop	371	6	0		0	
318	Integer	0	100	0		0	
319	Null	0	103	103		0	
320	Gosub	102	447	0		0	
321	OpenRead	202	93	0	19	0	
322	OpenRead	201	93	0	22	0	
323	OpenRead	200	49	0	7	0	
324	OpenRead	372	106	0	k(5,,,,,)	2	
325	Explain	325	316	216	SCAN p	0	
326	Rewind	202	379	0		0	
327	Column	202	4	98	1	0	
328	Ne	19	378	98	BINARY-8	84	
329	Column	202	18	86		128	
330	NotNull	86	333	0		0	
331	Rowid	202	98	0		0	
332	Goto	0	334	0		0	
333	Column	202	18	98		0	
334	Rowid	202	86	0		0	
335	Eq	86	378	98	BINARY-8	84	
336	Explain	336	316	45	SEARCH p_sub USING INTEGER PRIMARY KEY (rowid=?)	0	
337	Rowid	202	105	0		0	
338	SeekRowid	201	378	105		0	
339	Rowid	202	86	0		0	
340	Rowid	201	98	0		0	
341	Ne	98	378	86		83	
342	Column	201	4	98	1	0	
343	Ne	19	378	98	BINARY-8	84	
344	Explain	344	316	62	SEARCH s USING INDEX ix_stock_performance1 (product_id=?)	0	
345	Rowid	202	106	0		0	
346	SeekGE	372	378	106	1	0	
347	IdxGT	372	378	106	1	0	
348	DeferredSeek	372	0	200		0	
349	Rowid	202	98	0		0	
350	Column	372	0	86		0	
351	Ne	86	377	98	BINARY-8	83	
352	Rowid	202	104	0		0	
353	Compare	103	104	1	k(1,B)	0	
354	Jump	355	359	355		0	
355	Gosub	101	383	0		0	
356	Move	104	103	1		0	
357	IfPos	100	450	0		0	
358	Gosub	102	447	0		0	
359	Column	372	3	86		0	
360	AggStep	0	86	113	sum(1)	1	
361	Column	200	6	98		0	
362	NotNull	98	364	0		0	
363	Integer	0	98	0		0	
364	Column	372	3	117		0	
365	Multiply	117	98	86		0	
366	AggStep	0	86	114	sum(1)	1	
367	Column	372	2	86		0	
368	CollSeq	118	0	0	BINARY-8	0	
369	AggStep	0	86	115	min(1)	1	
370	Column	201	21	86	1	0	
371	CollSeq	118	0	0	BINARY-8	0	
372	AggStep	0	86	116	max(1)	1	
373	If	118	376	0		0	
374	Rowid	202	107	0		0	
375	Column	372	0	108		0	
376	Integer	1	99	0		0	
377	Next	372	347	0		0	
378	Next	202	327	0		1	
379	Gosub	101	383	0		0	
380	Goto	0	450	0		0	
381	Integer	1	100	0		0	
382	Return	101	0	0		0	
383	IfPos	99	385	0		0	
384	Return	101	0	0		0	
385	AggFinal	113	1	0	sum(1)	0	
386	AggFinal	114	1	0	sum(1)	0	
387	AggFinal	115	1	0	min(1)	0	
388	AggFinal	116	1	0	max(1)	0	
389	Le	50	384	113		80	
390	SCopy	107	51	0		0	
391	SCopy	113	52	0		0	
392	SCopy	113	53	0		0	
393	SCopy	114	119	0		0	
394	Function	2	119	54	round(2)	0	
395	SCopy	115	55	0		0	
396	BeginSubrtn	0	121	0		0	
397	Explain	397	316	0	CORRELATED SCALAR SUBQUERY 109	0	
398	Null	0	122	122		0	
399	Integer	1	123	0		0	
400	Null	0	124	125		0	
401	OpenRead	373	106	0	k(5,,,,,)	2	
402	Explain	402	397	53	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
403	Copy	108	126	0		0	
404	IsNull	126	412	0		0	
405	Integer	1	127	0		0	
406	Affinity	126	1	0	C	0	
407	SeekGE	373	412	126	2	0	
408	IdxGT	373	412	126	2	0	
409	Column	373	3	86		0	
410	AggStep	0	86	125	sum(1)	1	
411	Next	373	408	0		0	
412	AggFinal	125	1	0	sum(1)	0	
413	Copy	125	122	0		0	
414	DecrJumpZero	123	415	0		0	
415	Return	121	397	1		0	
416	Copy	122	56	0		0	
417	NotNull	56	419	0		0	
418	Integer	0	56	0		0	
419	BeginSubrtn	0	128	0		0	
420	Explain	420	316	0	CORRELATED SCALAR SUBQUERY 110	0	
421	Null	0	129	129		0	
422	Integer	1	130	0		0	
423	Null	0	131	132		0	
424	OpenRead	374	106	0	k(5,,,,,)	2	
425	Explain	425	420	53	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
426	Copy	108	133	0		0	
427	IsNull	133	435	0		0	
428	Integer	1	134	0		0	
429	Affinity	133	1	0	C	0	
430	SeekGE	374	435	133	2	0	
431	IdxGT	374	435	133	2	0	
432	Column	374	3	135		0	
433	AggStep	0	135	132	sum(1)	1	
434	Next	374	431	0		0	
435	AggFinal	132	1	0	sum(1)	0	
436	Copy	132	129	0		0	
437	DecrJumpZero	130	438	0		0	
438	Return	128	420	1		0	
439	Copy	129	57	0		0	
440	NotNull	57	442	0		0	
441	Integer	0	57	0		0	
442	Integer	0	58	0		0	
443	SCopy	116	59	0		0	
444	MakeRecord	51	9	136		0	
445	IdxInsert	360	136	51	9	0	
446	Return	101	0	0		0	
447	Null	0	107	116		0	
448	Integer	0	99	0		0	
449	Return	102	0	0		0	
450	Rewind	360	464	0		0	
451	Column	360	0	137		0	
452	Column	360	1	138		0	
453	Column	360	2	139		0	
454	Column	360	3	140		0	
455	Column	360	4	141		0	
456	Column	360	5	142		0	
457	Column	360	6	143		0	
458	Column	360	7	144		0	
459	Column	360	8	145		0	
460	MakeRecord	137	9	136		0	
461	NewRowid	197	146	0		0	
462	Insert	197	136	146		8	
463	Next	360	451	0		0	
464	Close	360	0	0		0	
465	Return	20	67	0		0	
466	Goto	0	2144	0		0	
467	Once	0	2143	0		0	
468	Explain	468	2	0	MATERIALIZE x	0	
469	OpenEphemeral	217	4	0		0	
470	OpenEphemeral	375	4	0	k(4,B,B,B,B)	0	
471	Explain	471	468	0	COMPOUND QUERY	0	
472	Explain	472	471	0	LEFT-MOST SUBQUERY	0	
473	Goto	0	873	0		0	
474	Once	0	872	0		0	
475	Explain	475	472	0	MATERIALIZE stock_current	0	
476	OpenEphemeral	270	9	0		0	
477	Explain	477	475	0	COMPOUND QUERY	0	
478	Explain	478	477	0	LEFT-MOST SUBQUERY	0	
479	OpenEphemeral	376	9	0	k(9,B,B,B,B,B,B,B,B,B)	0	
480	Noop	377	8	0		0	
481	Integer	0	150	0		0	
482	Null	0	153	153		0	
483	Gosub	152	720	0		0	
484	OpenRead	287	93	0	19	0	
485	OpenRead	378	113	0	k(3,,,)	0	
486	OpenRead	285	93	0	19	0	
487	OpenRead	284	93	0	22	0	
488	OpenRead	379	106	0	k(5,,,,,)	2	
489	OpenRead	286	97	0	9	0	
490	OpenRead	380	116	0	k(4,,,,)	2	
491	Explain	491	478	193	SCAN p USING INDEX ix_products_performance2	0	
492	Rewind	378	563	155	0	0	
493	DeferredSeek	378	0	287		0	
494	Column	378	1	155	1	0	
495	Ne	19	562	155	BINARY-8	84	
496	Explain	496	478	45	SEARCH p_sub USING INTEGER PRIMARY KEY (rowid=?)	0	
497	IdxRowid	378	156	0		0	
498	SeekRowid	285	562	156		0	
499	IdxRowid	378	155	0		0	
500	Rowid	285	157	0		0	
501	Ne	157	562	155		83	
502	Column	285	4	157	1	0	
503	Ne	19	562	157	BINARY-8	84	
504	Explain	504	478	45	SEARCH p_parent USING INTEGER PRIMARY KEY (rowid=?)	0	
505	Column	378	0	158		0	
506	ClrSubtype	158	0	0		0	
507	SeekRowid	284	562	158		0	
508	Column	284	4	157	1	0	
509	Ne	19	562	157	BINARY-8	84	
510	Explain	510	478	54	SEARCH s USING COVERING INDEX ix_stock_performance1 (product_id=?)	0	
511	IdxRowid	378	159	0		0	
512	SeekGE	379	562	159	1	0	
513	IdxGT	379	562	159	1	0	
514	IdxRowid	378	157	0		0	
515	Column	379	0	155		0	
516	Ne	155	561	157	BINARY-8	83	
517	Explain	517	478	59	SEARCH qucr USING INDEX ix_cache__quantity_unit_conversions_resolved_performance1 (product_id=? AND from_qu_id=? AND to_qu_id=?) LEFT-JOIN	0	
518	Integer	0	160	0		0	
519	IdxRowid	378	161	0		0	
520	Column	285	8	162		0	
521	Column	284	8	163		0	
522	Affinity	162	2	0	CC	0	
523	SeekGE	380	557	161	3	0	
524	IdxGT	380	557	161	3	0	
525	DeferredSeek	380	0	286		0	
526	Integer	1	160	0		0	
527	Column	378	0	154		0	
528	ClrSubtype	154	0	0		0	
529	Compare	153	154	1	k(1,B)	0	
530	Jump	531	535	531		0	
531	Gosub	151	567	0		0	
532	Move	154	153	1		0	
533	IfPos	150	723	0		0	
534	Gosub	152	720	0		0	
535	Column	379	3	157		0	
536	Column	286	8	176		0	
537	NotNull	176	539	0		0	
538	Real	0	176	0	1	0	
539	Multiply	176	157	155		0	
540	AggStep	0	155	171	sum(1)	1	
541	Column	379	2	155		0	
542	CollSeq	177	0	0	BINARY-8	0	
543	AggStep	0	155	172	min(1)	1	
544	Column	285	18	155		0	
545	AggStep	0	155	173	count(1)	1	
546	Column	284	21	155	1	0	
547	CollSeq	177	0	0	BINARY-8	0	
548	AggStep	0	155	174	max(1)	1	
549	Column	379	3	155		0	
550	AggStep	0	155	175	sum(1)	1	
551	If	177	555	0		0	
552	Column	287	18	164		0	
553	IdxRowid	378	165	0		0	
554	Column	286	8	166		0	
555	Integer	1	149	0		0	
556	Next	380	524	1		0	
557	IfPos	160	561	0		0	
558	NullRow	286	0	0		0	
559	NullRow	380	0	0		0	
560	Goto	0	526	0		0	
561	Next	379	513	0		0	
562	Next	378	493	0		1	
563	Gosub	151	567	0		0	
564	Goto	0	723	0		0	
565	Integer	1	150	0		0	
566	Return	151	0	0		0	
567	IfPos	149	569	0		0	
568	Return	151	0	0		0	
569	AggFinal	171	1	0	sum(1)	0	
570	AggFinal	172	1	0	min(1)	0	
571	AggFinal	173	1	0	count(1)	0	
572	AggFinal	174	1	0	max(1)	0	
573	AggFinal	175	1	0	sum(1)	0	
574	Le	50	568	175		80	
575	Copy	153	178	0		0	
576	ClrSubtype	178	0	0		0	
577	BeginSubrtn	0	187	0		0	
578	Explain	578	478	0	CORRELATED SCALAR SUBQUERY 159	0	
579	Null	0	188	188		0	
580	Integer	1	189	0		0	
581	Null	0	190	191		0	
582	OpenRead	381	106	0	k(5,,,,,)	2	
583	Explain	583	578	54	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=?)	0	
584	NotNull	164	587	0		0	
585	SCopy	165	192	0		0	
586	Goto	0	588	0		0	
587	SCopy	164	192	0		0	
588	ClrSubtype	192	0	0		0	
589	IsNull	192	596	0		0	
590	Affinity	192	1	0	C	0	
591	SeekGE	381	596	192	1	0	
592	IdxGT	381	596	192	1	0	
593	Column	381	3	155		0	
594	AggStep	0	155	191	sum(1)	1	
595	Next	381	592	0		0	
596	AggFinal	191	1	0	sum(1)	0	
597	Copy	191	188	0		0	
598	DecrJumpZero	189	599	0		0	
599	Return	187	578	1		0	
600	Copy	188	179	0		0	
601	NotNull	179	603	0		0	
602	Integer	0	179	0		0	
603	SCopy	171	180	0		0	
604	BeginSubrtn	0	195	0		0	
605	Explain	605	478	0	CORRELATED SCALAR SUBQUERY 160	0	
606	Null	0	196	196		0	
607	Integer	1	197	0		0	
608	Null	0	198	200		0	
609	OpenRead	289	49	0	7	0	
610	OpenRead	382	106	0	k(5,,,,,)	2	
611	Explain	611	605	62	SEARCH stock USING INDEX ix_stock_performance1 (product_id=?)	0	
612	NotNull	164	615	0		0	
613	SCopy	165	201	0		0	
614	Goto	0	616	0		0	
615	SCopy	164	201	0		0	
616	ClrSubtype	201	0	0		0	
617	IsNull	201	629	0		0	
618	Affinity	201	1	0	C	0	
619	SeekGE	382	629	201	1	0	
620	IdxGT	382	629	201	1	0	
621	DeferredSeek	382	0	289		0	
622	Column	289	6	203		0	
623	NotNull	203	625	0		0	
624	Integer	0	203	0		0	
625	Column	382	3	204		0	
626	Multiply	204	203	202		0	
627	AggStep	0	202	200	sum(1)	1	
628	Next	382	620	0		0	
629	AggFinal	200	1	0	sum(1)	0	
630	Copy	200	196	0		0	
631	DecrJumpZero	197	632	0		0	
632	Return	195	605	1		0	
633	SCopy	196	193	0		0	
634	Function	2	193	181	round(2)	0	
635	NotNull	181	637	0		0	
636	Integer	0	181	0		0	
637	SCopy	172	182	0		0	
638	BeginSubrtn	0	205	0		0	
639	Explain	639	478	0	CORRELATED SCALAR SUBQUERY 161	0	
640	Null	0	206	206		0	
641	Integer	1	207	0		0	
642	Null	0	208	209		0	
643	OpenRead	383	106	0	k(5,,,,,)	2	
644	Explain	644	639	53	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
645	NotNull	164	648	0		0	
646	SCopy	165	210	0		0	
647	Goto	0	649	0		0	
648	SCopy	164	210	0		0	
649	ClrSubtype	210	0	0		0	
650	IsNull	210	658	0		0	
651	Integer	1	211	0		0	
652	Affinity	210	1	0	C	0	
653	SeekGE	383	658	210	2	0	
654	IdxGT	383	658	210	2	0	
655	Column	383	3	212		0	
656	AggStep	0	212	209	sum(1)	1	
657	Next	383	654	0		0	
658	AggFinal	209	1	0	sum(1)	0	
659	Copy	209	206	0		0	
660	DecrJumpZero	207	661	0		0	
661	Return	205	639	1		0	
662	Copy	206	183	0		0	
663	NotNull	183	665	0		0	
664	Integer	0	183	0		0	
665	BeginSubrtn	0	214	0		0	
666	Explain	666	478	0	CORRELATED SCALAR SUBQUERY 162	0	
667	Null	0	215	215		0	
668	Integer	1	216	0		0	
669	Null	0	217	218		0	
670	OpenRead	384	106	0	k(5,,,,,)	2	
671	Explain	671	666	99	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
672	OpenEphemeral	385	1	0	k(1,B)	0	
673	Explain	673	666	0	CORRELATED LIST SUBQUERY 163	0	
674	OpenRead	293	93	0	19	0	
675	OpenRead	386	113	0	k(3,,,)	2	
676	Explain	676	673	52	SEARCH p USING COVERING INDEX ix_products_performance2 (<expr>=? AND active=?)	0	
677	NotNull	164	680	0		0	
678	SCopy	165	221	0		0	
679	Goto	0	681	0		0	
680	SCopy	164	221	0		0	
681	ClrSubtype	221	0	0		0	
682	IsNull	221	691	0		0	
683	Integer	1	222	0		0	
684	SeekGE	386	691	221	2	0	
685	IdxGT	386	691	221	2	0	
686	DeferredSeek	386	0	293		0	
687	IdxRowid	386	224	0		0	
688	MakeRecord	224	1	223	C	0	
689	IdxInsert	385	223	224	1	0	
690	Next	386	685	1		0	
691	Rewind	385	701	0		0	
692	Column	385	0	219		0	
693	IsNull	219	700	0		0	
694	Integer	1	220	0		0	
695	SeekGE	384	700	219	2	0	
696	IdxGT	384	700	219	2	0	
697	Column	384	3	223		0	
698	AggStep	0	223	218	sum(1)	1	
699	Next	384	696	0		0	
700	Next	385	692	0		0	
701	AggFinal	218	1	0	sum(1)	0	
702	Copy	218	215	0		0	
703	DecrJumpZero	216	704	0		0	
704	Return	214	666	1		0	
705	Copy	215	213	0		0	
706	NotNull	213	708	0		0	
707	Integer	0	213	0		0	
708	SCopy	166	225	0		0	
709	NotNull	225	711	0		0	
710	Integer	1	225	0		0	
711	Multiply	225	213	184		0	
712	Le	50	715	173		80	
713	Integer	1	185	0		0	
714	Goto	0	716	0		0	
715	Integer	0	185	0		0	
716	SCopy	174	186	0		0	
717	MakeRecord	178	9	225		0	
718	IdxInsert	376	225	178	9	0	
719	Return	151	0	0		0	
720	Null	0	164	175		0	
721	Integer	0	149	0		0	
722	Return	152	0	0		0	
723	Explain	723	477	0	UNION USING TEMP B-TREE	0	
724	Noop	387	6	0		0	
725	Integer	0	227	0		0	
726	Null	0	230	230		0	
727	Gosub	229	854	0		0	
728	OpenRead	279	93	0	19	0	
729	OpenRead	278	93	0	22	0	
730	OpenRead	277	49	0	7	0	
731	OpenRead	388	106	0	k(5,,,,,)	2	
732	Explain	732	723	216	SCAN p	0	
733	Rewind	279	786	0		0	
734	Column	279	4	225	1	0	
735	Ne	19	785	225	BINARY-8	84	
736	Column	279	18	213		128	
737	NotNull	213	740	0		0	
738	Rowid	279	225	0		0	
739	Goto	0	741	0		0	
740	Column	279	18	225		0	
741	Rowid	279	213	0		0	
742	Eq	213	785	225	BINARY-8	84	
743	Explain	743	723	45	SEARCH p_sub USING INTEGER PRIMARY KEY (rowid=?)	0	
744	Rowid	279	232	0		0	
745	SeekRowid	278	785	232		0	
746	Rowid	279	213	0		0	
747	Rowid	278	225	0		0	
748	Ne	225	785	213		83	
749	Column	278	4	225	1	0	
750	Ne	19	785	225	BINARY-8	84	
751	Explain	751	723	62	SEARCH s USING INDEX ix_stock_performance1 (product_id=?)	0	
752	Rowid	279	233	0		0	
753	SeekGE	388	785	233	1	0	
754	IdxGT	388	785	233	1	0	
755	DeferredSeek	388	0	277		0	
756	Rowid	279	225	0		0	
757	Column	388	0	213		0	
758	Ne	213	784	225	BINARY-8	83	
759	Rowid	279	231	0		0	
760	Compare	230	231	1	k(1,B)	0	
761	Jump	762	766	762		0	
762	Gosub	228	790	0		0	
763	Move	231	230	1		0	
764	IfPos	227	857	0		0	
765	Gosub	229	854	0		0	
766	Column	388	3	213		0	
767	AggStep	0	213	240	sum(1)	1	
768	Column	277	6	225		0	
769	NotNull	225	771	0		0	
770	Integer	0	225	0		0	
771	Column	388	3	244		0	
772	Multiply	244	225	213		0	
773	AggStep	0	213	241	sum(1)	1	
774	Column	388	2	213		0	
775	CollSeq	245	0	0	BINARY-8	0	
776	AggStep	0	213	242	min(1)	1	
777	Column	278	21	213	1	0	
778	CollSeq	245	0	0	BINARY-8	0	
779	AggStep	0	213	243	max(1)	1	
780	If	245	783	0		0	
781	Rowid	279	234	0		0	
782	Column	388	0	235		0	
783	Integer	1	226	0		0	
784	Next	388	754	0		0	
785	Next	279	734	0		1	
786	Gosub	228	790	0		0	
787	Goto	0	857	0		0	
788	Integer	1	227	0		0	
789	Return	228	0	0		0	
790	IfPos	226	792	0		0	
791	Return	228	0	0		0	
792	AggFinal	240	1	0	sum(1)	0	
793	AggFinal	241	1	0	sum(1)	0	
794	AggFinal	242	1	0	min(1)	0	
795	AggFinal	243	1	0	max(1)	0	
796	Le	50	791	240		80	
797	SCopy	234	178	0		0	
798	SCopy	240	179	0		0	
799	SCopy	240	180	0		0	
800	SCopy	241	246	0		0	
801	Function	2	246	181	round(2)	0	
802	SCopy	242	182	0		0	
803	BeginSubrtn	0	248	0		0	
804	Explain	804	723	0	CORRELATED SCALAR SUBQUERY 155	0	
805	Null	0	249	249		0	
806	Integer	1	250	0		0	
807	Null	0	251	252		0	
808	OpenRead	389	106	0	k(5,,,,,)	2	
809	Explain	809	804	53	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
810	Copy	235	253	0		0	
811	IsNull	253	819	0		0	
812	Integer	1	254	0		0	
813	Affinity	253	1	0	C	0	
814	SeekGE	389	819	253	2	0	
815	IdxGT	389	819	253	2	0	
816	Column	389	3	213		0	
817	AggStep	0	213	252	sum(1)	1	
818	Next	389	815	0		0	
819	AggFinal	252	1	0	sum(1)	0	
820	Copy	252	249	0		0	
821	DecrJumpZero	250	822	0		0	
822	Return	248	804	1		0	
823	Copy	249	183	0		0	
824	NotNull	183	826	0		0	
825	Integer	0	183	0		0	
826	BeginSubrtn	0	255	0		0	
827	Explain	827	723	0	CORRELATED SCALAR SUBQUERY 156	0	
828	Null	0	256	256		0	
829	Integer	1	257	0		0	
830	Null	0	258	259		0	
831	OpenRead	390	106	0	k(5,,,,,)	2	
832	Explain	832	827	53	SEARCH stock USING COVERING INDEX ix_stock_performance1 (product_id=? AND open=?)	0	
833	Copy	235	260	0		0	
834	IsNull	260	842	0		0	
835	Integer	1	261	0		0	
836	Affinity	260	1	0	C	0	
837	SeekGE	390	842	260	2	0	
838	IdxGT	390	842	260	2	0	
839	Column	390	3	262		0	
840	AggStep	0	262	259	sum(1)	1	
841	Next	390	838	0		0	
842	AggFinal	259	1	0	sum(1)	0	
843	Copy	259	256	0		0	
844	DecrJumpZero	257	845	0		0	
845	Return	255	827	1		0	
846	Copy	256	184	0		0	
847	NotNull	184	849	0		0	
848	Integer	0	184	0		0	
849	Integer	0	185	0		0	
850	SCopy	243	186	0		0	
851	MakeRecord	178	9	263		0	
852	IdxInsert	376	263	178	9	0	
853	Return	228	0	0		0	
854	Null	0	234	243		0	
855	Integer	0	226	0		0	
856	Return	229	0	0		0	
857	Rewind	376	871	0		0	
858	Column	376	0	264		0	
859	Column	376	1	265		0	
860	Column	376	2	266		0	
861	Column	376	3	267		0	
862	Column	376	4	268		0	
863	Column	376	5	269		0	
864	Column	376	6	270		0	
865	Column	376	7	271		0	
866	Column	376	8	272		0	
867	MakeRecord	264	9	263		0	
868	NewRowid	270	273	0		0	
869	Insert	270	263	273		8	
870	Next	376	858	0		0	
871	Close	376	0	0		0	
872	Return	148	474	0		0	
873	Noop	391	6	0		0	
874	Integer	0	275	0		0	
875	Null	0	278	278		0	
876	Gosub	277	1032	0		0	
877	OpenRead	271	93	0	35	0	
878	OpenRead	392	112	0	k(2,,)	2	
879	OpenRead	393	116	0	k(4,,,,)	2	
880	OpenRead	394	116	0	k(4,,,,)	2	
881	OpenRead	395	116	0	k(4,,,,)	2	
882	Explain	882	472	53	SEARCH p USING INDEX ix_products_performance1 (parent_product_id=?)	0	
883	Null	0	280	0		0	
884	Affinity	280	1	0	C	0	
885	SeekGE	392	988	280	1	0	
886	IdxGT	392	988	280	1	0	
887	DeferredSeek	392	0	271		0	
888	Column	271	9	281	0	0	
889	Eq	50	987	281	BINARY-8	84	
890	Column	271	20	281	0	0	
891	Ne	50	987	281	BINARY-8	84	
892	Column	271	4	281	1	0	
893	NotNull	281	895	0		0	
894	Integer	0	281	0		0	
895	Ne	19	987	281		80	
896	BeginSubrtn	0	283	0		0	
897	Explain	897	472	0	CORRELATED SCALAR SUBQUERY 152	0	
898	Null	0	284	284		0	
899	Integer	1	285	0		0	
900	OpenRead	396	112	0	k(2,,)	2	
901	Explain	901	897	51	SEARCH products USING COVERING INDEX ix_products_performance1 (parent_product_id=?)	0	
902	IdxRowid	392	286	0		0	
903	SeekGE	396	908	286	1	0	
904	IdxGT	396	908	286	1	0	
905	Integer	1	284	0		0	
906	DecrJumpZero	285	908	0		0	
907	Next	396	904	1		0	
908	Return	283	897	1		0	
909	IsNull	284	912	0		0	
910	Integer	1	281	0		0	
911	Goto	0	913	0		0	
912	Integer	0	281	0		0	
913	Ne	50	987	281	BINARY-8	80	
914	Explain	914	472	51	SEARCH quc_purchase USING COVERING INDEX ix_cache__quantity_unit_conversions_resolved_performance1 (product_id=? AND from_qu_id=? AND to_qu_id=?) LEFT-JOIN	0	
915	Integer	0	287	0		0	
916	IdxRowid	392	288	0		0	
917	Column	271	7	289		0	
918	Column	271	8	290		0	
919	Affinity	289	2	0	CC	0	
920	SeekGE	393	984	288	3	0	
921	IdxGT	393	984	288	3	0	
922	Integer	1	287	0		0	
923	Explain	923	472	51	SEARCH quc_consume USING COVERING INDEX ix_cache__quantity_unit_conversions_resolved_performance1 (product_id=? AND from_qu_id=? AND to_qu_id=?) LEFT-JOIN	0	
924	Integer	0	291	0		0	
925	IdxRowid	392	292	0		0	
926	Column	271	31	293		0	
927	IsNull	293	980	0		0	
928	Column	271	8	294		0	
929	Affinity	293	2	0	CC	0	
930	SeekGE	394	980	292	3	0	
931	IdxGT	394	980	292	3	0	
932	Integer	1	291	0		0	
933	Explain	933	472	51	SEARCH quc_price USING COVERING INDEX ix_cache__quantity_unit_conversions_resolved_performance1 (product_id=? AND from_qu_id=? AND to_qu_id=?) LEFT-JOIN	0	
934	Integer	0	295	0		0	
935	IdxRowid	392	296	0		0	
936	Column	271	34	297		0	
937	IsNull	297	976	0		0	
938	Column	271	8	298		0	
939	Affinity	297	2	0	CC	0	
940	SeekGE	395	976	296	3	0	
941	IdxGT	395	976	296	3	0	
942	Integer	1	295	0		0	
943	Once	0	945	0		0	
944	Gosub	148	474	0		0	
945	Explain	945	472	92	SCAN s LEFT-JOIN	0	
946	Integer	0	299	0		0	
947	Rewind	270	972	0		0	
948	IdxRowid	392	281	0		0	
949	Column	270	0	282		0	
950	Ne	282	971	281	BINARY-8	83	
951	Integer	1	299	0		0	
952	IdxRowid	392	279	0		0	
953	Compare	278	279	1	k(1,B)	0	
954	Jump	955	959	955		0	
955	Gosub	276	992	0		0	
956	Move	279	278	1		0	
957	IfPos	275	1035	0		0	
958	Gosub	277	1032	0		0	
959	Column	271	1	282		0	
960	CollSeq	309	0	0	BINARY-8	0	
961	AggStep	0	282	306	max(1)	1	
962	Column	270	1	282		0	
963	AggStep	0	282	307	sum(1)	1	
964	Column	270	5	282		0	
965	AggStep	0	282	308	sum(1)	1	
966	If	309	970	0		0	
967	IdxRowid	392	300	0		0	
968	Column	271	9	301	0	0	
969	Column	271	26	302	1	0	
970	Integer	1	274	0		0	
971	Next	270	948	0		1	
972	IfPos	299	975	0		0	
973	NullRow	270	0	0		0	
974	Goto	0	951	0		0	
975	Next	395	941	1		0	
976	IfPos	295	979	0		0	
977	NullRow	395	0	0		0	
978	Goto	0	942	0		0	
979	Next	394	931	1		0	
980	IfPos	291	983	0		0	
981	NullRow	394	0	0		0	
982	Goto	0	932	0		0	
983	Next	393	921	1		0	
984	IfPos	287	987	0		0	
985	NullRow	393	0	0		0	
986	Goto	0	922	0		0	
987	Next	392	886	0		0	
988	Gosub	276	992	0		0	
989	Goto	0	1035	0		0	
990	Integer	1	275	0		0	
991	Return	276	0	0		0	
992	IfPos	274	994	0		0	
993	Return	276	0	0		0	
994	AggFinal	306	1	0	max(1)	0	
995	AggFinal	307	1	0	sum(1)	0	
996	AggFinal	308	1	0	sum(1)	0	
997	SCopy	307	310	0		0	
998	NotNull	310	1000	0		0	
999	Integer	0	310	0		0	

</details>




Pre-orders start in Q4 2025! Sign up for our newsletter to receive: 🔍 Exclusive previews 📢 Release news 🔄 Access to updates 🎁 Special promotions. Don’t miss out – join our community today!



Can't get new Labelprinter webhook working Can't get new Labelprinter webhook working

According to the changelog of 4.5.0:

  • Label printer WebHooks now include a new property/field details (that's the full product/chore/battery/etc. object)

    • And also stock_entry (containing the full stock entry object) when printing a stock entry label

I would assume that I could find a fourth(details) and fifth(stock_entry) row using the network tab in the developer tools:

Am I doing something wrong? Double checked that I'm running 4.5.0, als changed to serverside generate, but that's harder to debug.


GS1 Barcode GS1 Barcode

Hi , I want to add some Products with a GS1 Barcode

The Problem is this Barcode is based with different Codes So in Fact only the first 14 Digits are the Product Code , Is there a possibility to add kind of Wildcards or to pass the different Information stored in the Barcode directly to Grocy ? Here is the exact exemple of the Barcode https://www.medtronic.com/content/dam/medtronic-com/us-en/hcp/product-identification/documents/medtronic-barcode-scanning-system-test.pdf


Barcode Camera workaround for http in a Browser Barcode Camera workaround for http in a Browser

Ever gotten stuck on the "Camera access if only possible when supported and allowed by your browser when grocy is servied via a secure connection" issue? Just wanted to put this out there for anyone that has a non-ssl setup, or is using the windows version with external access. Normally, due to browser security restrictions, accessing the camera for the barcode scanner only works when serving Grocy via a secure connection, but there is a workaround in Chrome!

There is a chrome://flags/ experiment called "Insecure origins treated as secure"

  1. Enable "Insecure origins treated as secure"

  2. Add your external access URL e.g., http://192.168.0.X:9283 or http://my-computer-name:4010

  3. Relaunch Chrome

This should allow you to access your Grocy setup in a browser with the camera enabled.






Can't Change Master Product Quantity Unit Can't Change Master Product Quantity Unit

So, like the title says, when I go into the master product, I can't change the product type. The other options just don't show up. I assumed this was because I had items in inventory, but even if I consume them, I still can't change it, even if I undo every purchase of them.

I can't seem to replicate this on the demo, or find an open issue. Has anyone else run into this? I would rather not have to recreate every product I changed my mind about a default quantity on. Windows version, but I relicated it on my Docker version as well.


Barcode Buddy App & External Scanner Barcode Buddy App & External Scanner

I have the Barcode Buddy app installed on an Android tablet and I have an external scanner connected via Bluetooth to the tablet.

I also have the Barcode Buddy app set up to use an external scanner.

However, when I scan a barcode with the external scanner, it doesn't scan, it just pops up the "Set Mode" menu.

That's the only thing scanning with an external scanner will do.

However, the external scanner works great when connected to my PC via Bluetooth. It send the correct data, etc... on PC.

So, what is going wrong with the Android app and how do I fix it?


Question About Adding New Products Question About Adding New Products

I just set up Grocy and Barcode Buddy.

I can scan a new (unknown) product in Barcode Buddy and add that product to Grocy.

The problem I'm running into is this:

If I add a new product via Barcode Buddy but then want to add either a unit or total price for the product in Grocy I have to "Purchase" the item in Grocy, which then increases my stock count by 1. So now instead of 1 product I have 2, and I have to go in and manually adjust the inventory.

Is there a way to add a new (unknown) product via Barcode Buddy that would also allow me to add a price?

Since I'm just getting started with the program I'd ideally like to come home from the grocery store, scan everything I've purchased, add them as new products (with their cost) and be done with it, instead of having to add them, purchase them (to add a price) and then adjust my inventory.



Suggestion on bar-code scanner for lazy people. Suggestion on bar-code scanner for lazy people.

Hello,

i have installed Grocy with the docker image last year, and start scanning everything in my house, with all details, because is really useful to know what you already have, what is near to end and so on...

All good, but as all thing to be useful must be maintained, or then is only another nice thing that will end in a mess (like is my inventory now)

What's the problem? We are a family, and not all (i can tell only me) want to spend too much effort on it.

So i'm trying to find the more easy and fast way to add and remove items from Grocy.

The easiest would be a simple wireless scanner docked in the warehouse with an easy switch on two basic way "Buy (Add to warehouse)" and "Consume (Remove from warehouse)" no matter of due date, just a bare warehouse quantity inventory, it's utopistic that my wife or sons spend time on insert even a due date, i must do something so easy and fast that even my cat could use....

Any suggestion about a good way to setup a thing like that?



Messed up my install. Help! Messed up my install. Help!

So, I'm an idiot, and in trying to get this set up, didn't change the path from "/path/to/grocy/config:/config" to an actual path. I am using Docker Desktop, with Portainer, on Windows 11.

I (almost certian) have managed to copy the Grocy files from - /path/to/grocy/config to E:\grocy\config\data. But I cannot for the life of me get my data back into Grocy. Changing the stack to:

---
services:
  grocy:
    image: lscr.io/linuxserver/grocy:latest
    container_name: grocy2
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - "/mnt/e/grocy/config:/config"
    ports:
      - 9284:80
    restart: unless-stopped

successfully deploys, but my username/password doesn't work, and admin/admin loads a blank database.

Changing the volume to - E:/grocy/config:/config wont deploy.

I would greatly appreciate any help.







Home Assistant Addon Cors ios Home Assistant Addon Cors ios

I have grocy installed as addon in Home Assistant. When I try to scan something from the Home Assistant ios app (grocy is inside the sidebar) I get this (I think cors related) issue/ error:

{"error_message":"Method not allowed. Must be one of: OPTIONS","error_details":{"stack_trace":"#0 /var/www/grocy/packages/slim/slim/Slim/Middleware/RoutingMiddleware.php(44): Slim\Middleware\RoutingMiddleware->performRouting()\n#1 /var/www/grocy/packages/slim/slim/Slim/MiddlewareDispatcher.php(129): Slim\Middleware\RoutingMiddleware->process()\n#2 /var/www/grocy/packages/slim/slim/Slim/Middleware/ErrorMiddleware.php(77): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()\n#3 /var/www/grocy/packages/slim/slim/Slim/MiddlewareDispatcher.php(129): Slim\Middleware\ErrorMiddleware->process()\n#4 /var/www/grocy/middleware/CorsMiddleware.php(27): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()\n#5 /var/www/grocy/packages/slim/slim/Slim/MiddlewareDispatcher.php(280): Grocy\Middleware\CorsMiddleware->__invoke()\n#6 /var/www/grocy/packages/slim/slim/Slim/MiddlewareDispatcher.php(73): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()\n#7 /var/www/grocy/packages/slim/slim/Slim/App.php(209): Slim\MiddlewareDispatcher->handle()\n#8 /var/www/grocy/packages/slim/slim/Slim/App.php(193): Slim\App->handle()\n#9 /var/www/grocy/app.php(133): Slim\App->run()\n#10 /var/www/grocy/public/index.php(45): require_once('...')\n#11 {main}","file":"/var/www/grocy/packages/slim/slim/Slim/Middleware/RoutingMiddleware.php","line":79}}

How can I fix it/ allow cors? I‘m connected to the Home Assistant via https to the public adress, not the local IP.

Thanks!


grocy, mealie and firefly3 integration grocy, mealie and firefly3 integration

I will be starting a self hosted setup soon. part of it will be a mealie-grocy-firefly3 stack.

Its my understanding that i can set it up to do this...

A. import recipes into mealie. this i do myself

B. i want it to automatically import ingredients from mealie, and if they are not in grocy i want it to add them into grocy

C. once that is up and running i want to integrate all into firefly3

what is the easiest way to interrogate all 3 in that order?




Access Log not showing External IP of attempted login Access Log not showing External IP of attempted login

Hello

Bit of topic, but I've got grocy set up behind a proxy, I'd like to set up fail2ban for catching failedlogin attemps

But looking at access.log I see the following - the redacted is my FQDN

192.168.1.145 - - [10/May/2025:10:59:29 +0000] "POST /login HTTP/1.1" 302 5 "[REDACTED]/login?invalid=true" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Mobile Safari/537.36"

192.168.1.145 - - [10/May/2025:10:59:29 +0000] "GET /login?invalid=true HTTP/1.1" 200 11128 "[REDACTED]/login?invalid=true" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Mobile Safari/537.36"

Am I missing something obvious or is this not possible?


Shopping list "Add this item to stock" uses "Quantity unit stock" and not "Default quantity unit purchase" to determine the amount to add. Shopping list "Add this item to stock" uses "Quantity unit stock" and not "Default quantity unit purchase" to determine the amount to add.

When my kid is with me, we go through 3 or 4 litres of milk in a week. When I'm alone, barely one litre. So I don't want milk on the shopping list when I still have enough, or it just gets old before I even get around to opening it. So I want the automatic shopping list adding to be triggered at 0.5 litres.

The problem

  • I want milk added to the shopping list when the amount is less than 500ml.

  • I buy milk in 2 or 3 litre packs.

  • I only want to see whether I have milk (parent). Child products will be hidden.

See this here in Private Demo

I found a way to set this up, but it requires both Round up quantity amounts to the nearest whole number to be set, and Default quantity unit purchase to be Pack for the Child products. If Default quantity unit purchase is Litre for the child, the "Shopping list to stock workflow" automation setting will add partial amounts.

How to replicate:

  • Shopping List Settings: set Round up quantity amounts to the nearest whole number

  • Create Parent and Child products

PARENT:

  • Set Disable own stock

  • Set Minimum stock amount to be anything less than the smallest Child Pack size (ie, 0.5 in my case)

  • Set a QU Conversion of 1 Pack = 1 Litre

  • Set Default quantity unit purchase to be Pack.

  • Set Quantity unit stock to be Litre (Pack is also OK, only because 1L = 1 Pack for the Minimum stock comparison)

  • Set Accumulate sub products min. stock amount, (has no effect as long as Child Min stock amounts are still 0)

CHILD:

  • Set QU Conversions: 1 Pack = 2L and 1Pack = 3L respectively

  • Set Default quantity unit purchase to be Pack.

  • Set Quantity unit stock to be Pack in order to match the Shopping list entry of 1 Pack. ***

TEST:

  • Consume All of any Child stock.

  • Go to Shopping list, note that 1 whole Pack is in the list. (Without the rounding or other settings it will be a partial pack. Feature requests for minimum purchase amounts will fix this.)

  • Select Add this item to stock. Note that selecting either the 2L or 3L child will result in 1 Pack being purchased.

  • Change the child Default quantity unit purchase to be Litres and repeat the test. Note that now the purchase will be fulfilled by PARTIAL packs of the child product. This means Autamatic Booking in the Shopping List to Stock Workflow won't work. Which leads me to:

Questions:

Why do the child products have to have Quantity unit stock = Pack for 1 whole Pack of a child to be purchased in order to fulfil the 1 Pack item in the shopping list? Shouldn't it be looking at Default quantity unit purchase? Is this a bug or by design?

Having the Child's Quantity unit stock = Pack makes setting Tare Weight Handling, Quick consume amount, and Quick Open Amount, quite tricky. Litres (or a weight measure for non-liquids) are much better for this. (My kitchen scales have a milk weight to volume setting, so I can easily use Tare to measure milk consumption)

Is there a better way already to do what I am trying to do?

Details (newbie level like I was this morning):

Go to Shopping list settings and apply Automatically add products that are below their defined min. stock amount to the shopping list

I have defined three products and their Quantity Units (QU):

Product Milk (parent) Milk 2L (child) Milk 3L (child)
Parent - Milk Milk
Minimum stock amount ^()* 0.5 na na
Quantity unit stock Litre *1 Litre *4 Litre *4
Default quantity unit purchase Pack*2 Pack Pack
Default quantity unit consume Litre Litre Litre
Quantity unit for prices Pack Pack Pack
Never show on stock overview -
Disable own stock - -
QU conversion ***Pack = 1L (***or 0.5L) *3 1 Pack = 2L 1 pack = 3L

*1 - Parent: Set QU Stock to Litre because this is what our 0.5 Minimum Stock is compared to in order to trigger adding to the shopping list

*2 - Parent: Set QU Purchase to Pack because we want a pack added to the shopping list. Without this we will get 0.5 Litres added to the shopping list to fulfil the minimum quantity.

*3 In order to be able to set QU Purchase to Pack, we need a QU Conversion between Pack and Litre.

Newbie tip: Enter a new product, press Save and Continue, and then the Product specific QU Conversions section will appear.

  • Consume All of any Child stock.

  • Note that, without rounding set in the Shopping List Settings, the following is added to the Shopping list.

The following conversion rates cause the following effects:

Parent Pack QU Conversion Qty added to shopping list Default Purchase Quantity
1 Pack = 3 Litres 0.1667 Packs (= 0.5 Litres, our minimum qty)
1 Pack = 2 Litres 0.25 Packs 0.5 ~ 0.5 Parent Packs = 0.5 Litre min qty = 0.25 of a 2L Child Pack or 0.3333 of a 3L Child Pack.
1 Pack = 1 Litre 0.5 Packs 0.5 ~ 0.5 Parent Packs = 0.5 Litre min qty = 0.25 of a 2L Child Pack or 0.3333 of a 3L Child Pack.
1 Pack = 0.5 Litre (~~~~*Minimum stock amount) 1 Pack 0.25 ~1 Parent Pack = 0.5 Litre = 0.25 of a 2L Child Pack (or 0.1667 or a 3L Child Pack.)

WITH ROUNDING:

To ensure a whole amount of packs added to the shopping list we need to:

  1. Set Round up quantity amounts to the nearest whole number in Shopping List Settings, or

  2. If you don't want the quantities rounded up because you like buying half sticks of celery, instead of applying the rounding setting, set 1 Pack = Minimum Stock Amount

Issue:

Because the child Quantity unit stock is set to Litre, with 1 Pack of the Parent Item now in the shopping list, clicking Add this item to stock attempts to fulfil the purchase with partial packs of the child products.

Select the child item you are purchasing:

Now depending on the size of the Parent Pack's conversion ratio, we get this:

The purchase amounts appear like this:

Parent Pack QU Conversion Qty added to shopping list with rounding up Default Purchase Quantity when selecting which size Child to fulfil the purchase:
1 Pack = 3 Litres 1 Pack 2L Child: 1.5 Packs (1 Parent Pack = 3 Litres = 1.5 x 2L Child Packs)
3L Child: 1 Pack (1 Parent = 3L = 1 Child Pack)
1 Pack = 2 Litres 1 Pack 2L Child: 1 Pack (1 Parent Pack = 3 Litres = 1.5 x 2L Child Packs)
3L Child: 0.6667 Packs (1 Parent = 1L = 0.5 x 2L Child)
1 Pack = 1 Litre 1 Pack 2L Child: 0.5 Packs (1 Parent = 3 Litres = 1.5 x 2L Child)
3L Child: 0.3333 Packs (1 Parent = 1L = 0.3333 x 3L Child)
1 Pack = 0.5 Litre 1 Pack 2L Child: 0.25 Packs (1 Parent = 0,5 Litres = 0.25 x 2L Child)
3L Child: 0.3337 Packs (1 Parent = 0,5 Litres = 0.3337 x 3L Child)

While it's easy just to type over this number (which is conveniently pre-selected), it means we can't use the "Shopping list to stock workflow" automation setting, or we'll get fractions of amounts. So the Child Product's Quantity unit stock needs to be set to Pack. Why not Default quantity unit purchase?


Grocy Brother Labelprinter Grocy Brother Labelprinter

Hello I have successfully created a webhook for the label printer in Grocy. Since my Grocy runs on Proxmox, I used an old Pi to create the webhook and sent it via USB to the Brother PT-P710BT. I use the philpem/printer-driver-ptouch. Does anyone have a script to create a DataMatrix code with the product name from the JSON post from Grocy? So far, I tried this, see below:

from flask import Flask, request, jsonify
from pystrich.datamatrix import DataMatrixEncoder
from PIL import Image, ImageDraw, ImageFont
import io
import logging
import subprocess

# Logging konfigurieren
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Flask-App
app = Flask(__name__)

# Druckername (muss bei dir mit 'lpstat -p' sichtbar sein)
PRINTER_NAME = 'Brother_PT-P710BT'

@app.route('/print', methods=['POST'])
def handle_print_job():
    try:
        data = request.get_json()
        grocycode = data.get('grocycode')
        product_name = data.get('product')

        if not grocycode or not product_name:
            logger.warning("Fehlende Daten im Request")
            return jsonify({'error': 'Missing grocycode or product name'}), 400

        logger.info(f"Empfangene Daten - Grocycode: {grocycode}, Produktname: {product_name}")

        # === Bildaufbau-Konstanten ===
        dpi = 180
        label_height_mm = 12
        label_height_px = int(label_height_mm / 25.4 * dpi)

        # Barcode generieren
        encoder = DataMatrixEncoder(grocycode)
        barcode_image = encoder.get_imagedata()
        barcode_pil = Image.open(io.BytesIO(barcode_image))

        # Barcode skalieren (quadratisch)
        barcode_height_px = int(label_height_px * 2 / 3)
        barcode_pil = barcode_pil.resize((barcode_height_px, barcode_height_px), Image.Resampling.LANCZOS)

        # Font laden
        font_size = int(label_height_px / 6)
        try:
            font = ImageFont.truetype("arial.ttf", font_size)
        except IOError:
            font = ImageFont.load_default()

        # Textgröße messen
        dummy_img = Image.new("RGB", (1, 1))
        draw_dummy = ImageDraw.Draw(dummy_img)
        text_bbox = draw_dummy.textbbox((0, 0), product_name, font=font)
        text_width = text_bbox[2] - text_bbox[0]
        text_height = text_bbox[3] - text_bbox[1]

        # Etikettenbreite berechnen
        label_width_px = max(barcode_height_px, text_width) + 20

        # Etikettenbild erstellen
        label_img = Image.new("RGB", (label_width_px, label_height_px), color="white")
        draw = ImageDraw.Draw(label_img)

        # Barcode platzieren
        barcode_x = (label_width_px - barcode_height_px) // 2
        barcode_y = (label_height_px * 2 // 3 - barcode_height_px) // 2
        label_img.paste(barcode_pil, (barcode_x, barcode_y))

        # Text platzieren
        text_x = (label_width_px - text_width) // 2
        text_y_start = label_height_px * 2 // 3
        text_y = text_y_start + (label_height_px // 3 - text_height) // 2
        draw.text((text_x, text_y), product_name, font=font, fill="black")

        # Temporär speichern
        temp_path = '/tmp/label_image.png'
        label_img.save(temp_path)
        logger.info(f"Etikett gespeichert unter {temp_path}")

        # Druckbefehl mit benutzerdefinierter Mediengröße
        command = ['lp', '-d', PRINTER_NAME, '-o', 'media=Custom.12x30mm', temp_path]

        # Druck ausführen
        subprocess.run(command, check=True)
        logger.info("Druckauftrag erfolgreich gesendet")

        return jsonify({'status': 'success'}), 200

    except subprocess.CalledProcessError as e:
        logger.error(f"Druckfehler: {e}")
        return jsonify({'error': 'Druck fehlgeschlagen'}), 500

    except Exception as e:
        logger.exception("Fehler beim Verarbeiten des Druckauftrags")
        return jsonify({'error': str(e)}), 500

# Server starten
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)


Windows Installation - Any way to import a CSV? Windows Installation - Any way to import a CSV?

I already have a pretty comprehensive inventory that can be exported to a csv. It includes a link to a picture, the barcode, item name, quantity, expiration date.

Photo Barcode Product Pieces Quantity_metric Unit_metric Level Expiry_date Shelf
/1696175116.jpeg 011210008427 Sriracha Sauce by Tabasco 1 full 46624 Pantry
/1707084683.jpeg 860001697803 Fly By Jing Sichuan Chili Crisp 1 6 oz full 09/11/2025 Pantry

I would love to not have to re-enter all of this by hand (1000+) items.

But... While I'm not a complete ludite, and I am planning on hosting this eventually (I have a web host/domain, I can handle Wordpress, etc), right now I need fast and brainless, so Grocy is set up on Windows 11 and I don't really understand scripting, although if I can get a really dumbed down explanation or something to feed into ChatGPT, I can make it happen.

There must be imports, right?



change defoult setting for cost calculation and correct misinterpreted input change defoult setting for cost calculation and correct misinterpreted input

is it possible to change the defoult setting in a product to use total cost (Gesamtpreis) becose the not defined (nicht spezifiziert) always uses th single price (Einzelpreis) functionality meaning if I insert 130g Rindsbullion it interprets the price as price=price/g not as price/130g=price/g, also I now have a lot of product that are interpreted as thousands of euro while they shuld only be a view euro and althoug I correctet a lot of products to use total price it semes to not change the already inserted inventory Ind I cant find a place to correct those




Need help with my grocy performance Need help with my grocy performance

Hi. My Grocy instance was quite slow for some time now, but its gradually getting worse. I thought its my growing database (its 11MB), but recently i have asked here about your db sizes and mine is not that bad as i thought.
A few months ago, i have found the developer sharing his grocy config, so i have added some optimisations from his php config to mine, but this has not helped - mainly because opcache is not included in linuxserver image (in fact i have asked LS devs and they added it today, https://github.com/linuxserver/docker-grocy/pull/95, but it feels that with Opcache it is even slower).
Anyhow, im looking for some tips regarding Grocy optimisation. Currently the pages can load for 10+ seconds when 1 person is using Grocy - in fact Lighthouse test timeouts on my instance - and gets completely unusable (504 timeouts) when 2 ppl are trying to use it simultaneously.
According to Portainer, my Grocy instance is using 450% of CPU and it all comes from dozens of "php-fpm: pool www" processes, each taking 4-7% of CPU. The server is a beast with 2 Xeon E5 CPUs (12 cores), 256GB of RAM and SSD drive.
My docker compose:

https://pastesio.com/docker-compose-2

my php-local.ini:
https://pastesio.com/php-localini

my grocy config:

https://pastesio.com/grocy-config


Created Grocy-Toolkit for Creating and Deleting Custom Entities Created Grocy-Toolkit for Creating and Deleting Custom Entities

Greetings!

I'm excited to share grocy-toolkit - a Docker-based CLI tool I developed to automate creating custom userentities in Grocy. If you've ever wanted to track kitchen equipment, meal prep sessions, ingredient substitutions, or outdoor cooking setups in Grocy, this makes it super easy.

Key features:

  • Pre-configured entity templates for kitchen management, food preservation, and outdoor cooking

  • Easily extendable to include your own custom userentities

  • Fine-grained control to include/exclude specific entities

  • Works with Docker or Deno runtime

  • Comprehensive documentation with real-world use cases

The tool handles all the API interactions to create the entity structures, fields, and properties - saving you hours of manual setup in the Grocy UI.

Check it out on GitHub: grocy-toolkit

I'd appreciate your feedback, suggestions, or contributions to make this even more useful for the Grocy community!


また作品を台無しにされたんですか?




Created two Grocy libraries for automation: node-grocy + node-red-contrib-grocy Created two Grocy libraries for automation: node-grocy + node-red-contrib-grocy

Greetings!

In the recent using of Node-RED and Grocy, I had AI write a Node.js wrapper for the Grocy API based on the API specification. With the wrapper, I had it write a collection of Node-RED nodes. After some back-and-forth, it came out ok.

I wanted to share the packages here in case anyone else wants to beta test them too:

node-grocy: A JavaScript client that wraps the Grocy API, making it easy to interact with Grocy from any Node.js application.

node-red-contrib-grocy: A set of Node-RED nodes built on top of node-grocy that let you create visual workflows

Feedback is always welcome!


Suggestions for improvements Suggestions for improvements

Congratulations on the excellent product.
For use with small controls, it is interesting that a resource is available to disable the consume all and consume one options, as well as the option to inhibit what is opened in the module with "Cannot be opened". The inhibition should not be just like a CSS update, but rather independent of it and permanent and not cached.

Another request is that the "Manage master data" module can be inhibited by user. Currently it is always enabled regardless of the user.


I Discovered Grocy and Set It Up with Pangolin for Remote Access - Have Some Security Questions I Discovered Grocy and Set It Up with Pangolin for Remote Access - Have Some Security Questions

Hey everyone!

I just discovered Grocy today and I'm absolutely thrilled with it. Since we wanted to access it together as a household, I immediately hosted it on my Docker server at home.

To make it accessible from anywhere, I used the Pangolin tool (https://github.com/fosrl/pangolin) so we can use it while on the go.

To simplify things even further, Pangolin offers the option to expose the API interface without additional authentication.

Now I have two questions:

  1. How secure is this setup overall?

  2. Is there a way to enhance the nginx access logs to show the IP addresses of those accessing the server, so I can monitor them through CrowdSec?

What do you think? Has anyone set up something similar or have advice on securing this kind of remote access setup?


Catch up on the EOFY Mini Series with QuickBooks experts. Watch on demand and learn how to automate, simplify, and scale your accounting workflows.

Grow your firm with QuickBooks, Watch on demand now



Just wanted to share this for anyone starting with Grocy — I wish I had something like this to begin with😄 Made these fun little cheat sheets for Grocy Master Data to make organizing way more fun & less robotic. Hope it helps someone! Just wanted to share this for anyone starting with Grocy — I wish I had something like this to begin with😄 Made these fun little cheat sheets for Grocy Master Data to make organizing way more fun & less robotic. Hope it helps someone!

🗃️ Locations

Location Description
🛁 Bathroom Closet Storage spa for 🧻 TP, 🪥 toothbrushes, 🧼 soaps & other self-care sidekicks. Smells good, feels clean, stays tidy 😌✨.
🙏 Temple Fridge Chilled haven for prasadam 🍛, offering milk 🥛, sweet treats 🍮 & fresh flowers 🌸. Keeps devotion cool & fragrant ❄️✨🙏.
🩹 Medical Cabinet Home base for pills, band-aids, ointments, thermometers, and emergency calm-down juice.
🧽 Kitchen Sink Cabinet Secret lair beneath the sink—home to mop sidekicks 🧽, spray wizards 💨, and grease-fighting legends 🫧.
🧺 Laundry Drawer Home to soaps, softeners & spin-cycle sidekicks 🧼🫧. Where stains fear to tread 🚿👕.
🧪 Lab Locker Stockpile of science stuff 🧫🔬—gloves, goggles, vials & mystery tools. Experiments begin here ⚗️🧠.
🧊 Freezer Home of the frozen 🧊! Keeps 🍦, 🥟, 🍗 & more chillin'. Usually hums like a cold ninja 🥷.
🧂 Pantry Dry goods HQ: 🍝, 🥫, 🍪 & more. No fridge drama—just calm, cool & crunchy vibes 😎🧺.
🥶 Fridge Cool zone for 🥛, 🥩, 🍰 & other chill vibes. Lives around 1–4°C ❄️.
🖇️ Office Drawer Secret snack bunker 🍫🍪🍬. Where productivity meets pretzels 🥨—guarded like treasure 🏴‍☠️.

🧮 Quantity Units

Unit Description
Bag For flexible bags—chips, flour, rice, or produce 🛍️
Bottle Liquids like water, milk, oil, or cleaners 🥤🧴
Box Cereal, frozen food, tissues—anything boxy 📦
Can Soda, beans, soup—sealed metal freshness 🥫
Pack Bundled items—snacks, sponges, screws
Piece Individual items—fruits, tools, batteries 🎯
Pouch Resealable packs for treats, spices, baby food 👜🧃
Roll Wound-up stuff—TP, towels, garbage liners 🧻
Sachet Tiny packets—coffee, condiments, shampoo ☕🧼
Tube Squeezables like toothpaste, glue, creams 🧴🪥

🧾 Product Groups

Group Description
🌶️ Spices & Condiments Masalas, sauces, pickles—flavor bombs 💥
🍚 Pantry Staples Grains, flours, pasta—dry survival essentials
🍫 Snacks & Sweets Chips, chocolates, biscuits—treat stash 😋
💊 Medicine & First Aid Band-aids, pills, creams—health kit
🖊️ Stationery & Office Pens, chargers, notes—productivity fuel ⚡
🧀 Fridge Essentials Milk, cheese, leftovers—fridge basics
🧂 Seasoning & Sauces Salt, sugar, marinades—chef’s kiss extras 😘
🧃 Drinks & Beverages Water, soda, coffee—hydration heroes
🧊 Frozen Goods Ice cream, frozen peas, meats—cold storage ❄️
🧪 Lab Supplies Vials, chemicals, glassware—science kit 🔬
🧴 Personal Care Soap, razors, shampoo—stay fresh 🧼
🧼 Cleaning & Laundry Detergent, sponges, surface sprays 🧽
🛠️ Tools & Hardware Tape, screwdrivers, kits—DIY zone
🌸 Freshness & Air Care Oils, sprays, candles—good vibes only 🌬️

📌 Task Categories

Category Description
📅 Appointments Dentist, haircut—don't miss it!
💼 Bills & Admin Paperwork, taxes—keep life legal 📜
⚙️ Maintenance Prevent problems before they start!
🤷‍♀️ Miscellaneous For stuff that fits nowhere else
🔧 Repairs Fix before it breaks!
🚗 Vehicle Oil, tires, cleanup—car TLC
🌳 Yardwork Mow, plant, clean—green space pride 🌱

🧹 Chores

Chore Description
⌚ Charge Smartwatch Don’t let it become a bracelet ⚡
✂️ Trim Nails / Grooming Quick tune-up for fresh vibes 💇‍♀️
🌀 Clean Fans No more dusty breeze 😷💨
🌫️ Clean Chimney Unleash the curry fumes safely 🍛🔥
🍫 Restock Snacks Refill the munchie vault 🍪
👗 Organize Wardrobe Tidy up, donate, repeat 👚✨
📱 Clean Phone Gallery Bye blurry selfies! 📸🗑️
🔧 Descale Appliances Banish mineral buildup 💧⚙️
🕯️ Replace Fresheners Keep the air dreamy 🌸🌬️
🕸️ Clean Spider Webs Evict 8-legged freeloaders 🕷️
🖥️ Backup Servers Reboot & secure that backend 🧑‍💻
🗑️ Clean Trash Bins No more science experiments 🚮🧼
🧺 Iron Clothes Fight wrinkles, boost confidence 💪
🧺 Laundry Day Time to spin! 👕🌀
🧺 Wash Bedsheets Fresh sheets, fresh sleep 🛏️
🧼 Clean Floor Mats Dust mites, be gone! 🧽
🧼 Clean Desk Cable chaos begone! 🖇️
🧽 Deep Clean Bathroom Scrub it all—shine mode: ON 🛁
🪞 Clean Mirrors Reflect success ✨👀
🚪 Clean Handles Sanitize the germ zone 🧴
🚬 Restock Cigarettes Respect the ritual 🔁🌀
🚰 Wash Water Bottles No haunted hydration ghosts 👻💧
🛒 Grocery Shopping Fuel the fridge! 🛒🥬
🛠️ Lubricate Hinges Silence the squeaks 🥷




Doesn't work quite as I thought it would Doesn't work quite as I thought it would

Hi,

I was testing using the live demo. When I marked a stock as all consumed, or moved a stock down to 0 I would have expected that item to be added to the shopping list, or to be asked to add it automatically.

Also vice versa, when in the Shopping List I would have expected the item when marked as purchased to be added or asked to be added into stock.

Instead the stock just gets removed.

Am I missing something? I fee like I am because the chocolate item is "greyed" out from clicking on its buttons since it has 0 stock and is also in the shopping list.







Docker, Docker Desktop & Grocy - How I Did It. Docker, Docker Desktop & Grocy - How I Did It.

Hello Everyone, I decided to post this "how I did it" so that any other noobs to docker, docker desktop, & Grocy will have an EASY step by step list of resources to follow for getting their Grocy up and running. I personally struggled mightily to find all all the puzzle pieces laid out in order. This worked for ME, there are probably other ways to get started. Please no criticisms, but definitely add to the knowledge if you have some!

THANKS and successful house hold management to us all!

Step 1: Install Docker & Docker Desktop following the directions at this link. Please note, for STEP 4 use the "permanent solution". You will have to reboot your machine so save or bookmark any resources you have up.

Step 2: Install Grocy using Docker following the directions at this link. Instructions stop at "Install Grocy using Portainer"

**BONUS (**so it's all in one place) Add Barcode Buddy to Docker, Add Recipe Buddy to Docker


Confused about different sizes or brands of the same thing, Sriracha Confused about different sizes or brands of the same thing, Sriracha

We usually buy a large 28oz bottle of Sriracha sauce, as an example. Today, a new bottle of Sriracha sauce showed up ant was only 18oz.

We don't care how much sauce is left in the bottle. We just care that we have some on hand. So we're not consuming the bottle fractionally. When we purchase it, it's unopened, and it goes into stock. When we open it, it's open, and in stock. When it's empty, we consume it and it's gone.

What if I had a half empty 28oz bottle, and a new unopened 18oz bottle? Do I need to create two products? Brands and stores price differently so if we opt to NOT care about store or brand, we'll never be able to track the best pricing based on the store or supplier.

The same would go for eggs, only with eggs, it would be easier to track number consumed. But how would we record that we purchased a dozen versus 60 eggs versus an 18 pack?

Confused.



Barcode buddy vs Android app AI unlock key Barcode buddy vs Android app AI unlock key

I've been using barcode buddy this whole time and just found out about the AI unlock key for the Android app. It has anybody used the AI unlock key. I got it off of the GitHub page for free to try it out before I give them 10 bucks for it but I wanted to see if anybody else has used it and knows if it's better than barcode buddy or not.

Tell me what you guys think of it. I'm sure there's a lot of you who use barcodes that I don't. ie alcohol ECT.


Couple questions related to Kids Couple questions related to Kids

Hey, I found this by accident looking for something else and this looks like a good fit for a few different things / needs.

It looks like I can add users (Adult and Kids) to this and create chores / assign them.

Is there a way to have a login for each kid and put it on their amazon kids tablets so they have their own personalized chore lists that they can check off as they do them from chores assigned?

Is there a way to hide the rest of the stuff so they can only see chores? When I open this up on my computer I do not see a login but just a general area of the chores. I see that you can filter by who they are assigned to but I am wanting to prevent a kid from checking off other kids chores.

This all possible?


Albert Heijn Plugin (alternative for OpenFoodFacts) Albert Heijn Plugin (alternative for OpenFoodFacts)

Hi all,

Since recently I installed and tried Grocy, and I'm trying to configure/develop it to my liking. One part of that is creating a plugin to retrieve product-data from Albert Heijn (Dutch supermarket firma). Since I've seen some Dutch people on this subreddit, I thought it might be useful to share this. This might get a bit technical.

Improvements that this plugin would bring:

  • Better names than OpenFoodFacts (based on the few products I've scanned now)

  • Pretty professional images (all pictures are exactly from the front with an even white background.

  • Products or product data that might not be present in OpenFoodFacts.

The developer of Grocy made a template for making new plugins, so I think it will not be hard for me or anyone to add this (unofficial) API.

API calls

I documented the necessary 3 API-calls in the link below. If you have Postman, you can also add the workspace to you Postman client (it automatically links tokes to requests). I also documented here how to create a virtual Android device to sniff the Albert Heijn API.

https://documenter.getpostman.com/view/10527213/2sAYkBsgYY

Basically you just get a token (you don't need an account) and then do a GET request per scanned barcode. Below is the output for a jar of Speculoos spread.

{
    "webshopId": 195783,
    "hqId": 796819,
    "title": "Lotus Biscoff Speculoos pasta creamy",
    "salesUnitSize": "720 g",
    "unitPriceDescription": "prijs per kg €8.18",
    "images": [
        {
            "width": 800,
            "height": 800,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=800x800_JPG_Q90&fileType=binary"
        },
        {
            "width": 400,
            "height": 400,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=400x400_JPG_Q85&fileType=binary"
        },
        {
            "width": 200,
            "height": 200,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=200x200_JPG_Q85&fileType=binary"
        },
        {
            "width": 48,
            "height": 48,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=48x48_GIF&fileType=binary"
        },
        {
            "width": 80,
            "height": 80,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=80x80_JPG&fileType=binary"
        }
    ],
    "priceBeforeBonus": 5.89,
    "orderAvailabilityStatus": "IN_ASSORTMENT",
    "mainCategory": "Ontbijtgranen, beleg",
    "subCategory": "Speculoospasta",
    "brand": "Lotus Biscoff",
    "shopType": "AH",
    "availableOnline": true,
    "isPreviouslyBought": false,
    "descriptionHighlights": "<p>Verras je boterham met deze lekker smeuige speculoos pasta van Lotus Biscoff. Geniet van de unieke speculoos smaak, eens wat anders dan chocopasta of jam!</p><p><ul><li>Pot bevat 720 gram aan speculoos pasta</li><li>Zonder kleurstoffen en toegevoegde smaakstoffen, geschikt voor veganisten</li><li>Gebruik deze speculoos pasta eens als ingredient tijdens het bakken</li><li>The original speculoos</li></ul></p>",
    "propertyIcons": [
        "vegan"
    ],
    "nix18": false,
    "isStapelBonus": false,
    "extraDescriptions": [],
    "isBonus": false,
    "descriptionFull": "",
    "isOrderable": true,
    "isInfiniteBonus": false,
    "isSample": false,
    "isSponsored": false,
    "isVirtualBundle": false,
    "discountLabels": []
}
{
    "webshopId": 195783,
    "hqId": 796819,
    "title": "Lotus Biscoff Speculoos pasta creamy",
    "salesUnitSize": "720 g",
    "unitPriceDescription": "prijs per kg €8.18",
    "images": [
        {
            "width": 800,
            "height": 800,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=800x800_JPG_Q90&fileType=binary"
        },
        {
            "width": 400,
            "height": 400,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=400x400_JPG_Q85&fileType=binary"
        },
        {
            "width": 200,
            "height": 200,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=200x200_JPG_Q85&fileType=binary"
        },
        {
            "width": 48,
            "height": 48,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=48x48_GIF&fileType=binary"
        },
        {
            "width": 80,
            "height": 80,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=80x80_JPG&fileType=binary"
        }
    ],
    "priceBeforeBonus": 5.89,
    "orderAvailabilityStatus": "IN_ASSORTMENT",
    "mainCategory": "Ontbijtgranen, beleg",
    "subCategory": "Speculoospasta",
    "brand": "Lotus Biscoff",
    "shopType": "AH",
    "availableOnline": true,
    "isPreviouslyBought": false,
    "descriptionHighlights": "<p>Verras je boterham met deze lekker smeuige speculoos pasta van Lotus Biscoff. Geniet van de unieke speculoos smaak, eens wat anders dan chocopasta of jam!</p><p><ul><li>Pot bevat 720 gram aan speculoos pasta</li><li>Zonder kleurstoffen en toegevoegde smaakstoffen, geschikt voor veganisten</li><li>Gebruik deze speculoos pasta eens als ingredient tijdens het bakken</li><li>The original speculoos</li></ul></p>",
    "propertyIcons": [
        "vegan"
    ],
    "nix18": false,
    "isStapelBonus": false,
    "extraDescriptions": [],
    "isBonus": false,
    "descriptionFull": "",
    "isOrderable": true,
    "isInfiniteBonus": false,
    "isSample": false,
    "isSponsored": false,
    "isVirtualBundle": false,
    "discountLabels": []
}
{
    "webshopId": 195783,
    "hqId": 796819,
    "title": "Lotus Biscoff Speculoos pasta creamy",
    "salesUnitSize": "720 g",
    "unitPriceDescription": "prijs per kg €8.18",
    "images": [
        {
            "width": 800,
            "height": 800,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=800x800_JPG_Q90&fileType=binary"
        },
        {
            "width": 400,
            "height": 400,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=400x400_JPG_Q85&fileType=binary"
        },
        {
            "width": 200,
            "height": 200,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=200x200_JPG_Q85&fileType=binary"
        },
        {
            "width": 48,
            "height": 48,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=48x48_GIF&fileType=binary"
        },
        {
            "width": 80,
            "height": 80,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=80x80_JPG&fileType=binary"
        }
    ],
    "priceBeforeBonus": 5.89,
    "orderAvailabilityStatus": "IN_ASSORTMENT",
    "mainCategory": "Ontbijtgranen, beleg",
    "subCategory": "Speculoospasta",
    "brand": "Lotus Biscoff",
    "shopType": "AH",
    "availableOnline": true,
    "isPreviouslyBought": false,
    "descriptionHighlights": "<p>Verras je boterham met deze lekker smeuige speculoos pasta van Lotus Biscoff. Geniet van de unieke speculoos smaak, eens wat anders dan chocopasta of jam!</p><p><ul><li>Pot bevat 720 gram aan speculoos pasta</li><li>Zonder kleurstoffen en toegevoegde smaakstoffen, geschikt voor veganisten</li><li>Gebruik deze speculoos pasta eens als ingredient tijdens het bakken</li><li>The original speculoos</li></ul></p>",
    "propertyIcons": [
        "vegan"
    ],
    "nix18": false,
    "isStapelBonus": false,
    "extraDescriptions": [],
    "isBonus": false,
    "descriptionFull": "",
    "isOrderable": true,
    "isInfiniteBonus": false,
    "isSample": false,
    "isSponsored": false,
    "isVirtualBundle": false,
    "discountLabels": []
}
{
    "webshopId": 195783,
    "hqId": 796819,
    "title": "Lotus Biscoff Speculoos pasta creamy",
    "salesUnitSize": "720 g",
    "unitPriceDescription": "prijs per kg €8.18",
    "images": [
        {
            "width": 800,
            "height": 800,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=800x800_JPG_Q90&fileType=binary"
        },
        {
            "width": 400,
            "height": 400,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=400x400_JPG_Q85&fileType=binary"
        },
        {
            "width": 200,
            "height": 200,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=200x200_JPG_Q85&fileType=binary"
        },
        {
            "width": 48,
            "height": 48,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=48x48_GIF&fileType=binary"
        },
        {
            "width": 80,
            "height": 80,
            "url": "https://static.ah.nl/dam/product/AHI_4354523130303035353736?revLabel=1&rendition=80x80_JPG&fileType=binary"
        }
    ],
    "priceBeforeBonus": 5.89,
    "orderAvailabilityStatus": "IN_ASSORTMENT",
    "mainCategory": "Ontbijtgranen, beleg",
    "subCategory": "Speculoospasta",
    "brand": "Lotus Biscoff",
    "shopType": "AH",
    "availableOnline": true,
    "isPreviouslyBought": false,
    "descriptionHighlights": "<p>Verras je boterham met deze lekker smeuige speculoos pasta van Lotus Biscoff. Geniet van de unieke speculoos smaak, eens wat anders dan chocopasta of jam!</p><p><ul><li>Pot bevat 720 gram aan speculoos pasta</li><li>Zonder kleurstoffen en toegevoegde smaakstoffen, geschikt voor veganisten</li><li>Gebruik deze speculoos pasta eens als ingredient tijdens het bakken</li><li>The original speculoos</li></ul></p>",
    "propertyIcons": [
        "vegan"
    ],
    "nix18": false,
    "isStapelBonus": false,
    "extraDescriptions": [],
    "isBonus": false,
    "descriptionFull": "",
    "isOrderable": true,
    "isInfiniteBonus": false,
    "isSample": false,
    "isSponsored": false,
    "isVirtualBundle": false,
    "discountLabels": []
}

I am a bit oversharing with this. However, but it took me long enough to get this to work and I want to save other developers the trouble. Also, if I eventually don't end up completing the plugin, somebody else has all necessary information needed to create it himself and share it back with the community.



Synchronize Tasks with Outlook Synchronize Tasks with Outlook

I am using grocy for some time and meanwhile our family's shopping list is accepted to be organized in grocy ;-)

As I currently try to synchronize Apps and expand using APIs, I was wondering if someone has already a best practise for syncing MS Outlook Tasks with Grocy tasks? (Syncing the calendar would be nice to follow, but this is my next step then...)

Currently I am reading some data from Grocy (Tasks, Shopping list) and am able to flush back task completion with home automation (FHEM). Therefore linking in Outlook would be nice to learn now...




Shopping list sort program and app Shopping list sort program and app

I've done some searches, but I'm new and wanted to ask the community before I submit a feature request. I'm looking for a clean solution for sorting the shopping list by both store and product group at the same time while using the android app. Specifically in shopping mode I want to see my list grouped by store and by product group in the store. One option may be to allow filtering so I can choose which store categories to see and only see one store or one store and those items without a default store.

I've found I can do it with the shopping list in the program (not the app), but it would also be helpful to be able to see the default store in the stock overview.

Anyways, maybe I'm overlooking something so I thought I would ask for advice as the next step before feature request.

*Editted before anyone responded because I answered a few of my original questions and thoughts.



grocy docker with npm grocy docker with npm

I got grocy set up so I can try to manage my apartment, but I'm struggling on having it interface with nginx proxy manager. It works so long as I address it by IP address, but not with a hostname from the reverse proxy.

When I try to use NPM to go to grocy.domain.tld, I just get a 502 Bad Gateway response. I can't seem to figure out if there's a config change I need to make to get this to work.
*edit*

It's installed via docker image from image: lscr.io/linuxserver/grocy:

Docker-compose.yml

services:
  grocy:
    image: lscr.io/linuxserver/grocy:latest
    container_name: grocy
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - /mnt/nvme1/docker_volumes/grocy/config:/config
    ports:
      - 9283:80
    restart: unless-stopped

nginx.conf

## Version 2024/05/27 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx/nginx.conf.sample
### Based on alpine defaults
# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.conf?h=3.20-stable
user abc;
# Set number of worker processes automatically based on number of CPU cores.
include /config/nginx/worker_processes.conf;
# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;
# Configures default error logger.
error_log /config/log/nginx/error.log;
# Includes files with directives to load dynamic modules.
include /etc/nginx/modules/*.conf;
# Include files with config snippets into the root context.
include /etc/nginx/conf.d/*.conf;
events {
# The maximum number of simultaneous connections that can be opened by
# a worker process.
worker_connections 1024;
}
http {
# Includes mapping of file name extensions to MIME types of responses
# and defines the default type.
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Name servers used to resolve names of upstream servers into addresses.
# It's also needed when using tcpsocket and udpsocket in Lua modules.
#resolver 1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001;
include /config/nginx/resolver.conf;
# Don't tell nginx version to the clients. Default is 'on'.
server_tokens off;
# Specifies the maximum accepted body size of a client request, as
# indicated by the request header Content-Length. If the stated content
# length is greater than this size, then the client receives the HTTP
# error code 413. Set to 0 to disable. Default is '1m'.
client_max_body_size 0;
# Sendfile copies data between one FD and other from within the kernel,
# which is more efficient than read() + write(). Default is off.
sendfile on;
# Causes nginx to attempt to send its HTTP response head in one packet,
# instead of using partial frames. Default is 'off'.
tcp_nopush on;
# all ssl related config moved to ssl.conf
# included in server blocks where listen 443 is defined
# Enable gzipping of responses.
#gzip on;
# Set the Vary HTTP header as defined in the RFC 2616. Default is 'off'.
gzip_vary on;
# Helper variable for proxying websockets.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Enable http2 by default for all servers
http2 on;
# Sets the path, format, and configuration for a buffered log write.
access_log /config/log/nginx/access.log;
# Includes virtual hosts configs.
include /etc/nginx/http.d/*.conf;
include /config/nginx/site-confs/*.conf;
}
daemon off;
pid /run/nginx.pid;

Newbie Parent Product question Newbie Parent Product question

Hi there. I am sorry if this is a really basic question, but I'm pretty confused with how parent/sub products work.

I think I understand the principle, but I'm going to lay it out here as I understand it so if I'm wrong, someone can correct me!

My understanding is that the parent products are the "thing" while the sub products are the "brand". So there's two different brands of chicken breast that we see in the shop, and we're happy to buy either and use either in our recipes, they're interchangeable. So the Parent Product is "Chicken Breast" and the sub product are Brand X Chicken Breast and Brand Y Chicken Breast. Okay, that makes sense to me: I can scan the barcode on either, it'll add Brand X and Brand Y, and they all count towards the grand total of the Chicken Breast parent product. That's right... right?

On the UI though, I am quite confused with how it looks. On the parent product it says I have "0 Pieces [symbol] 14 Pieces". Is there any way to just make it say "14 pieces"? Since the parent product is closer to a category than an item it feels weird that it's listed like that. I saw options for counting sub products under parents but I have no idea whether I'm supposed to click that on the sub or the parent (I just clicked on both).

Secondly, is there a way to group the sub products under the parent? As in, if we keep my earlier example, Brand X/Brand Y will be listed alphabetically separate from Chicken Breast. Is there any way to visually group them so all the sub products are listed under the parent products? I could rename them all but I am generally a bit baffled by all the options and terminology in Grocy so I wouldn't be surprised if there was something obvious I'm missing here.

Sorry for the newbie questions here, but I'd appreciate any help! Thank you!



Grocy works but can't access config files Grocy works but can't access config files

I have Grocy installed via Docker a week ago (v4.4.1). The server was brand new, with a fresh install of Ubuntu.

I pretty much used the default Docker CLI install instructions (at Docker Hub) which should create a /config directory on the server. However, there is no such directory. I also used WinSCP to try a search but nothing came up.

It's important to be able to do a backup of the database and to tweak a setting that I forgot to change (timezone) but after spending hours searching each directory I am coming up short here. The Docker folders don't have any mention of Grocy either. It runs fully, stores information, works quick in all aspects. However from a file perspective it's like it doesn't exist?

Anyone with a similar issue?



Problems with the Shopping List in Grocy Mobile app Problems with the Shopping List in Grocy Mobile app

Hello everyone,

I noticed that when I deactivate the "Disable Own Stock" option in the product master data, I can no longer add this item to the shopping list in the Grocy Mobile app. This is possible in the Android app and on the website.

Additionally, I cannot delete products from the shopping list because the "Are you sure you want to delete?" field disappears after a very short time.

I would also like to make a feature request in case the developer reads this.
Is it possible to add a shopping mode (similar to the Android app)?

Best regards from Germany,
Mueke

u/Windbeutel1337



[Help] Use API to add entry to shopping list without a product ID? [Help] Use API to add entry to shopping list without a product ID?

Update: I did more reading after I made this post and learned that I was using the wrong endpoint. I'll post working code in the next reply in case someone with the same question finds this post one day.

I now use grocy all the time to manage my shopping list and I like it a lot. I would like to write a Python script so that I can add arbitrary items to the shopping lists from the command line. This should be possible since both the grocy web interface and the android app allow you to add things to the shopping list without assigning a product to the shopping list entry. As long as you put something in the "notes" field then it gets added to the shopping list both from the web and in the android app.

My problem is that I can't figure out how to do this via the api in Python:

data = {
    "product_id": None,    # If I give a valid integer for this instead, it works as expected
    "list_id": 2,
    "product_amount": 5,
    "note": "This is a note with product_id set to None."
}

# Make the POST request
response = requests.post(url, headers=headers, json=data)

Running the above results in Status Code 400 and {"error_message":"No product id was supplied"} .

Does anyone know how to set up my request so that I can do this?



Einbinden der Open EAN/GTIN Database? Einbinden der Open EAN/GTIN Database?

Hallo,

ich habe Grocy erst ein paar Tage, bin aber schon total begeistert. Genaugenommen habe ich so etwas schon seit Jahren gesucht.
Was das Ganze jetzt noch ein bisschen besser machen würde wäre, wenn ich irgendwie die Open EAN/GTIN Database einbinden könnte.
Leider ist mein Englisch eine Katastrophe, aber wie ich es verstanden habe, sollte es wirklich irgendwie gehen, aber ich bekomme nicht heraus, wie.
Vielleicht könnt Ihr mir ja helfen.


Automatic due date suggestion stopped working Automatic due date suggestion stopped working

Hi, I'm new to Grocy, still figuring things out. During my testing I learned that if the product has "Default due days" set, then when purchasing it, "Due date" will be pre-filled.

Unfortunately that doesn't seem to work anymore. I've tried with several products, and I'm always asked to enter the Due date when purchasing. I've double checked that the products do indeed have "Default due days" set to a positive integer. My products dont have parents, and the "default due days" is set directly in them.

I'm sure it's an error on my part. Is there some other setting that affects due date calculation? I might have toggled it during my testing, but currently cannot recall anything.

Thanks for any suggestions!



Not able to create new location Not able to create new location

Ok so I looked in this subreddit and on other pages but I cant get it to work. I installed grocy as an AddOn in HomeAssistent. It all works as it should but I simply cannot create any new location. I can edit the Fridge-Location but thats it. The same goes for example for Userfields. If I open the demo, i can create a location with no problem, only in my instance (over the ingress in my HomeAssistent) it does not work. So I am turning to you, in hope and need of help :)

Thx in advance, for your help.


Recipe / Stock Control Recipe / Stock Control

Hi, new to Grocy, but really impressed so far, I am busy incorporating it fully in to Home Assist and our daily lives. but I wanted to try and do more with it if possible,

My main - query that I am looking for help to resolve is when I run a recipe to consume 0.07 of a box of cereal (ie 40g not the whole box) and 0.02 ltrs of milk - the milk works fine, but on the cereal for some reason it does correctly take 0.07 from the box but bizarre automatically purchases a new box. So if I had one box - instead of it dropping to 0.93 it actually goes to 1.93 any clues whats happening? and then try it a again it goes to 2.86

The second part is me wanting to do more.
I loved that it worked out the calorie total of the recipe - what 0.07 of the cereal box total calorie is + what 0.02 of milk is. So i decided to add my own field for the carbohydrate, protein and fat (in grams) each item to provide the same detail it does for calorie. is there any way to add these userdefined fields on to the recipe page?

And then if there is - then to go further more Finally when you get a consume report - so Samuel consumes the breakfast at 9:05am for example - is there any way for the report to have the relevant calorie and my added carbo, fat, protein consumed by eating that item - as it would be great to then have a by person daily total so i can put into my health app - it's a nightmare cataloguing meals in there.

Thanks



Grocy Userfield Images Grocy Userfield Images

I've added images as a userfield to chores. I'm trying to display them on a kiosk style application that I've written in Python.

When I make the request through the API I get back:

{
  "chore_image": "YWM0NXU2NGZxYjgxM3AxdW0yOGppOW0uanBn_cGlja3VwdG95cy5qcGc=",
  "Chore_Value": null
}

The image was uploaded through the grocy web application

The image saved on the file system is data/storage/userfiles/ac45u64fqb813p1um28ji9m.jpg

Can anyone help me with how I should be accessing this image using the response that i'm getting back from the API?


Is there a way to mark a product as spoiled but not consumed, aka thrown away? Is there a way to mark a product as spoiled but not consumed, aka thrown away?

Hello, newbie here tracking and starting to use Grocy.

I'm trying to figure out the best way to mark products that have been thrown away as expired or not consumable.

I see that I can mark them as spoiled in the consume action, which seems misleading. ( as i didn't consume, simply thrown away without consuming it)

Is there any better way?

Thanks in advance.




Grocy Web throwing errors Grocy Web throwing errors

Edit:

Managed to fix my issue, I took a backup with the database, deleted everything, redeployed the container and copied the DB back, all working.

Original Post:

Went to use the web app this morning and getting this error, not sure what the fix is (android app still works)

Error source:

\```

/app/www/helpers/BaseBarcodeLookupPlugin.php:8

\```

Error message:

\```

Cannot declare self-referencing constant self::PLUGIN_NAME

\```

Stack trace:

\```

#0 /app/www/services/StockService.php(1759): [constant expression]()

#1 /app/www/services/StockService.php(599): Grocy\Services\StockService->LoadExternalBarcodeLookupPlugin()

#2 /app/www/controllers/StockController.php(21): Grocy\Services\StockService->GetExternalBarcodeLookupPluginName()

#3 /app/www/packages/php-di/php-di/src/Definition/Resolver/ObjectCreator.php(129): Grocy\Controllers\StockController->__construct()

#4 /app/www/packages/php-di/php-di/src/Definition/Resolver/ObjectCreator.php(56): DI\Definition\Resolver\ObjectCreator->createInstance()

#5 /app/www/packages/php-di/php-di/src/Definition/Resolver/ResolverDispatcher.php(60): DI\Definition\Resolver\ObjectCreator->resolve()

#6 /app/www/packages/php-di/php-di/src/Container.php(354): DI\Definition\Resolver\ResolverDispatcher->resolve()

#7 /app/www/packages/php-di/php-di/src/Container.php(136): DI\Container->resolveDefinition()

#8 /app/www/packages/slim/slim/Slim/CallableResolver.php(135): DI\Container->get()

#9 /app/www/packages/slim/slim/Slim/CallableResolver.php(97): Slim\CallableResolver->resolveSlimNotation()

#10 /app/www/packages/slim/slim/Slim/CallableResolver.php(70): Slim\CallableResolver->resolveByPredicate()

#11 /app/www/packages/slim/slim/Slim/Routing/Route.php(345): Slim\CallableResolver->resolveRoute()

#12 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(73): Slim\Routing\Route->handle()

#13 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(73): Slim\MiddlewareDispatcher->handle()

#14 /app/www/packages/slim/slim/Slim/Routing/Route.php(321): Slim\MiddlewareDispatcher->handle()

#15 /app/www/packages/slim/slim/Slim/Routing/RouteRunner.php(74): Slim\Routing\Route->run()

#16 /app/www/middleware/LocaleMiddleware.php(16): Slim\Routing\RouteRunner->handle()

#17 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(280): Grocy\Middleware\LocaleMiddleware->__invoke()

#18 /app/www/middleware/AuthMiddleware.php(77): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()

#19 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(280): Grocy\Middleware\AuthMiddleware->__invoke()

#20 /app/www/packages/slim/slim/Slim/Middleware/RoutingMiddleware.php(45): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()

#21 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(129): Slim\Middleware\RoutingMiddleware->process()

#22 /app/www/packages/slim/slim/Slim/Middleware/ErrorMiddleware.php(77): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()

#23 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(129): Slim\Middleware\ErrorMiddleware->process()

#24 /app/www/middleware/CorsMiddleware.php(27): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()

#25 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(280): Grocy\Middleware\CorsMiddleware->__invoke()

#26 /app/www/packages/slim/slim/Slim/MiddlewareDispatcher.php(73): Psr\Http\Server\RequestHandlerInterface@anonymous->handle()

#27 /app/www/packages/slim/slim/Slim/App.php(209): Slim\MiddlewareDispatcher->handle()

#28 /app/www/packages/slim/slim/Slim/App.php(193): Slim\App->handle()

#29 /app/www/app.php(133): Slim\App->run()

#30 /app/www/public/index.php(45): require_once('...')

#31 {main}

\```

System info:

\```

{

"grocy_version": {

"Version": "4.4.1",

"ReleaseDate": "2025-01-31"

},

"php_version": "8.3.15",

"sqlite_version": "3.45.3",

"db_version": 250,

"os": "Linux 6.6.68-Unraid #1 SMP PREEMPT_DYNAMIC Tue Dec 31 13:42:37 PST 2024 x86_64",

"client": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/133.0.0.0 Safari\/537.36 Edg\/133.0.0.0"

}

\```



Dropdowns are missing entries (Default quantity...) Dropdowns are missing entries (Default quantity...)

Moin,

I'm new to GROCY but willing to use it heavily. But I already struggle adding Items. I have Grocy 4.4.1 installed on a public web sever. (Linux 5.15.0 #141 Ubuntu) - I'm using Safari on Mac and iOS.

When I user iOS Safari and scan a product, it gets elementary information from the web. But a few things I cannot choose or change.

Quantity unit stock - fine, choose from everything I added:

But Default quantity unit purchase and all other quantity fields are fixed:

I also cannot change products at a later stage... that might be logical. If it used to be packs of Jam and I still have a few in my stock, I shouldn't be able to make it now glasses... or?

So is this an expected behavior, or is there something messed up with my installation?


How do I set expired stock to not count as stocked? How do I set expired stock to not count as stocked?

Say I have one opened jug of milk in the system, but it is expired. I want it to automatically be placed on the shopping list based on my "keep x in stock" setting, which can be done by setting it to not count any expired stock. But I can't seem to find this feature or any talk or questions about it online. This seems like most straight forward automated way to me but, the complete lack of anyone online mentioning this has me wondering. Am I coming about this from the wrong angle? Is there a better way?

EDIT: I feel I should clarify just in case, that this is not the default behavior, which was a little surprising to me


Bug or user error? Not able to add new stock/purchase Bug or user error? Not able to add new stock/purchase

Hey all,

I've been using Grocy as a HA add-on (on a Pi-4) and have come across a problem recently where I can't add any stock. When I use the purchase or inventory screen (or even try to add through shopping list) I'm left with an indeifinte loading mouse.

I'm not sure if this started following an update on HA/Grocy, but would say it's been going on for ~2weeks at least.

I can still remove items from stock, add new products to my master list, merge products no problem.

I have tried restarting HA and restarting Grocy.

My cleverer, more tech savier husband did some digging and believes he's narrowed it down to a bug relating to the location field in the purchases screen, but I don't know why or how to fix it.

When making an entry the console returns an error:

purchase.js?v=4.3.0:302 Uncaught TypeError: Cannot read properties of undefined (reading 'SetId')

at purchase.js?v=4.3.0:302:48

at xhr.onreadystatechange (grocy.js?v=4.3.0:17:7)

(screenshot here)

I'm sure that deleting Grocy and re-installing it would fix the issue, but I'm not sure how to save/copy the database in Home Assistant.

Anyone familiar with this bug or have any solutions that aren't reverting to a HA backup?

Thanks in advance!





How to fix time issues with Grocy (hosted on VPS) How to fix time issues with Grocy (hosted on VPS)

I just had to figure this out on my own. Grocy doesn't have a way to designate the time zone that it uses, so my chore times were all out of whack.

I host my Grocy on a VPS so I went digging. First I tried using .htaccess to set the time zone, that didn't work. Then I tried a php.ini file at the root of the subdomain, and then set the time zone at the system level. Still didn't change anything. Grocy was still using UTC instead of my local time zone.

Then I realised that Grocy was getting the time zone from the php.ini file located deep in the system (this was news to me, maybe it's obvious to others).

I ran this command:

php --ini | grep "Loaded Configuration File"

And it gave me a path to the actual php.ini file:

Loaded Configuration File: /usr/local/php82/lib/php.ini

Did some editing with nano /usr/local/php82/lib/php.ini and found this line (use ctrl+w and type timezone to get to this part easily):

[Date]
; Defines the default timezone used by the date functions
; https://php.net/date.timezone
date.timezone = "Etc/UTC"

Changed the value from "Etc/UTC" to "America/Los_Angeles" and now time is working as expected!

This might be super basic to some of you, and I'm not sure if it applies to people that run Grocy with Docker, but I'm putting this out there in case someone else is having the same issue and is bashing their head against a brick wall like I was an hour ago.



To all Docker users: grocy/grocy-docker will be retired, migrate to linuxserver/docker-grocy