#!/usr/bin/env bash # Source the common utils and the environment variable loader source load_common_and_env.sh # (Attempt to) take variable we need DOMAIN=${GROCY_DOMAIN} API_KEY=${GROCY_API_KEY} LIST_ID=${GROCY_LIST_ID} # Curl function for API requests perform_curl() { local ROUTE=$1 local METHOD=$2 local DATA=${3:-""} if [ "$METHOD" = "GET" ]; then curl --silent -X 'GET' "${DOMAIN}${ROUTE}" -H 'accept: application/json' -H "GROCY-API-KEY: ${API_KEY}" elif [ "$METHOD" = "POST" ]; then curl --silent -X 'POST' "${DOMAIN}${ROUTE}" -H 'Content-Type: application/json' -H "GROCY-API-KEY: ${API_KEY}" --data-raw "$DATA" fi } # Clear the shopping list, because the api only supports adding items and it is way more cumbersome to adjust to that than just doing it from scratch each time echo "Clearing list..." perform_curl "/api/stock/shoppinglist/clear" "POST" "{ \"list_id\": ${LIST_ID}, \"done_only\": false }" echo "Fetching product stock..." # Fetching product stock list STOCK_JSON=$(perform_curl "/api/stock" "GET") echo "$STOCK_JSON" | jq '.' > stock.json echo "Fetching missing products..." # Fetching missing products MISSING_PRODUCTS_JSON=$(perform_curl "/api/stock/volatile?due_soon_days=0" "GET") echo "$MISSING_PRODUCTS_JSON" | jq '.missing_products' > missing_products.json # Combining lists jq -s add stock.json missing_products.json > combined_products.json rm stock.json missing_products.json # Cleanup echo "Fetching items already on the default shopping list..." # Fetch current items on the default shopping list DEFAULT_SHOPPING_LIST_JSON=$(perform_curl "/api/objects/shopping_list??query%5B%5D=shopping_list_id%3D1" "GET") echo "$DEFAULT_SHOPPING_LIST_JSON" > default_shopping_list.json echo "Processing products..." # Iterate over each product to check MaxStockAmount jq -c '.[]' combined_products.json | while read i; do PRODUCT_ID=$(echo $i | jq '.product.id') PRODUCT_NAME=$(echo $i | jq -r '.product.name') # Extract product name CURRENT_AMOUNT=$(echo $i | jq '.amount_aggregated' | sed 's/null/0/') # Treat null as 0 # Fetch MaxStockAmount value and convert to number if not null MAX_STOCK_AMOUNT_JSON=$(perform_curl "/api/userfields/products/${PRODUCT_ID}" "GET") MAX_STOCK_AMOUNT_RAW=$(echo "$MAX_STOCK_AMOUNT_JSON" | jq '.MaxStockAmount') # Check if MaxStockAmount is not null and handle accordingly if [ "$MAX_STOCK_AMOUNT_RAW" != "null" ]; then MAX_STOCK_AMOUNT=$(echo "$MAX_STOCK_AMOUNT_RAW" | jq 'tonumber') else # Use min_stock_amount from the product details if MaxStockAmount is null MIN_STOCK_AMOUNT=$(echo $i | jq '.product.min_stock_amount') MAX_STOCK_AMOUNT=$MIN_STOCK_AMOUNT # Use Grocy internal min amount as the fallback fi # Fetch how much of the product is already on the default shopping list AMOUNT_ON_DEFAULT_LIST=$(jq --arg PRODUCT_ID "$PRODUCT_ID" \ '[.[] | select(.product_id | tostring == $PRODUCT_ID) | .amount] | add' default_shopping_list.json) # Adjust PRODUCT_AMOUNT_TO_ADD considering the amount already on the list if [ -z "$AMOUNT_ON_DEFAULT_LIST" ] || [ "$AMOUNT_ON_DEFAULT_LIST" = "null" ]; then AMOUNT_ON_DEFAULT_LIST=0; fi # Calculate the total desired amount considering amounts on both shopping lists REMAINING_AMOUNT_TO_ADD=$(echo "$MAX_STOCK_AMOUNT - $CURRENT_AMOUNT - $AMOUNT_ON_DEFAULT_LIST" | bc -l) PRODUCT_AMOUNT_TO_ADD=$(printf "%.0f" "$REMAINING_AMOUNT_TO_ADD") # Handle the "-0" case by converting it to "0" if [ "$PRODUCT_AMOUNT_TO_ADD" == "-0" ]; then PRODUCT_AMOUNT_TO_ADD="0" fi if [ "$PRODUCT_AMOUNT_TO_ADD" -gt 0 ]; then # Original logic to add to the list if PRODUCT_AMOUNT_TO_ADD is positive echo "Adjusting and adding \"$PRODUCT_NAME\" (ID: $PRODUCT_ID) to the shopping list, amount: $PRODUCT_AMOUNT_TO_ADD" # Add or adjust the product amount on the secondary shopping list perform_curl "/api/stock/shoppinglist/add-product" "POST" "{ \"product_id\": ${PRODUCT_ID}, \"list_id\": ${LIST_ID}, \"product_amount\": ${PRODUCT_AMOUNT_TO_ADD}, \"note\": \"Bereits da: ${CURRENT_AMOUNT} + ${AMOUNT_ON_DEFAULT_LIST}\" }" fi done rm combined_products.json default_shopping_list.json # Final cleanup echo "Process completed."