Issue with the arguments of a Python function when it is called

I have some Doctypes in a custom App. One of them work as Production Order. In that Doctype, when I click on the Start button to make a material transfer, I get an error, which is the following:

500 (INTERNAL SERVER ERROR)

Traceback (most recent call last):
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 62, in application
    response = frappe.handler.handle()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/handler.py", line 22, in handle
    data = execute_cmd(cmd)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/handler.py", line 53, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 939, in call
    return fn(*args, **newargs)
TypeError: make_stock_entry() takes at least 2 arguments (2 given)

This is the Javascript code that triggers the function:

frappe.ui.form.on("Work Order", "refresh", function (frm)
{
    if (frm.doc.docstatus === 1 && frm.doc.status != 'Stopped')
        custom_app.make_se(frm, "Material Transfer for Manufacture");
});

custom_app = {

    make_se: function (frm, purpose)
    {
        frappe.prompt(
            {
                fieldtype: "Float",
                label: __("Qty for {0}", [purpose]),
                fieldname: "qty",
                description: __("Max: {0}", [max]),
                'default': max
            },
            function (data)
            {
                frappe.call({
                    method: "custom_app.work_order.doctype.work_order.work_order.make_stock_entry",
                    args: {
                        "work_order_id": frm.doc.docname,
                        "purpose": purpose,
                        "qty": data.qty
                    },
                    callback: function (r)
                    {
                        var doclist = frappe.model.sync(r.message);
                        frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
                    }
                });
            }, __("Select Quantity"), __("Make"));
    }
}

This is the Python code where I defined the function:

@frappe.whitelist()
def make_stock_entry(work_order_id, purpose, qty=None):
    work_order = frappe.get_doc("Work Order", work_order_id)

    if not frappe.db.get_value("Warehouse", work_order.wip_warehouse, "is_group"):
        wip_warehouse = work_order.wip_warehouse
    else:
        wip_warehouse = None

    stock_entry = frappe.new_doc("Stock Entry")
    stock_entry.purpose = purpose
    stock_entry.production_order = work_order_id
    stock_entry.from_bom = 1
    stock_entry.bom_no = work_order.bom_no
    stock_entry.fg_completed_qty = qty or (flt(work_order.qty) - flt(work_order.produced_qty))

    if purpose == "Material Transfer for Manufacture":
        stock_entry.to_warehouse = wip_warehouse
    else:
        stock_entry.from_warehouse = work_order.wip_warehouse
        stock_entry.fg_warehouse   = work_order.fg_warehouse

    stock_entry.get_items()
    return stock_entry.as_dict()

I think all is right, so I do not know why I get this error.

Does anyone know how to approach this?

Try this:

Instead of qty=None take qty=0. I’m assuming qty means quantity in the context of a regular stock transaction

Thanks for your answer.
It makes sense what you say, but still it keeps returning the same error.

“qty”: data.qty

this is some times none so make sure it must have some value when its none

you can try this

“qty”: data.qty ? data.qty:0

2 Likes

That error gets thrown when you’re not passing some of the mandatory arguments.

In your case, either the document name, or the purpose is not getting passed to the function. Might be a possible bug.

What version are you on, @vazdan?

@root13Fk your issue is because frm.doc.docname, it should be frm.docname or frm.doc.name

2 Likes

I have changed "qty": data.qty by "qty": data.qty ? data.qty : 0 and I tried to use frm.docname and frm.doc.name instead of frm.doc.docname, and now I get the error 404 (NOT FOUND) related to the Doctype.

ERPNext version: 10.1.18
Frappé version: 10.1.16

I receive 404 error (NOT FOUND) with the message: The resource you are looking for is not available, but I do not know what may be failing.

In the .PY code, when it reaches the frappe.get_doc() function, it can not find the current Doctype, but if I execute the frappe.get_doc() function from the web browser console, it returns all the fields and information about the Doctype.

@frappe.whitelist():
def make_stock_entry(work_order_id, purpose, qty=0):
    work_order = frappe.get_doc("Work Order", work_order_id)
    ...

