@rmeyer @youssef
So, I switched from …
stock_entry.run_method('submit')
… to …
stock_entry.submit()
… as your source code reference suggests.
Then …
In order to be sure I know what’s going internally, I did a bunch of before and after diffs on the MariaDB database, like this:
- Use the UI manually to complete a
Material Transfer
with serial numbered items.
- Save a database dump as
before.sql
.
- Call my whitelisted, user-defined API method to complete a
Material Transfer
with serial numbered items.
- Save a database dump as
after.sql
.
- Run
diff
to save a file of differences.
I found relevant insertions in 5 database tables:
- GL Entry
- Stock Ledger Entry
- Stock Entry
- Stock Entry Detail
- Serial No
I then compared each column of each the altered tables.
The only differences I found were the ones I listed in the original post:
-
that the manual Submit writes
purchase_document_type
, purchase_document_no
& purchase_date
into “tabSerial No
” while the automated Submit does not.
I suspect this is an undetected bug in the way that the source code, suggested by @youssef, submits a Stock Entry.
Meanwhile, my serial numbers still don’t refer back to their original “purchase” document.
Questions:
- Can you suggest a different code sample?
- Where would I find the code executed on the client and the server when a user hits
Submit
on a new Stock Entry?
A further issue:
A further annoyance is the following single error message (split into 4 parts for readability):
Traceback (most recent call last):
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/app.py", line 64, in application
response = frappe.api.handle()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/api.py", line 58, in handle
return frappe.handler.handle()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/handler.py", line 30, in handle
data = execute_cmd(cmd)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/handler.py", line 69, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/__init__.py", line 1086, in call
return fn(*args, **newargs)
File "/home/erpdev/frappe-bench-DYPW/apps/returnable/returnable/returnable/doctype/returnable/returnable.py", line 534, in install_returnables
frappe.enqueue('returnable.returnable.doctype.returnable.returnable.installReturnables', now = True, timeout=60000)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/__init__.py", line 1537, in enqueue
return frappe.utils.background_jobs.enqueue(*args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/utils/background_jobs.py", line 44, in enqueue
return frappe.call(method, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/__init__.py", line 1086, in call
return fn(*args, **newargs)
File "/home/erpdev/frappe-bench-DYPW/apps/returnable/returnable/returnable/doctype/returnable/returnable.py", line 523, in installReturnables
createReturnablesInitialStockEntries()
File "/home/erpdev/frappe-bench-DYPW/apps/returnable/returnable/returnable/doctype/returnable/returnable.py", line 514, in createReturnablesInitialStockEntries
stock_entry.submit()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 897, in submit
self._submit()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 886, in _submit
self.save()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 281, in save
return self._save(*args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 303, in _save
self.insert()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 264, in insert
self.run_post_save_methods()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 963, in run_post_save_methods
self.run_method("on_submit")
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 827, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 1119, in composer
return composed(self, method, *args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 1102, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 821, in <lambda>
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py", line 85, in on_submit
self.update_stock_ledger()
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py", line 669, in update_stock_ledger
self.make_sl_entries(sl_entries)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/controllers/stock_controller.py", line 285, in make_sl_entries
make_sl_entries(sl_entries, allow_negative_stock, via_landed_cost_voucher)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/stock_ledger.py", line 48, in make_sl_entries
sle_id = make_entry(sle, allow_negative_stock, via_landed_cost_voucher)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/stock_ledger.py", line 70, in make_entry
sle.submit()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 897, in submit
self._submit()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 886, in _submit
self.save()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 281, in save
return self._save(*args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 333, in _save
self.run_post_save_methods()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 963, in run_post_save_methods
self.run_method("on_submit")
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 827, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 1119, in composer
return composed(self, method, *args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 1102, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/model/document.py", line 821, in <lambda>
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py", line 44, in on_submit
process_serial_no(self)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py", line 220, in process_serial_no
validate_serial_no(sle, item_det)
File "/home/erpdev/frappe-bench-DYPW/apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py", line 259, in validate_serial_no
frappe.throw(_("Serial No {0} has already been received").format(serial_no),
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/__init__.py", line 396, in throw
msgprint(msg, raise_exception=exc, title=title, indicator='red', is_minimizable=is_minimizable)
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/__init__.py", line 375, in msgprint
_raise_exception()
File "/home/erpdev/frappe-bench-DYPW/apps/frappe/frappe/__init__.py", line 326, in _raise_exception
raise raise_exception(msg)
erpnext.stock.doctype.serial_no.serial_no.SerialNoDuplicateError: Serial No TSTC012 has already been received
I have made sure that the test serial numbers are entirely new.
As far as I can tell the code suggested by @youssef does not expect items to have serial numbers and possibly will not work if serial numbers are involved.