from __future__ import unicode_literals import frappe def execute(): frappe.reload_doc('buying', 'doctype', 'purchase_order') frappe.reload_doc('buying', 'doctype', 'supplier_quotation') frappe.reload_doc('selling', 'doctype', 'sales_order') frappe.reload_doc('selling', 'doctype', 'quotation') frappe.reload_doc('stock', 'doctype', 'delivery_note') frappe.reload_doc('stock', 'doctype', 'purchase_receipt') frappe.reload_doc('accounts', 'doctype', 'sales_invoice') frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') doctypes = ["Sales Order", "Sales Invoice", "Delivery Note",\ "Purchase Order", "Purchase Invoice", "Purchase Receipt", "Quotation", "Supplier Quotation"] for doctype in doctypes: total_qty = frappe.db.sql(''' SELECT parent, SUM(qty) as qty FROM `tab{0} Item` where parenttype = '{0}' GROUP BY parent '''.format(doctype), as_dict = True) # Query to update total_qty might become too big, Update in batches # batch_size is chosen arbitrarily, Don't try too hard to reason about it batch_size = 100000 for i in range(0, len(total_qty), batch_size): batch_transactions = total_qty[i:i + batch_size] # UPDATE with CASE for some reason cannot use PRIMARY INDEX, # causing all rows to be examined, leading to a very slow update # UPDATE with WHERE clause uses PRIMARY INDEX, but will lead to too many queries # INSERT with ON DUPLICATE KEY UPDATE uses PRIMARY INDEX # and can perform multiple updates per query # This is probably never used anywhere else as of now, but should be values = [] for d in batch_transactions: values.append("({0}, {1})".format(frappe.db.escape(d.parent), d.qty)) conditions = ",".join(values) frappe.db.sql(""" INSERT INTO `tab{}` (name, total_qty) VALUES {} ON DUPLICATE KEY UPDATE name = VALUES(name), total_qty = VALUES(total_qty) """.format(doctype, conditions))