1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Anuncie Aqui
    Anuncie aqui você Também: fdantas@4each.com.br

[Python] ERPNext Server Script API call returns 200 but does not update database or return...

Discussão em 'Python' iniciado por Stack, Setembro 17, 2025.

  1. Stack

    Stack Membro Participativo

    I’m trying to update Sales Order Items in ERPNext using a Server Script of type API.

    I want to hit the endpoint from Postman and update custom fields (custom_buying_price, custom_qty) in the Sales Order Item child table.

    Here’s my script:

    def custom_update_so_items(sales_order, items=None):
    """
    Update Sales Order items (qty, rate, custom fields) with validations.
    Works for draft and submitted Sales Orders.
    """
    try:
    # Parse JSON items if string
    if isinstance(items, str):
    items = frappe.parse_json(items)
    if not items:
    return {"status": "error", "message": "Parameter 'items' is required."}

    # Load Sales Order
    so = frappe.get_doc("Sales Order", sales_order)
    so.flags.ignore_validate_update_after_submit = True
    so.flags.ignore_permissions = True
    so.flags.ignore_mandatory = True

    # Map child rows by docname
    by_name = {d.name: d for d in so.items}

    # Update fields
    for it in items:
    rowname = (it or {}).get("docname")
    if not rowname or rowname not in by_name:
    continue

    row = by_name[rowname]

    # Update standard fields
    if it.get("qty") is not None:
    row.qty = frappe.utils.flt(it["qty"])
    if it.get("rate") is not None:
    row.rate = frappe.utils.flt(it["rate"])

    # Update custom fields
    if it.get("custom_buying_price") is not None:
    row.custom_buying_price = frappe.utils.flt(it["custom_buying_price"])
    if it.get("custom_margin_amount") is not None:
    row.custom_margin_amount = frappe.utils.flt(it["custom_margin_amount"])
    if it.get("custom_margin_percentage") is not None:
    row.custom_margin_percentage = frappe.utils.flt(it["custom_margin_percentage"])

    # Recalculate amount
    row.amount = row.qty * row.rate

    # Save document
    so.save(ignore_permissions=True)
    frappe.db.commit()

    # If custom fields still not updated, try direct DB update
    for it in items:
    rowname = (it or {}).get("docname")
    if not rowname:
    continue

    updates = {}
    if it.get("custom_buying_price") is not None:
    updates["custom_buying_price"] = frappe.utils.flt(it["custom_buying_price"])
    if it.get("custom_margin_amount") is not None:
    updates["custom_margin_amount"] = frappe.utils.flt(it["custom_margin_amount"])
    if it.get("custom_margin_percentage") is not None:
    updates["custom_margin_percentage"] = frappe.utils.flt(it["custom_margin_percentage"])

    if updates:
    frappe.db.set_value("Sales Order Item", rowname, updates)

    frappe.db.commit()

    return {"status": "ok", "name": so.name}

    except Exception as e:
    frappe.log_error(frappe.get_traceback(), "custom_update_so_items_simple")
    return {"status": "error", "message": str(e)}


    What I tried using Postman

    POST https:///api/method/update_so_items_with_custom_fields

    Headers: Content-Type: application/json + Authorization Token

    Body:

    {
    "sales_order": "Ashish-1990",
    "items": [
    {
    "docname": "actual_docname_from_sales_order_item",
    "qty": 5,
    "rate": 120,
    "custom_buying_price": 100,
    "custom_margin_amount": 20,
    "custom_margin_percentage": 16.7
    }
    ]
    }

    Continue reading...

Compartilhe esta Página