From 64c512dd61033f8454e19e64cff6a42e84e0eea0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 13 Dec 2013 12:34:52 +0530 Subject: [PATCH 1/5] [minor] [fix] allow roles --- setup/page/setup/setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup/page/setup/setup.py b/setup/page/setup/setup.py index 4418f857e4..11025c9607 100644 --- a/setup/page/setup/setup.py +++ b/setup/page/setup/setup.py @@ -233,8 +233,9 @@ items = [ "route": "Report/Scheduler Log", "type": "Link", "icon": "icon-exclamation-sign" }, ] -@webnotes.whitelist(allow_roles=["System Manager"]) +@webnotes.whitelist() def get(): + webnotes.only_for("System Manager") for item in items: if item.get("type")=="Section": continue From b0636edaf74edbe155bf52591b4e88729fb3f190 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 16 Dec 2013 13:51:09 +0530 Subject: [PATCH 2/5] [minor] [scheduler] send scheduler errors as email digest --- patches/1311/p07_scheduler_errors_digest.py | 23 +++++++++ patches/1311/p08_email_digest_recipients.py | 11 +++++ patches/patch_list.py | 2 + setup/doctype/email_digest/email_digest.js | 4 +- setup/doctype/email_digest/email_digest.py | 27 +++++++---- setup/doctype/email_digest/email_digest.txt | 53 ++++++++++++++++----- setup/page/setup_wizard/setup_wizard.py | 19 ++++++-- startup/bean_handlers.py | 3 +- startup/schedule_handlers.py | 11 ++--- 9 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 patches/1311/p07_scheduler_errors_digest.py create mode 100644 patches/1311/p08_email_digest_recipients.py diff --git a/patches/1311/p07_scheduler_errors_digest.py b/patches/1311/p07_scheduler_errors_digest.py new file mode 100644 index 0000000000..7cfa251847 --- /dev/null +++ b/patches/1311/p07_scheduler_errors_digest.py @@ -0,0 +1,23 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + from webnotes.profile import get_system_managers + system_managers = get_system_managers(only_name=True) + if not system_managers: + return + + # scheduler errors digest + edigest = webnotes.new_bean("Email Digest") + edigest.doc.fields.update({ + "name": "Scheduler Errors", + "company": webnotes.conn.get_default("company"), + "frequency": "Daily", + "enabled": 1, + "recipient_list": "\n".join(system_managers), + "scheduler_errors": 1 + }) + edigest.insert() \ No newline at end of file diff --git a/patches/1311/p08_email_digest_recipients.py b/patches/1311/p08_email_digest_recipients.py new file mode 100644 index 0000000000..fad540844f --- /dev/null +++ b/patches/1311/p08_email_digest_recipients.py @@ -0,0 +1,11 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + from webnotes.utils import extract_email_id + for name, recipients in webnotes.conn.sql("""select name, recipient_list from `tabEmail Digest`"""): + recipients = "\n".join([extract_email_id(r) for r in recipients.split("\n")]) + webnotes.conn.set_value("Email Digest", name, "recipient_list", recipients) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 9400e08872..9df0207979 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -258,4 +258,6 @@ patch_list = [ "execute:webnotes.delete_doc('Report', 'Stock Ledger') #2013-11-29", "execute:webnotes.delete_doc('Report', 'Payment Collection With Ageing')", "execute:webnotes.delete_doc('Report', 'Payment Made With Ageing')", + "patches.1311.p07_scheduler_errors_digest", + "patches.1311.p08_email_digest_recipients", ] \ No newline at end of file diff --git a/setup/doctype/email_digest/email_digest.js b/setup/doctype/email_digest/email_digest.js index 3367a7237a..79cc681985 100644 --- a/setup/doctype/email_digest/email_digest.js +++ b/setup/doctype/email_digest/email_digest.js @@ -70,8 +70,10 @@ cur_frm.cscript.addremove_recipients = function(doc, dt, dn) { check.checked = 1; add_or_update = 'Update'; } + var fullname = wn.user.full_name(v.name); + if(fullname !== v.name) v.name = fullname + " <" + v.name + ">"; if(v.enabled==0) { - v.name = "" + v.name + " (disabled user)" + v.name = repl(" %(name)s (disabled user)", {name: v.name}); } var profile = $a($td(tab, i+1, 1), 'span', '', '', v.name); //profile.onclick = function() { check.checked = !check.checked; } diff --git a/setup/doctype/email_digest/email_digest.py b/setup/doctype/email_digest/email_digest.py index a9720ae005..082b92fb7f 100644 --- a/setup/doctype/email_digest/email_digest.py +++ b/setup/doctype/email_digest/email_digest.py @@ -19,16 +19,16 @@ content_sequence = [ ["Selling", ["new_leads", "new_enquiries", "new_quotations", "new_sales_orders"]], ["Stock", ["new_delivery_notes", "new_purchase_receipts", "new_stock_entries"]], ["Support", ["new_communications", "new_support_tickets", "open_tickets"]], - ["Projects", ["new_projects"]] + ["Projects", ["new_projects"]], + ["System", ["scheduler_errors"]], ] user_specific_content = ["calendar_events", "todo_list"] -digest_template = """\ - -

%(digest)s

-

%(date)s

