Python runner unavailable" on Docker & Help converting Pricing Logic to JavaScript

Hi everyone,

I am running a self-hosted n8n instance via easypanel (version 2.3.2). I am building a workflow to calculate pricing for an e-commerce platform (Mercado Livre), but I hit a roadblock.

1. The Problem I have a complex Python script that calculates the ideal selling price by iterating through different shipping cost ranges (matrix of 22 weights x 8 price ranges) to find a specific profit margin.

When I try to run it in the Code Node, I get this error: Error: Python runner unavailable: Python 3 is missing from this system

I understand I probably need to build a custom Docker image to include Python, but I would prefer to solve this using JavaScript (native Code Node) to keep my setup simple.

2. What I need I tried converting my logic to JavaScript, but I am struggling with data parsing (Brazilian number formats like 1.200,50 or 8 400 with spaces) and the iterative logic structure.

The Logic I need to implement:

  1. Input: I receive a list of items with Cost, Weight, Taxes, etc.

  2. Freight Matrix: I have a constant array of freight costs (22 weight rows x 8 price columns).

  3. Simulation Loop:

    • For each product, I need to test different “Price Ceilings” (e.g., 29.99, 49.99, 79.99…).

    • If I sell at that ceiling, using the corresponding freight, do I achieve a 15% margin?

    • If yes, calculate the exact price.

    • If no, try the next (more expensive) bracket.

3. Sample Input Data (JSON)

JSON

[
  {
    "SKU": "322",
    "SELL_IN": "133,14",
    "PESO_EM_G": "8 400,00",
    "Packing": "4,5",
    "ComissĂŁo": "0,115",
    "Imposto": "0,045",
    "TAXALAWEB": "0,1",
    "ACOS": "0,1"
  }
]

4. My current Python Logic (which works logic-wise but not in n8n) Could someone help me translate this logic into a robust JavaScript Code Node that handles the number parsing correctly?

Python

# Pseudo-code of what I'm trying to do
def calculate(item):
    # 1. Parse numbers (remove spaces, swap comma for dot)
    weight = parse_br_number(item.weight) 
    cost = parse_br_number(item.cost)
    
    # 2. Get Freight List based on Weight
    freight_list = get_freight_row(weight) # Returns array of 8 costs
    
    # 3. Iterative Check
    price_ceilings = [29.99, 49.99, 79.99, ...]
    
    for i, ceiling in enumerate(price_ceilings):
        freight = freight_list[i]
        # Check margin
        margin = (ceiling - cost - freight - taxes) / ceiling
        
        if margin >= 0.15:
            # Calculate exact price
            final_price = (cost + freight) / (1 - taxes - 0.15)
            return final_price
            
    return fallback_price

Thanks in advance for any help!

Hey! I got you covered with the JavaScript version.

The main challenge is parsing those Brazilian number formats. Here’s the full solution:

// Helper function to parse Brazilian numbers
function parseBRNumber(str) {
  if (!str) return 0;
  // Remove spaces, replace comma with dot
  return parseFloat(str.toString().replace(/\s/g, '').replace(',', '.'));
}

const items = $input.all();
const results = [];

// Define your freight matrix (22 weights x 8 price columns)
// Example structure - replace with your actual data
const freightMatrix = {
  '500': [10, 12, 15, 18, 22, 25, 30, 35],
  '1000': [12, 14, 17, 20, 24, 28, 33, 38],
  // ... add all your weight ranges
  '8400': [25, 28, 32, 36, 42, 48, 55, 62]
};

const priceCeilings = [29.99, 49.99, 79.99, 99.99, 149.99, 199.99, 299.99, 399.99];

for (const item of items) {
  const sku = item.json.SKU;
  const cost = parseBRNumber(item.json.SELL_IN);
  const weight = parseBRNumber(item.json.PESO_EM_G);
  const packing = parseBRNumber(item.json.Packing);
  const commission = parseBRNumber(item.json.ComissĂŁo);
  const tax = parseBRNumber(item.json.Imposto);
  const taxaLaweb = parseBRNumber(item.json.TAXALAWEB);
  const acos = parseBRNumber(item.json.ACOS);
  
  const totalTaxRate = commission + tax + taxaLaweb + acos;
  
  // Find closest weight bracket
  const weightKeys = Object.keys(freightMatrix).map(Number).sort((a,b) => a-b);
  const weightBracket = weightKeys.find(w => weight <= w) || weightKeys[weightKeys.length-1];
  const freightList = freightMatrix[weightBracket];
  
  let finalPrice = null;
  
  // Test each price ceiling
  for (let i = 0; i < priceCeilings.length; i++) {
    const ceiling = priceCeilings[i];
    const freight = freightList[i];
    
    // Check if this ceiling gives us 15% margin
    const margin = (ceiling - cost - freight - packing - (ceiling * totalTaxRate)) / ceiling;
    
    if (margin >= 0.15) {
      // Calculate exact price to hit 15% margin
      finalPrice = (cost + freight + packing) / (1 - totalTaxRate - 0.15);
      break;
    }
  }
  
  // If no ceiling worked, use highest bracket
  if (!finalPrice) {
    const lastFreight = freightList[freightList.length - 1];
    finalPrice = (cost + lastFreight + packing) / (1 - totalTaxRate - 0.15);
  }
  
  results.push({
    json: {
      SKU: sku,
      calculated_price: finalPrice.toFixed(2),
      original_cost: cost,
      weight: weight
    }
  });
}

return results;

Just update the freightMatrix with your actual 22x8 data and you’re good to go!

I actually built pricing automation for e-commerce clients before, so if you need help optimizing this further or want to add more logic (like competitor pricing checks), feel free to reach out.

1 Like

hi, ty for your suport and dedication. But i already resolve this, now i looking into making python works in my n8n, because the automation that i’am fixing have so many codes and detals, which makes it more easy recover than making one by one for the beginning. Again ty very much for that, bye!

@Laweb Good Luck to you. Mark as solution to close this chat.