From the web browser console, I tried this:

frappe.get_doc("Work Order", "WO-008")

and also this:

frappe.get_doc(cur_frm.doctype, cur_frm.docname)

and in both cases everything is executed in the correct way.

What can I do?

I can not find a way to do this

Could someone help me with this problem?

After a few weeks, I have determined that the error occurs in the Python code when stock_entry uses get_items at the end of the make_stock_entry function.

What can cause this to fail?

I have been using the IPython Console with bench console command to follow more closely each line of code and, when I run stock_entry.get_items(), the list of errors is larger than the size of my screen and I can not see all the errors.

This is the error caused by the call to stock_entry.get_items():

DoesNotExistError 			              Traceback (most recent call last)
/home/frappe/frappe-bench/apps/frappe/frappe/commands/utils.pyc in <module>()
----> 1 stock_entry.get_items()

/home/frappe/frappe-bench/apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.pyc in get_items(self)
    581                         frappe.throw(_("Posting date and posting time is mandatory"))
    582
--> 583                 self.set_production_order_details()
    584
    585                 if self.bom_no:

/home/frappe/frappe-bench/apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.pyc in set_production_order_details(self)
    674                         # common variables
    648                         if not self.pro_doc:
--> 649                                 self.pro_doc = frappe.get_doc('Production Order', self.production_order)
    650
    651                         if self.pro_doc:

/home/frappe/frappe-bench/apps/frappe/frappe/__init__.pyc in get_doc(*args, **kwargs)
    636         """
    637         """
    637         import frappe.model.document
--> 638         return frappe.model.document.get_doc(*args, **kwargs)
    639
    640 def get_last_doc(doctype):

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.pyc in get_doc(*args, **kwargs)
     66         controller = get_controller(doctype)
     67         if controller:
---> 68                 return controller(*args, **kwargs)
     69
     70         raise ImportError(doctype)

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.pyc in __init__(self, *args, **kwargs)
    101                                         self.name = args[1]
    102
--> 103                         self.load_from_db()
    104                         return
    105

/home/frappe/frappe-bench/apps/frappe/frappe/model/document.pyc in load_from_db(self)
    138                         d = frappe.db.get_value(self.doctype, self.docname, "*", as_dict=1)
    139                         if not d:
--> 140                                 frappe.throw(_("{0} {1} not found").format(_(self.doctype), self.name), frappe.DoesNotExistError)
    141
    141
    142                         super(Document, self).__init__(d)

/home/frappe/frappe-bench/apps/frappe/frappe/__init__.pyc in throw(msg, exc, title)
    321         :param msg: Message.
    322         :param exc: Exception class. Default `frappe.ValidationError`"""
--> 323         msgprint(msg, raise_exception=exc, title=title, indicator='red')
    324
    325 def emit_js(js, user=False, **kwargs):

/home/frappe/frappe-bench/apps/frappe/frappe/__init__.pyc in msgprint(msg, title, raise_exception, as_table, indicator, alert)
    307
    308         message_log.append(json.dumps(out))
--> 309         _raise_exception()
    310
    311 def clear_messages():

/home/frappe/frappe-bench/apps/frappe/frappe/__init__.pyc in _raise_exception()
    280
    281                         if inspect.isclass(raise_exception) and issubclass(raise_exception, Exception):
--> 282                                 raise raise_exception(encode(msg))
    283                         else:
    284                                 raise ValidationError(encode(msg))

DoesNotExistError: Production Order WO-019 not found

I do not understand why this part fails:

If I use the bench console command and execute the following code manually, it returns the entire field structure of the doctype, it does not give an error:

d = frappe.db.get_value("Work Order", "WO-019", "*", ad_dict=1)

if not d:
    frappe.throw(_("{0} {1} not found").format(_("Work Order"), "WO-019"), frappe.DoesNotExistError)
else:
    print(d)

The else statement is the one that is executed.

I finally managed to solve it.
The error occurred because the Python functions related to the doctype Stock Entry look for resources like WO-019 in the doctype Production Order, and I need them to do it in the doctype Work Order.