+digest_template = """ +

%(name)s

%(company)s

+

%(date)s


%(with_value)s %(no_value)s @@ -53,10 +53,10 @@ class DocType(DocListController): def get_profiles(self): """get list of profiles""" - import webnotes profile_list = webnotes.conn.sql(""" select name, enabled from tabProfile where docstatus=0 and name not in ('Administrator', 'Guest') + and user_type = "System User" order by enabled desc, name asc""", as_dict=1) if self.doc.recipient_list: @@ -81,7 +81,9 @@ class DocType(DocListController): msg_for_this_receipient = self.get_msg_html(self.get_user_specific_content(user_id) + \ common_msg) from webnotes.utils.email_lib import sendmail - sendmail(recipients=user_id, subject="[ERPNext] " + (self.doc.frequency + " Digest"), + sendmail(recipients=user_id, + subject="[ERPNext] [{frequency} Digest] {name}".format( + frequency=self.doc.frequency, name=self.doc.name), msg=msg_for_this_receipient) def get_digest_msg(self): @@ -123,7 +125,7 @@ class DocType(DocListController): if with_value: with_value = "\n".join(with_value) else: - with_value = "

There were no updates in the items selected for this digest.

" + with_value = "

There were no updates in the items selected for this digest.


" # seperate out no value items no_value = [o[1] for o in out if not o[0]] @@ -138,7 +140,8 @@ class DocType(DocListController): "date": date, "company": self.doc.company, "with_value": with_value, - "no_value": no_value or "" + "no_value": no_value or "", + "name": self.doc.name } return msg @@ -452,6 +455,10 @@ class DocType(DocListController): t for t in open_tickets]) else: return 0, "No Open Tickets!" + + def get_scheduler_errors(self): + import webnotes.utils.scheduler + return webnotes.utils.scheduler.get_error_report(self.from_date, self.to_date) def onload(self): self.get_next_sending() @@ -470,4 +477,4 @@ def send(): where enabled=1 and docstatus<2""", as_list=1): ed_obj = get_obj('Email Digest', ed[0]) if (now_date == ed_obj.get_next_sending()): - ed_obj.send() + ed_obj.send() \ No newline at end of file diff --git a/setup/doctype/email_digest/email_digest.txt b/setup/doctype/email_digest/email_digest.txt index f71d82a0e3..b04885a4c9 100644 --- a/setup/doctype/email_digest/email_digest.txt +++ b/setup/doctype/email_digest/email_digest.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-21 14:15:31", "docstatus": 0, - "modified": "2013-07-05 14:36:13", + "modified": "2013-12-16 12:37:43", "modified_by": "Administrator", "owner": "Administrator" }, @@ -100,11 +100,10 @@ "label": "Add/Remove Recipients" }, { - "description": "Check all the items below that you want to send in this digest.", "doctype": "DocField", - "fieldname": "select_digest_content", + "fieldname": "accounts", "fieldtype": "Section Break", - "label": "Select Digest Content" + "label": "Accounts" }, { "doctype": "DocField", @@ -178,7 +177,7 @@ "doctype": "DocField", "fieldname": "section_break_20", "fieldtype": "Section Break", - "options": "Simple" + "label": "Buying & Selling" }, { "doctype": "DocField", @@ -234,6 +233,12 @@ "fieldtype": "Check", "label": "New Sales Orders" }, + { + "doctype": "DocField", + "fieldname": "section_break_34", + "fieldtype": "Section Break", + "label": "Inventory & Support" + }, { "doctype": "DocField", "fieldname": "stock_module", @@ -258,12 +263,6 @@ "fieldtype": "Check", "label": "New Stock Entries" }, - { - "doctype": "DocField", - "fieldname": "section_break_34", - "fieldtype": "Section Break", - "options": "Simple" - }, { "doctype": "DocField", "fieldname": "support_module", @@ -288,6 +287,12 @@ "fieldtype": "Check", "label": "New Communications" }, + { + "doctype": "DocField", + "fieldname": "section_break_40", + "fieldtype": "Section Break", + "label": "Projects & System" + }, { "doctype": "DocField", "fieldname": "projects_module", @@ -302,7 +307,25 @@ }, { "doctype": "DocField", - "fieldname": "utilities_module", + "fieldname": "core_module", + "fieldtype": "Column Break", + "label": "System" + }, + { + "doctype": "DocField", + "fieldname": "scheduler_errors", + "fieldtype": "Check", + "label": "Scheduler Failed Events" + }, + { + "doctype": "DocField", + "fieldname": "user_specific", + "fieldtype": "Section Break", + "label": "User Specific" + }, + { + "doctype": "DocField", + "fieldname": "general", "fieldtype": "Column Break", "label": "General" }, @@ -318,6 +341,12 @@ "fieldtype": "Check", "label": "To Do List" }, + { + "doctype": "DocField", + "fieldname": "stub", + "fieldtype": "Column Break", + "label": "Stub" + }, { "cancel": 1, "create": 1, diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index bf149059a1..b5133ef479 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -171,7 +171,7 @@ def create_feed_and_todo(): def create_email_digest(): from webnotes.profile import get_system_managers - system_managers = get_system_managers() + system_managers = get_system_managers(only_name=True) if not system_managers: return @@ -186,10 +186,23 @@ def create_email_digest(): }) for fieldname in edigest.meta.get_fieldnames({"fieldtype": "Check"}): - edigest.doc.fields[fieldname] = 1 + if fieldname != "scheduler_errors": + edigest.doc.fields[fieldname] = 1 edigest.insert() - + + # scheduler errors digest + edigest = webnotes.new_bean("Email Digest") + edigest.doc.fields.update({ + "name": "Scheduler Errors", + "company": webnotes.conn.get_default("company"), + "frequency": "Daily", + "recipient_list": "\n".join(system_managers), + "scheduler_errors": 1, + "enabled": 1 + }) + edigest.insert() + def get_fy_details(fy_start_date, fy_end_date): start_year = getdate(fy_start_date).year if start_year == getdate(fy_end_date).year: diff --git a/startup/bean_handlers.py b/startup/bean_handlers.py index 06d27343d8..678c8aa5b4 100644 --- a/startup/bean_handlers.py +++ b/startup/bean_handlers.py @@ -13,4 +13,5 @@ def on_method(bean, method): clear_doctype_notifications(bean.controller, method) if bean.doc.doctype=="Stock Entry" and method in ("on_submit", "on_cancel"): - update_completed_qty(bean.controller, method) \ No newline at end of file + update_completed_qty(bean.controller, method) + \ No newline at end of file diff --git a/startup/schedule_handlers.py b/startup/schedule_handlers.py index cdb0e5d5dd..252a091547 100644 --- a/startup/schedule_handlers.py +++ b/startup/schedule_handlers.py @@ -34,10 +34,6 @@ def execute_daily(): from core.doctype.notification_count.notification_count import delete_notification_count_for delete_notification_count_for("Event") - # email digest - from setup.doctype.email_digest.email_digest import send - run_fn(send) - # run recurring invoices from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices run_fn(manage_recurring_invoices) @@ -53,10 +49,11 @@ def execute_daily(): # check reorder level from stock.utils import reorder_item run_fn(reorder_item) + + # email digest + from setup.doctype.email_digest.email_digest import send + run_fn(send) - # scheduler error - scheduler.report_errors() - def execute_weekly(): from setup.doctype.backup_manager.backup_manager import take_backups_weekly run_fn(take_backups_weekly) From 9ff9dafd009eb2ec7b2fcbac8b23522d934e98d9 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 16 Dec 2013 19:32:22 +0530 Subject: [PATCH 3/5] [feature] create material request sales order wise from production planning tool --- .../purchase_common/purchase_common.py | 9 +- .../production_planning_tool.py | 192 +++++++++++------- .../material_request/material_request.py | 36 ++-- 3 files changed, 140 insertions(+), 97 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index c265874992..6d8be0e79b 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -7,11 +7,9 @@ import webnotes from webnotes.utils import cstr, flt from webnotes.model.utils import getlist from webnotes import msgprint, _ - from buying.utils import get_last_purchase_details - - from controllers.buying_controller import BuyingController + class DocType(BuyingController): def __init__(self, doc, doclist=None): self.doc = doc @@ -107,7 +105,10 @@ class DocType(BuyingController): msgprint("Item %s is not a purchase item or sub-contracted item. Please check" % (d.item_code), raise_exception=True) # list criteria that should not repeat if item is stock item - e = [d.schedule_date, d.item_code, d.description, d.warehouse, d.uom, d.fields.has_key('prevdoc_docname') and d.prevdoc_docname or '', d.fields.has_key('prevdoc_detail_docname') and d.prevdoc_detail_docname or '', d.fields.has_key('batch_no') and d.batch_no or ''] + e = [d.schedule_date, d.item_code, d.description, d.warehouse, d.uom, + d.fields.has_key('prevdoc_docname') and d.prevdoc_docname or d.fields.has_key('sales_order_no') and d.sales_order_no or '', + d.fields.has_key('prevdoc_detail_docname') and d.prevdoc_detail_docname or '', + d.fields.has_key('batch_no') and d.batch_no or ''] # if is not stock item f = [d.schedule_date, d.item_code, d.description] diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index ce93d80c6b..17db5f4f85 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint, _ - class DocType: def __init__(self, doc, doclist=[]): self.doc = doc @@ -47,7 +46,7 @@ class DocType: def validate_company(self): if not self.doc.company: - msgprint("Please enter Company", raise_exception=1) + webnotes.throw(_("Please enter Company")) def get_open_sales_orders(self): """ Pull sales orders which are pending to deliver based on criteria selected""" @@ -106,7 +105,7 @@ class DocType: def get_items(self): so_list = filter(None, [d.sales_order for d in getlist(self.doclist, 'pp_so_details')]) if not so_list: - msgprint("Please enter sales order in the above table") + msgprint(_("Please enter sales order in the above table")) return [] items = webnotes.conn.sql("""select distinct parent, item_code, reserved_warehouse, @@ -155,21 +154,21 @@ class DocType: for d in getlist(self.doclist, 'pp_details'): self.validate_bom_no(d) if not flt(d.planned_qty): - msgprint("Please Enter Planned Qty for item: %s at row no: %s" % - (d.item_code, d.idx), raise_exception=1) + webnotes.throw(_("Please Enter Planned Qty for item: %s at row no: %s") % + (d.item_code, d.idx)) def validate_bom_no(self, d): if not d.bom_no: - msgprint("Please enter bom no for item: %s at row no: %s" % - (d.item_code, d.idx), raise_exception=1) + webnotes.throw(_("Please enter bom no for item: %s at row no: %s") % + (d.item_code, d.idx)) else: bom = webnotes.conn.sql("""select name from `tabBOM` where name = %s and item = %s and docstatus = 1 and is_active = 1""", (d.bom_no, d.item_code), as_dict = 1) if not bom: - msgprint("""Incorrect BOM No: %s entered for item: %s at row no: %s - May be BOM is inactive or for other item or does not exists in the system""" % - (d.bom_no, d.item_doce, d.idx), raise_exception=1) + webnotes.throw(_("""Incorrect BOM No: %s entered for item: %s at row no: %s + May be BOM is inactive or for other item or does not exists in the system""") % + (d.bom_no, d.item_doce, d.idx)) def raise_production_order(self): """It will raise production order (Draft) for all distinct FG items""" @@ -183,16 +182,20 @@ class DocType: if pro: pro = ["""%s""" % \ (p, p) for p in pro] - msgprint("Production Order(s) created:\n\n" + '\n'.join(pro)) + msgprint(_("Production Order(s) created:\n\n") + '\n'.join(pro)) else : - msgprint("No Production Order created.") + msgprint(_("No Production Order created.")) def get_distinct_items_and_boms(self): - """ Club similar BOM and item for processing""" + """ Club similar BOM and item for processing + bom_dict { + bom_no: ['sales_order', 'qty'] + } + """ item_dict, bom_dict = {}, {} for d in self.doclist.get({"parentfield": "pp_details"}): - bom_dict[d.bom_no] = bom_dict.get(d.bom_no, 0) + flt(d.planned_qty) + bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)]) item_dict[(d.item_code, d.sales_order, d.warehouse)] = { "production_item" : d.item_code, "sales_order" : d.sales_order, @@ -241,48 +244,59 @@ class DocType: "item_code": [qty_required, description, stock_uom, min_order_qty] } """ - for bom in bom_dict: + bom_wise_item_details = {} + item_list = [] + + for bom, so_wise_qty in bom_dict.items(): if self.doc.use_multi_level_bom: # get all raw materials with sub assembly childs - fl_bom_items = webnotes.conn.sql("""select fb.item_code, - ifnull(sum(fb.qty_consumed_per_unit), 0)*%s as qty, + for d in webnotes.conn.sql("""select fb.item_code, + ifnull(sum(fb.qty_consumed_per_unit), 0) as qty, fb.description, fb.stock_uom, it.min_order_qty from `tabBOM Explosion Item` fb,`tabItem` it - where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No' + where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No' and ifnull(it.is_sub_contracted_item, 'No') = 'No' - and fb.docstatus<2 and fb.parent=%s - group by item_code, stock_uom""", (flt(bom_dict[bom]), bom)) + and fb.docstatus<2 and fb.parent=%s + group by item_code, stock_uom""", bom, as_dict=1): + bom_wise_item_details.setdefault(d.item_code, d) else: # Get all raw materials considering SA items as raw materials, # so no childs of SA items - fl_bom_items = webnotes.conn.sql("""select bom_item.item_code, - ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s, - bom_item.description, bom_item.stock_uom, item.min_order_qty - from `tabBOM Item` bom_item, tabItem item + for d in webnotes.conn.sql("""select bom_item.item_code, + ifnull(sum(bom_item.qty_consumed_per_unit), 0) as qty, + bom_item.description, bom_item.stock_uom, item.min_order_qty + from `tabBOM Item` bom_item, tabItem item where bom_item.parent = %s and bom_item.docstatus < 2 and bom_item.item_code = item.name - group by item_code""", (flt(bom_dict[bom]), bom)) - self.make_items_dict(fl_bom_items) + group by item_code""", bom, as_dict=1): + bom_wise_item_details.setdefault(d.item_code, d) + + for item, item_details in bom_wise_item_details.items(): + for so_qty in so_wise_qty: + item_list.append([item, flt(item_details.qty) * so_qty[1], item_details.description, + item_details.stock_uom, item_details.min_order_qty, so_qty[0]]) + + self.make_items_dict(item_list) def make_items_dict(self, item_list): for i in item_list: - self.item_dict[i[0]] = [(flt(self.item_dict.get(i[0], [0])[0]) + flt(i[1])), - i[2], i[3], i[4]] - + self.item_dict.setdefault(i[0], []).append([flt(i[1]), i[2], i[3], i[4], i[5]]) def get_csv(self): item_list = [['Item Code', 'Description', 'Stock UOM', 'Required Qty', 'Warehouse', 'Quantity Requested for Purchase', 'Ordered Qty', 'Actual Qty']] - for d in self.item_dict: - item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0]]) - item_qty= webnotes.conn.sql("""select warehouse, indented_qty, ordered_qty, actual_qty - from `tabBin` where item_code = %s""", d) - i_qty, o_qty, a_qty = 0, 0, 0 - for w in item_qty: - i_qty, o_qty, a_qty = i_qty + flt(w[1]), o_qty + flt(w[2]), a_qty + flt(w[3]) - item_list.append(['', '', '', '', w[0], flt(w[1]), flt(w[2]), flt(w[3])]) - if item_qty: - item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty]) + for item in self.item_dict: + total_qty = sum([flt(d[0]) for d in self.item_dict[item]]) + for item_details in self.item_dict[item]: + item_list.append([item, item_details[1], item_details[2], item_details[0]]) + item_qty = webnotes.conn.sql("""select warehouse, indented_qty, ordered_qty, actual_qty + from `tabBin` where item_code = %s""", item) + i_qty, o_qty, a_qty = 0, 0, 0 + for w in item_qty: + i_qty, o_qty, a_qty = i_qty + flt(w[1]), o_qty + flt(w[2]), a_qty + flt(w[3]) + item_list.append(['', '', '', '', w[0], flt(w[1]), flt(w[2]), flt(w[3])]) + if item_qty: + item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty]) return item_list @@ -293,31 +307,49 @@ class DocType: """ self.validate_data() if not self.doc.purchase_request_for_warehouse: - webnotes.msgprint("Please enter Warehouse for which Material Request will be raised", - raise_exception=1) + webnotes.throw(_("Please enter Warehouse for which Material Request will be raised")) bom_dict = self.get_distinct_items_and_boms()[0] self.get_raw_materials(bom_dict) - if not self.item_dict: - return - + if self.item_dict: + self.insert_purchase_request() + + def get_requested_items(self): item_projected_qty = self.get_projected_qty() - - from accounts.utils import get_fiscal_year - fiscal_year = get_fiscal_year(nowdate())[0] - items_to_be_requested = webnotes._dict() - for item in self.item_dict: - if flt(self.item_dict[item][0]) > item_projected_qty.get(item, 0): + + for item, so_item_qty in self.item_dict.items(): + requested_qty = 0 + total_qty = sum([flt(d[0]) for d in so_item_qty]) + if total_qty > item_projected_qty.get(item, 0): # shortage - requested_qty = flt(self.item_dict[item][0]) - item_projected_qty.get(item, 0) - # comsider minimum order qty - requested_qty = requested_qty > flt(self.item_dict[item][3]) and \ - requested_qty or flt(self.item_dict[item][3]) - items_to_be_requested[item] = requested_qty - - self.insert_purchase_request(items_to_be_requested, fiscal_year) + requested_qty = total_qty - item_projected_qty.get(item, 0) + # consider minimum order qty + requested_qty = requested_qty > flt(so_item_qty[0][3]) and \ + requested_qty or flt(so_item_qty[0][3]) + + # distribute requested qty SO wise + for item_details in so_item_qty: + if requested_qty: + sales_order = item_details[4] or "No Sales Order" + if requested_qty <= item_details[0]: + adjusted_qty = requested_qty + else: + adjusted_qty = item_details[0] + + items_to_be_requested.setdefault(item, {}).setdefault(sales_order, 0) + items_to_be_requested[item][sales_order] += adjusted_qty + requested_qty -= adjusted_qty + else: + break + + # requested qty >= total so qty, due to minimum order qty + if requested_qty: + items_to_be_requested.setdefault(item, {}).setdefault("No Sales Order", 0) + items_to_be_requested[item]["No Sales Order"] += requested_qty + + return items_to_be_requested def get_projected_qty(self): items = self.item_dict.keys() @@ -327,24 +359,29 @@ class DocType: return dict(item_projected_qty) - def insert_purchase_request(self, items_to_be_requested, fiscal_year): + def insert_purchase_request(self): + items_to_be_requested = self.get_requested_items() + + from accounts.utils import get_fiscal_year + fiscal_year = get_fiscal_year(nowdate())[0] + purchase_request_list = [] if items_to_be_requested: for item in items_to_be_requested: item_wrapper = webnotes.bean("Item", item) - pr_doclist = [ - { - "doctype": "Material Request", - "__islocal": 1, - "naming_series": "IDT", - "transaction_date": nowdate(), - "status": "Draft", - "company": self.doc.company, - "fiscal_year": fiscal_year, - "requested_by": webnotes.session.user, - "material_request_type": "Purchase" - }, - { + pr_doclist = [{ + "doctype": "Material Request", + "__islocal": 1, + "naming_series": "IDT", + "transaction_date": nowdate(), + "status": "Draft", + "company": self.doc.company, + "fiscal_year": fiscal_year, + "requested_by": webnotes.session.user, + "material_request_type": "Purchase" + }] + for sales_order, requested_qty in items_to_be_requested[item].items(): + pr_doclist.append({ "doctype": "Material Request Item", "__islocal": 1, "parentfield": "indent_details", @@ -354,11 +391,12 @@ class DocType: "uom": item_wrapper.doc.stock_uom, "item_group": item_wrapper.doc.item_group, "brand": item_wrapper.doc.brand, - "qty": items_to_be_requested[item], + "qty": requested_qty, "schedule_date": add_days(nowdate(), cint(item_wrapper.doc.lead_time_days)), - "warehouse": self.doc.purchase_request_for_warehouse - } - ] + "warehouse": self.doc.purchase_request_for_warehouse, + "sales_order_no": sales_order if sales_order!="No Sales Order" else None + }) + pr_wrapper = webnotes.bean(pr_doclist) pr_wrapper.ignore_permissions = 1 pr_wrapper.submit() @@ -367,7 +405,7 @@ class DocType: if purchase_request_list: pur_req = ["""%s""" % \ (p, p) for p in purchase_request_list] - webnotes.msgprint("Material Request(s) created: \n%s" % + msgprint(_("Material Request(s) created: \n%s") % "\n".join(pur_req)) else: - webnotes.msgprint("Nothing to request") + msgprint(_("Nothing to request")) \ No newline at end of file diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py index f340ccaedd..67d36eff1b 100644 --- a/stock/doctype/material_request/material_request.py +++ b/stock/doctype/material_request/material_request.py @@ -37,20 +37,25 @@ class DocType(BuyingController): for so_no in so_items.keys(): for item in so_items[so_no].keys(): - already_indented = webnotes.conn.sql("select sum(qty) from `tabMaterial Request Item` where item_code = '%s' and sales_order_no = '%s' and docstatus = 1 and parent != '%s'" % (item, so_no, self.doc.name)) + already_indented = webnotes.conn.sql("""select sum(qty) from `tabMaterial Request Item` + where item_code = '%s' and sales_order_no = '%s' and + docstatus = 1 and parent != '%s'""" % (item, so_no, self.doc.name)) already_indented = already_indented and flt(already_indented[0][0]) or 0 - actual_so_qty = webnotes.conn.sql("select sum(qty) from `tabSales Order Item` where parent = '%s' and item_code = '%s' and docstatus = 1 group by parent" % (so_no, item)) + actual_so_qty = webnotes.conn.sql("""select sum(qty) from `tabSales Order Item` + where parent = '%s' and item_code = '%s' and docstatus = 1 + group by parent""" % (so_no, item)) actual_so_qty = actual_so_qty and flt(actual_so_qty[0][0]) or 0 - if flt(so_items[so_no][item]) + already_indented > actual_so_qty: - msgprint("You can raise indent of maximum qty: %s for item: %s against sales order: %s\n Anyway, you can add more qty in new row for the same item." % (actual_so_qty - already_indented, item, so_no), raise_exception=1) + if actual_so_qty and (flt(so_items[so_no][item]) + already_indented > actual_so_qty): + webnotes.throw(_("You can raise indent of maximum qty: %s for item: %s against sales order: %s\ + \n Anyway, you can add more qty in new row for the same item.") + % (actual_so_qty - already_indented, item, so_no)) def validate_schedule_date(self): for d in getlist(self.doclist, 'indent_details'): if d.schedule_date < self.doc.transaction_date: - msgprint("Expected Date cannot be before Material Request Date") - raise Exception + webnotes.throw(_("Expected Date cannot be before Material Request Date")) # Validate # --------------------- @@ -80,8 +85,8 @@ class DocType(BuyingController): for d in getlist(self.doclist, 'indent_details'): if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes": if not d.warehouse: - msgprint("Please Enter Warehouse for Item %s as it is stock item" - % cstr(d.item_code), raise_exception=1) + webnotes.throw("Please Enter Warehouse for Item %s as it is stock item" + % cstr(d.item_code)) qty =flt(d.qty) if is_stopped: @@ -96,16 +101,15 @@ class DocType(BuyingController): update_bin(args) def on_submit(self): - webnotes.conn.set(self.doc,'status','Submitted') + webnotes.conn.set(self.doc, 'status', 'Submitted') self.update_bin(is_submit = 1, is_stopped = 0) def check_modified_date(self): mod_db = webnotes.conn.sql("select modified from `tabMaterial Request` where name = '%s'" % self.doc.name) - date_diff = webnotes.conn.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) + date_diff = webnotes.conn.sql("select TIMEDIFF('%s', '%s')" % (mod_db[0][0], cstr(self.doc.modified))) if date_diff and date_diff[0][0]: - msgprint(cstr(self.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ") - raise Exception + webnotes.throw(cstr(self.doc.doctype) + " => " + cstr(self.doc.name) + " has been modified. Please Refresh.") def update_status(self, status): self.check_modified_date() @@ -113,10 +117,10 @@ class DocType(BuyingController): self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1) # Step 2:=> Set status - webnotes.conn.set(self.doc,'status',cstr(status)) + webnotes.conn.set(self.doc, 'status', cstr(status)) # Step 3:=> Acknowledge User - msgprint(self.doc.doctype + ": " + self.doc.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status)) ) + msgprint(self.doc.doctype + ": " + self.doc.name + _(" has been %s.") % ((status == 'Submitted') and 'Unstopped' or cstr(status)) ) def on_cancel(self): @@ -177,9 +181,9 @@ def update_completed_qty(controller, caller_method): mr_doctype = webnotes.get_doctype("Material Request") if mr_obj.doc.status in ["Stopped", "Cancelled"]: - msgprint(_("Material Request") + ": %s, " % mr_obj.doc.name + webnotes.throw(_("Material Request") + ": %s, " % mr_obj.doc.name + _(mr_doctype.get_label("status")) + " = %s. " % _(mr_obj.doc.status) - + _("Cannot continue."), raise_exception=webnotes.InvalidStatusError) + + _("Cannot continue."), exc=webnotes.InvalidStatusError) _update_requested_qty(controller, mr_obj, mr_items) From 9ee20e8f5a66f8976f1578ff2e6567df2ffabfc1 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 17 Dec 2013 13:07:00 +0530 Subject: [PATCH 4/5] [fix] [minor] material request sales order wise through production planning tool --- .../purchase_common/purchase_common.py | 62 +++++++++---------- .../production_planning_tool.py | 17 ++--- .../material_request/material_request.py | 20 +++--- 3 files changed, 51 insertions(+), 48 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index 6d8be0e79b..b480caffc7 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -36,13 +36,13 @@ class DocType(BuyingController): if flt(d.conversion_factor): last_purchase_rate = flt(d.purchase_rate) / flt(d.conversion_factor) else: - msgprint(_("Row ") + cstr(d.idx) + ": " + - _("UOM Conversion Factor is mandatory"), raise_exception=1) + webnotes.throw(_("Row ") + cstr(d.idx) + ": " + + _("UOM Conversion Factor is mandatory")) # update last purchsae rate if last_purchase_rate: - webnotes.conn.sql("update `tabItem` set last_purchase_rate = %s where name = %s", - (flt(last_purchase_rate),d.item_code)) + webnotes.conn.sql("""update `tabItem` set last_purchase_rate = %s where name = %s""", + (flt(last_purchase_rate), d.item_code)) def get_last_purchase_rate(self, obj): """get last purchase rates for all items""" @@ -74,11 +74,11 @@ class DocType(BuyingController): for d in getlist( obj.doclist, obj.fname): # validation for valid qty if flt(d.qty) < 0 or (d.parenttype != 'Purchase Receipt' and not flt(d.qty)): - msgprint("Please enter valid qty for item %s" % cstr(d.item_code)) - raise Exception + webnotes.throw("Please enter valid qty for item %s" % cstr(d.item_code)) # udpate with latest quantities - bin = webnotes.conn.sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) + bin = webnotes.conn.sql("""select projected_qty from `tabBin` where + item_code = %s and warehouse = %s""", (d.item_code, d.warehouse), as_dict=1) f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0} if d.doctype == 'Purchase Receipt Item': @@ -87,22 +87,21 @@ class DocType(BuyingController): if d.fields.has_key(x): d.fields[x] = f_lst[x] - item = webnotes.conn.sql("select is_stock_item, is_purchase_item, is_sub_contracted_item, end_of_life from tabItem where name=%s", - d.item_code) + item = webnotes.conn.sql("""select is_stock_item, is_purchase_item, + is_sub_contracted_item, end_of_life from `tabItem` where name=%s""", d.item_code) if not item: - msgprint("Item %s does not exist in Item Master." % cstr(d.item_code), raise_exception=True) + webnotes.throw("Item %s does not exist in Item Master." % cstr(d.item_code)) from stock.utils import validate_end_of_life validate_end_of_life(d.item_code, item[0][3]) # validate stock item if item[0][0]=='Yes' and d.qty and not d.warehouse: - msgprint("Warehouse is mandatory for %s, since it is a stock item" % - d.item_code, raise_exception=1) + webnotes.throw("Warehouse is mandatory for %s, since it is a stock item" % d.item_code) # validate purchase item if item[0][1] != 'Yes' and item[0][2] != 'Yes': - msgprint("Item %s is not a purchase item or sub-contracted item. Please check" % (d.item_code), raise_exception=True) + webnotes.throw("Item %s is not a purchase item or sub-contracted item. Please check" % (d.item_code)) # list criteria that should not repeat if item is stock item e = [d.schedule_date, d.item_code, d.description, d.warehouse, d.uom, @@ -113,25 +112,25 @@ class DocType(BuyingController): # if is not stock item f = [d.schedule_date, d.item_code, d.description] - ch = webnotes.conn.sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) + ch = webnotes.conn.sql("""select is_stock_item from `tabItem` where name = %s""", d.item_code) if ch and ch[0][0] == 'Yes': # check for same items if e in check_list: - msgprint("""Item %s has been entered more than once with same description, schedule date, warehouse and uom.\n - Please change any of the field value to enter the item twice""" % d.item_code, raise_exception = 1) + webnotes.throw("""Item %s has been entered more than once with same description, schedule date, warehouse and uom.\n + Please change any of the field value to enter the item twice""" % d.item_code) else: check_list.append(e) elif ch and ch[0][0] == 'No': # check for same items if f in chk_dupl_itm: - msgprint("""Item %s has been entered more than once with same description, schedule date.\n - Please change any of the field value to enter the item twice.""" % d.item_code, raise_exception = 1) + webnotes.throw("""Item %s has been entered more than once with same description, schedule date.\n + Please change any of the field value to enter the item twice.""" % d.item_code) else: chk_dupl_itm.append(f) - def get_qty(self,curr_doctype,ref_tab_fname,ref_tab_dn,ref_doc_tname, transaction, curr_parent_name): + def get_qty(self, curr_doctype, ref_tab_fname, ref_tab_dn, ref_doc_tname, transaction, curr_parent_name): # Get total Quantities of current doctype (eg. PR) except for qty of this transaction #------------------------------ # please check as UOM changes from Material Request - Purchase Order ,so doing following else uom should be same . @@ -139,35 +138,36 @@ class DocType(BuyingController): # but if in Material Request uom KG it can change in PO get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty' - qty = webnotes.conn.sql("select sum(%s) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% ( get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) + qty = webnotes.conn.sql("""select sum(%s) from `tab%s` where %s = %s and + docstatus = 1 and parent != %s""", (get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) qty = qty and flt(qty[0][0]) or 0 # get total qty of ref doctype #-------------------- - max_qty = webnotes.conn.sql("select qty from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn)) + max_qty = webnotes.conn.sql("""select qty from `tab%s` where name = %s + and docstatus = 1""", (ref_doc_tname, ref_tab_dn)) max_qty = max_qty and flt(max_qty[0][0]) or 0 return cstr(qty)+'~~~'+cstr(max_qty) def check_for_stopped_status(self, doctype, docname): - stopped = webnotes.conn.sql("select name from `tab%s` where name = '%s' and status = 'Stopped'" % - ( doctype, docname)) + stopped = webnotes.conn.sql("""select name from `tab%s` where name = '%s' and + status = 'Stopped'""", (doctype, docname)) if stopped: - msgprint("One cannot do any transaction against %s : %s, it's status is 'Stopped'" % - ( doctype, docname), raise_exception=1) + webnotes.throw("One cannot do any transaction against %s : %s, it's status is 'Stopped'" % + (doctype, docname)) - def check_docstatus(self, check, doctype, docname , detail_doctype = ''): + def check_docstatus(self, check, doctype, docname, detail_doctype = ''): if check == 'Next': submitted = webnotes.conn.sql("""select t1.name from `tab%s` t1,`tab%s` t2 where t1.name = t2.parent and t2.prevdoc_docname = %s and t1.docstatus = 1""" % (doctype, detail_doctype, '%s'), docname) if submitted: - msgprint(cstr(doctype) + ": " + cstr(submitted[0][0]) - + _(" has already been submitted."), raise_exception=1) + webnotes.throw(cstr(doctype) + ": " + cstr(submitted[0][0]) + + _("has already been submitted.")) if check == 'Previous': submitted = webnotes.conn.sql("""select name from `tab%s` - where docstatus = 1 and name = %s"""% (doctype, '%s'), docname) + where docstatus = 1 and name = %s""" % (doctype, '%s'), docname) if not submitted: - msgprint(cstr(doctype) + ": " + cstr(submitted[0][0]) - + _(" not submitted"), raise_exception=1) + webnotes.throw(cstr(doctype) + ": " + cstr(submitted[0][0]) + _("not submitted")) diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 17db5f4f85..c1185a1b12 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -154,20 +154,20 @@ class DocType: for d in getlist(self.doclist, 'pp_details'): self.validate_bom_no(d) if not flt(d.planned_qty): - webnotes.throw(_("Please Enter Planned Qty for item: %s at row no: %s") % + webnotes.throw("Please Enter Planned Qty for item: %s at row no: %s" % (d.item_code, d.idx)) def validate_bom_no(self, d): if not d.bom_no: - webnotes.throw(_("Please enter bom no for item: %s at row no: %s") % + webnotes.throw("Please enter bom no for item: %s at row no: %s" % (d.item_code, d.idx)) else: bom = webnotes.conn.sql("""select name from `tabBOM` where name = %s and item = %s and docstatus = 1 and is_active = 1""", (d.bom_no, d.item_code), as_dict = 1) if not bom: - webnotes.throw(_("""Incorrect BOM No: %s entered for item: %s at row no: %s - May be BOM is inactive or for other item or does not exists in the system""") % + webnotes.throw("""Incorrect BOM No: %s entered for item: %s at row no: %s + May be BOM is inactive or for other item or does not exists in the system""" % (d.bom_no, d.item_doce, d.idx)) def raise_production_order(self): @@ -290,11 +290,12 @@ class DocType: for item_details in self.item_dict[item]: item_list.append([item, item_details[1], item_details[2], item_details[0]]) item_qty = webnotes.conn.sql("""select warehouse, indented_qty, ordered_qty, actual_qty - from `tabBin` where item_code = %s""", item) + from `tabBin` where item_code = %s""", item, as_dict=1) i_qty, o_qty, a_qty = 0, 0, 0 for w in item_qty: - i_qty, o_qty, a_qty = i_qty + flt(w[1]), o_qty + flt(w[2]), a_qty + flt(w[3]) - item_list.append(['', '', '', '', w[0], flt(w[1]), flt(w[2]), flt(w[3])]) + i_qty, o_qty, a_qty = i_qty + flt(w.indented_qty), o_qty + flt(w.ordered_qty), a_qty + flt(w.actual_qty) + item_list.append(['', '', '', '', w.warehouse, flt(w.indented_qty), + flt(w.ordered_qty), flt(w.actual_qty)]) if item_qty: item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty]) @@ -405,7 +406,7 @@ class DocType: if purchase_request_list: pur_req = ["""%s""" % \ (p, p) for p in purchase_request_list] - msgprint(_("Material Request(s) created: \n%s") % + msgprint("Material Request(s) created: \n%s" % "\n".join(pur_req)) else: msgprint(_("Nothing to request")) \ No newline at end of file diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py index 67d36eff1b..50661a316a 100644 --- a/stock/doctype/material_request/material_request.py +++ b/stock/doctype/material_request/material_request.py @@ -38,18 +38,18 @@ class DocType(BuyingController): for so_no in so_items.keys(): for item in so_items[so_no].keys(): already_indented = webnotes.conn.sql("""select sum(qty) from `tabMaterial Request Item` - where item_code = '%s' and sales_order_no = '%s' and - docstatus = 1 and parent != '%s'""" % (item, so_no, self.doc.name)) + where item_code = %s and sales_order_no = %s and + docstatus = 1 and parent != %s""", (item, so_no, self.doc.name)) already_indented = already_indented and flt(already_indented[0][0]) or 0 actual_so_qty = webnotes.conn.sql("""select sum(qty) from `tabSales Order Item` - where parent = '%s' and item_code = '%s' and docstatus = 1 - group by parent""" % (so_no, item)) + where parent = %s and item_code = %s and docstatus = 1 + group by parent""", (so_no, item)) actual_so_qty = actual_so_qty and flt(actual_so_qty[0][0]) or 0 if actual_so_qty and (flt(so_items[so_no][item]) + already_indented > actual_so_qty): - webnotes.throw(_("You can raise indent of maximum qty: %s for item: %s against sales order: %s\ - \n Anyway, you can add more qty in new row for the same item.") + webnotes.throw("You can raise indent of maximum qty: %s for item: %s against sales order: %s\ + \n Anyway, you can add more qty in new row for the same item." % (actual_so_qty - already_indented, item, so_no)) def validate_schedule_date(self): @@ -105,8 +105,10 @@ class DocType(BuyingController): self.update_bin(is_submit = 1, is_stopped = 0) def check_modified_date(self): - mod_db = webnotes.conn.sql("select modified from `tabMaterial Request` where name = '%s'" % self.doc.name) - date_diff = webnotes.conn.sql("select TIMEDIFF('%s', '%s')" % (mod_db[0][0], cstr(self.doc.modified))) + mod_db = webnotes.conn.sql("""select modified from `tabMaterial Request` where name = %s""", + self.doc.name) + date_diff = webnotes.conn.sql("""select TIMEDIFF('%s', '%s')""" + % (mod_db[0][0], cstr(self.doc.modified))) if date_diff and date_diff[0][0]: webnotes.throw(cstr(self.doc.doctype) + " => " + cstr(self.doc.name) + " has been modified. Please Refresh.") @@ -120,7 +122,7 @@ class DocType(BuyingController): webnotes.conn.set(self.doc, 'status', cstr(status)) # Step 3:=> Acknowledge User - msgprint(self.doc.doctype + ": " + self.doc.name + _(" has been %s.") % ((status == 'Submitted') and 'Unstopped' or cstr(status)) ) + msgprint(self.doc.doctype + ": " + self.doc.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status))) def on_cancel(self): From d94bab0e1d4ea3858180afe5a23d6e46f0c4d0dc Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 17 Dec 2013 15:05:37 +0530 Subject: [PATCH 5/5] [fix] [minor] sql query related changes in purchase common --- buying/doctype/purchase_common/purchase_common.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index b480caffc7..8c4fbffe5b 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -139,20 +139,21 @@ class DocType(BuyingController): get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty' qty = webnotes.conn.sql("""select sum(%s) from `tab%s` where %s = %s and - docstatus = 1 and parent != %s""", (get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) + docstatus = 1 and parent != %s""" % (get_qty, curr_doctype, ref_tab_fname, '%s', '%s'), + (ref_tab_dn, curr_parent_name)) qty = qty and flt(qty[0][0]) or 0 # get total qty of ref doctype #-------------------- max_qty = webnotes.conn.sql("""select qty from `tab%s` where name = %s - and docstatus = 1""", (ref_doc_tname, ref_tab_dn)) + and docstatus = 1""" % (ref_doc_tname, '%s'), ref_tab_dn) max_qty = max_qty and flt(max_qty[0][0]) or 0 return cstr(qty)+'~~~'+cstr(max_qty) def check_for_stopped_status(self, doctype, docname): - stopped = webnotes.conn.sql("""select name from `tab%s` where name = '%s' and - status = 'Stopped'""", (doctype, docname)) + stopped = webnotes.conn.sql("""select name from `tab%s` where name = %s and + status = 'Stopped'""" % (doctype, '%s'), docname) if stopped: webnotes.throw("One cannot do any transaction against %s : %s, it's status is 'Stopped'" % (doctype, docname))