From 7c76f80966b1e59c2c11ee2549dd2cb50f745f4c Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 16 Feb 2012 10:58:45 +0100 Subject: [PATCH 01/13] gateway patch --- .../jan_mar_2012/website/getfile_rename.py | 16 +++++++++++----- erpnext/startup/event_handlers.py | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/erpnext/patches/jan_mar_2012/website/getfile_rename.py b/erpnext/patches/jan_mar_2012/website/getfile_rename.py index 8f7cede659b..15aa8157e6f 100644 --- a/erpnext/patches/jan_mar_2012/website/getfile_rename.py +++ b/erpnext/patches/jan_mar_2012/website/getfile_rename.py @@ -23,17 +23,23 @@ def execute(): txt = get_file_id(txt) webnotes.conn.sql("""update `tab%s` set %s=%s where name=%s""" % \ - (table[0], table[1], '%s', '%s'), (txt, item[0]), debug=1) + (table[0], table[1], '%s', '%s'), (txt, item[0])) # control panel, client name txt = webnotes.conn.get_value('Control Panel',None,'client_name') - txt = get_file_id(txt) - webnotes.conn.set_value('Control Panel', None, 'client_name', txt.replace('index.cgi?cmd=get_file&fname=', 'files/')) - + if txt: + txt = get_file_id(txt) + webnotes.conn.set_value('Control Panel', None, 'client_name', txt.replace('index.cgi?cmd=get_file&fname=', 'files/')) + def get_file_id(txt): """old file links may be from fileid or filename""" import re match = re.search('files/([^"\']*)', txt) + + if not match: + print txt + return txt + fname = match.groups()[0] if not fname.startswith('FileData'): fid = webnotes.conn.sql("""select name from `tabFile Data` @@ -41,4 +47,4 @@ def get_file_id(txt): if fid: fid = fid[0][0].replace('/', '-') txt = txt.replace(fname, fid) - return txt \ No newline at end of file + return txt diff --git a/erpnext/startup/event_handlers.py b/erpnext/startup/event_handlers.py index b6b1f9f2580..9740be48801 100644 --- a/erpnext/startup/event_handlers.py +++ b/erpnext/startup/event_handlers.py @@ -7,7 +7,7 @@ def on_login(login_manager): """ called from login manager, before login """ - if login_manager.user not in ('Guest', None, ''): + if login_manager.user not in ('Guest', None, '') and webnotes.conn.cur_db_name!='accounts' and webnotes.conn.get_value('Control Panel', 'Control Panel', 'account_id')!='s5u011': try: login_manager = login_as(login_manager) update_account_details() @@ -32,7 +32,7 @@ def on_login_post_session(login_manager): sid!=%s""", \ (webnotes.session['user'], webnotes.session['sid']), as_list=1) - if webnotes.session['user'] not in ('Guest'): + if webnotes.session['user'] not in ('Guest') and webnotes.conn.cur_db_name!='accounts': # create feed from webnotes.utils import nowtime home.make_feed('Login', 'Profile', login_manager.user, login_manager.user, From ff336776240afee52076135eb3afd69e382da45e Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 16:26:08 +0530 Subject: [PATCH 02/13] Packing Slip Fix --- .../Delivery Note-Packing Slip.txt | 8 ++--- .../doctype/delivery_note/delivery_note.js | 2 +- .../doctype/delivery_note/delivery_note.py | 23 ++++++++++++ .../doctype/packing_slip/packing_slip.js | 9 +++-- .../doctype/packing_slip/packing_slip.py | 36 ++++++++++++++----- 5 files changed, 59 insertions(+), 19 deletions(-) diff --git a/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt b/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt index baf2b7465e7..f59ab733517 100644 --- a/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt +++ b/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-02-13 11:28:48', + 'creation': '2012-02-02 11:50:33', 'docstatus': 0, - 'modified': '2012-02-13 11:28:48', + 'modified': '2012-02-21 16:11:29', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -34,7 +34,7 @@ 'from_doctype': u'Delivery Note', 'module': u'Stock', 'name': '__common__', - 'ref_doc_submitted': 1, + 'ref_doc_submitted': 0, 'to_doctype': u'Packing Slip' }, @@ -77,7 +77,7 @@ 'from_table': u'Delivery Note', 'match_id': 0, 'to_table': u'Packing Slip', - 'validation_logic': u'docstatus=1' + 'validation_logic': u'docstatus=0' }, # Table Mapper Detail diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index d9f479504a3..10297dde835 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -52,7 +52,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { unhide_field(['SMS','Send SMS', 'message', 'customer_mobile_no', 'Repair Delivery Note']); } - if(doc.docstatus==1) { + if(doc.docstatus==0 && !doc.__islocal) { cur_frm.add_custom_button('Make Packing Slip', cur_frm.cscript['Make Packing Slip']); } diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 60aee13512a..40fdc94ca9e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -309,6 +309,7 @@ class DocType(TransactionBase): # ON SUBMIT # ================================================================================================= def on_submit(self): + self.validate_packed_qty() set(self.doc, 'message', 'Items against your Order #%s have been delivered. Delivery #%s: ' % (self.doc.po_no, self.doc.name)) self.check_qty_in_stock() # Check for Approving Authority @@ -326,6 +327,28 @@ class DocType(TransactionBase): set(self.doc, 'status', 'Submitted') + def validate_packed_qty(self): + """ + Validate that if packed qty exists, it should be equal to qty + """ + if not any([d.fields.get('packed_qty') for d in self.doclist]): + return + packing_error_list = [] + for d in self.doclist: + if d.doctype != 'Delivery Note Detail': continue + if d.fields.get('qty') != d.fields.get('packed_qty'): + packing_error_list.append([ + d.fields.get('item_code', ''), + d.fields.get('qty', ''), + d.fields.get('packed_qty', '') + ]) + if packing_error_list: + from webnotes.utils import cstr + err_msg = "\n".join([("Item: " + d[0] + ", Qty: " + cstr(d[1]) \ + + ", Packed: " + cstr(d[2])) for d in packing_error_list]) + webnotes.msgprint("Packing Error:\n" + err_msg, raise_exception=1) + + # *********** Checks whether actual quantity is present in warehouse ************* def check_qty_in_stock(self): for d in getlist(self.doclist, 'packing_details'): diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.js b/erpnext/stock/doctype/packing_slip/packing_slip.js index 2e728f687fe..7359ffad1a4 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.js +++ b/erpnext/stock/doctype/packing_slip/packing_slip.js @@ -1,12 +1,12 @@ cur_frm.fields_dict['delivery_note'].get_query = function(doc, cdt, cdn) { - return 'SELECT name FROM `tabDelivery Note` WHERE docstatus=1 AND %(key)s LIKE "%s"'; + return 'SELECT name FROM `tabDelivery Note` WHERE docstatus=0 AND %(key)s LIKE "%s"'; } cur_frm.fields_dict['item_details'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) { return 'SELECT name, description FROM `tabItem` WHERE name IN ( \ - SELECT item_code FROM `tabDelivery Note Detail` \ - WHERE parent="' + doc.delivery_note + '") AND %(key)s LIKE "%s" LIMIT 50'; + SELECT item_code FROM `tabDelivery Note Detail` dnd \ + WHERE parent="' + doc.delivery_note + '" AND qty > packed_qty) AND %(key)s LIKE "%s" LIMIT 50'; } @@ -39,8 +39,7 @@ cur_frm.cscript.update_item_details = function(doc) { if(r.exc) { msgprint(r.exc); } else { - refresh_field('item_details'); - refresh_field('naming_series'); + refresh_many(['item_details', 'naming_series', 'from_case_no', 'to_case_no']) } }); } diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py index 33ec2b52c23..23367c73415 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -28,9 +28,10 @@ class DocType: WHERE name=%(delivery_note)s """, self.doc.fields) - if not(res and res[0][0]==1): + if not(res and res[0][0]==0): webnotes.msgprint("""Invalid Delivery Note. Delivery Note should exist - and should be submitted. Please rectify and try again.""", raise_exception=1) + and should be in draft state. Please rectify and try again.""", + raise_exception=1) def validate_case_nos(self): @@ -46,12 +47,8 @@ class DocType: """, self.doc.fields) if res: - recommended_case_no = webnotes.conn.sql("""\ - SELECT MAX(to_case_no) FROM `tabPacking Slip` - WHERE delivery_note = %(delivery_note)s AND docstatus=1""", self.doc.fields) - webnotes.msgprint("""Case No(s). already in use. Please rectify and try again. - Recommended From Case No. = %s""" % (cint(recommended_case_no[0][0]) + 1), + Recommended From Case No. = %s""" % self.get_recommended_case_no(), raise_exception=1) @@ -75,13 +72,18 @@ class DocType: * Item Quantity dict of current packing slip doc * No. of Cases of this packing slip """ - item_codes = ", ".join([('"' + d.item_code + '"') for d in self.doclist]) + item_codes = ", ".join([('"' + d.item_code + '"') for d in + self.doclist]) + + if not item_codes: webnotes.msgprint("No Items to Pack", + raise_exception=1) res = webnotes.conn.sql("""\ SELECT item_code, IFNULL(SUM(qty), 0) as qty, IFNULL(packed_qty, 0) as packed_qty, stock_uom FROM `tabDelivery Note Detail` WHERE parent = "%s" AND item_code IN (%s) - GROUP BY item_code""" % (self.doc.delivery_note, item_codes), as_dict=1) + GROUP BY item_code""" % (self.doc.delivery_note, item_codes), + as_dict=1) ps_item_qty = dict([[d.item_code, d.qty] for d in self.doclist]) @@ -150,7 +152,23 @@ class DocType: """ Fill empty columns in Packing Slip Detail """ + self.doc.from_case_no = self.get_recommended_case_no() + from webnotes.model.code import get_obj for d in self.doclist: psd_obj = get_obj(doc=d) psd_obj.get_item_details(self.doc.delivery_note) + + + def get_recommended_case_no(self): + """ + Returns the next case no. for a new packing slip for a delivery + note + """ + recommended_case_no = webnotes.conn.sql("""\ + SELECT MAX(to_case_no) FROM `tabPacking Slip` + WHERE delivery_note = %(delivery_note)s AND docstatus=1""", self.doc.fields) + + return cint(recommended_case_no[0][0]) + 1 + + From 8e703ef26f04b16db08a2b821a2025f42adfbc49 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 16:29:46 +0530 Subject: [PATCH 03/13] packing slip fix --- .../patches/jan_mar_2012/fix_packing_slip.py | 20 +++++++++++++++++++ erpnext/patches/patch_list.py | 7 ++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/jan_mar_2012/fix_packing_slip.py diff --git a/erpnext/patches/jan_mar_2012/fix_packing_slip.py b/erpnext/patches/jan_mar_2012/fix_packing_slip.py new file mode 100644 index 00000000000..98eb8259810 --- /dev/null +++ b/erpnext/patches/jan_mar_2012/fix_packing_slip.py @@ -0,0 +1,20 @@ +def execute(): + """ + * Change DN to PS mapper + + Set Ref doc should be submitted to 0 + + Set validation logic of DN PS Table mapper record to docstatus=0 + """ + import webnotes + webnotes.conn.sql("""\ + UPDATE `tabDocType Mapper` + SET ref_doc_submitted=0 + WHERE name='Delivery Note-Packing Slip'""") + + webnotes.conn.sql("""\ + UPDATE `tabTable Mapper Detail` + SET validation_logic='docstatus=0' + WHERE parent='Delivery Note-Packing Slip' + AND docstatus=0 + AND from_table='Delivery Note' + AND to_table='Packing Slip'""") + diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py index ccaebaec9ff..e83d2a6aa49 100644 --- a/erpnext/patches/patch_list.py +++ b/erpnext/patches/patch_list.py @@ -99,5 +99,10 @@ patch_list = [ 'patch_module': 'patches.jan_mar_2012', 'patch_file': 'reload_item', 'description': 'reload item' - } + }, + { + 'patch_module': 'patches.jan_mar_2012', + 'patch_file': 'fix_packing_slip', + 'description': 'Update Mapper Delivery Note-Packing Slip' + }, ] From 5ff541b53c36f95f09744f38365b5bd3f5aa0525 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 16:44:31 +0530 Subject: [PATCH 04/13] fix in remove_archive patch --- erpnext/patches/jan_mar_2012/remove_archive.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/patches/jan_mar_2012/remove_archive.py b/erpnext/patches/jan_mar_2012/remove_archive.py index cce4d8e034b..9f685b6f30b 100644 --- a/erpnext/patches/jan_mar_2012/remove_archive.py +++ b/erpnext/patches/jan_mar_2012/remove_archive.py @@ -8,12 +8,17 @@ def execute(): from webnotes.utils import archive arc_tables = webnotes.conn.sql('show tables like "arc%"') try: + count = 0 for tab in arc_tables: tab = tab[0] dt = tab[3:] res = webnotes.conn.sql("SELECT name FROM `%s`" % tab) for dn in res: archive.archive_doc(dt, dn[0], restore=1) + count++ + if not count%100: + webnotes.conn.commit() + webnotes.conn.begin() except Exception, e: raise e else: From 62a3872480fcfb5c0ff6fc79f7b40d24f81056cf Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 16:46:57 +0530 Subject: [PATCH 05/13] fix in remove_archive --- erpnext/patches/jan_mar_2012/remove_archive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/jan_mar_2012/remove_archive.py b/erpnext/patches/jan_mar_2012/remove_archive.py index 9f685b6f30b..dbc61d7e913 100644 --- a/erpnext/patches/jan_mar_2012/remove_archive.py +++ b/erpnext/patches/jan_mar_2012/remove_archive.py @@ -15,7 +15,7 @@ def execute(): res = webnotes.conn.sql("SELECT name FROM `%s`" % tab) for dn in res: archive.archive_doc(dt, dn[0], restore=1) - count++ + count += 1 if not count%100: webnotes.conn.commit() webnotes.conn.begin() From b8fa4a37e541fc4825e47df0f426a3c9aa5001af Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 17:27:24 +0530 Subject: [PATCH 06/13] fix in remove_archive --- erpnext/patches/jan_mar_2012/remove_archive.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/patches/jan_mar_2012/remove_archive.py b/erpnext/patches/jan_mar_2012/remove_archive.py index dbc61d7e913..5f2cdab8c01 100644 --- a/erpnext/patches/jan_mar_2012/remove_archive.py +++ b/erpnext/patches/jan_mar_2012/remove_archive.py @@ -8,17 +8,13 @@ def execute(): from webnotes.utils import archive arc_tables = webnotes.conn.sql('show tables like "arc%"') try: - count = 0 + webnotes.conn.auto_commit_on_excess = 1 for tab in arc_tables: tab = tab[0] dt = tab[3:] res = webnotes.conn.sql("SELECT name FROM `%s`" % tab) for dn in res: archive.archive_doc(dt, dn[0], restore=1) - count += 1 - if not count%100: - webnotes.conn.commit() - webnotes.conn.begin() except Exception, e: raise e else: From c70e8d9791160679f1d065d9bc4cf64cc7c61683 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 17:30:36 +0530 Subject: [PATCH 07/13] fix in remove_archive --- erpnext/patches/jan_mar_2012/remove_archive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/jan_mar_2012/remove_archive.py b/erpnext/patches/jan_mar_2012/remove_archive.py index 5f2cdab8c01..1b914d5606f 100644 --- a/erpnext/patches/jan_mar_2012/remove_archive.py +++ b/erpnext/patches/jan_mar_2012/remove_archive.py @@ -8,7 +8,7 @@ def execute(): from webnotes.utils import archive arc_tables = webnotes.conn.sql('show tables like "arc%"') try: - webnotes.conn.auto_commit_on_excess = 1 + webnotes.conn.auto_commit_on_many_writes = 1 for tab in arc_tables: tab = tab[0] dt = tab[3:] From ffbfd2c60a8f8df298456717ed20cea91b3e1dbb Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 21 Feb 2012 18:15:31 +0530 Subject: [PATCH 08/13] Update feed on submission --- erpnext/home/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/home/__init__.py b/erpnext/home/__init__.py index 75556e39370..5f9c44737a8 100644 --- a/erpnext/home/__init__.py +++ b/erpnext/home/__init__.py @@ -66,7 +66,7 @@ def make_feed(feedtype, doctype, name, owner, subject, color): def update_feed(doc, method=None): "adds a new feed" - if method=='on_update': + if method in ['on_update', 'on_submit']: subject, color = feed_dict.get(doc.doctype, [None, None]) if subject: make_feed('', doc.doctype, doc.name, doc.owner, subject % doc.fields, color) From cab5b31ffa0573d01e3bce128131cbcf2335390d Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 22 Feb 2012 18:33:39 +0530 Subject: [PATCH 09/13] change product's document type to Master --- erpnext/website/doctype/product/product.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/website/doctype/product/product.txt b/erpnext/website/doctype/product/product.txt index 6258691a911..0405e4ca51e 100644 --- a/erpnext/website/doctype/product/product.txt +++ b/erpnext/website/doctype/product/product.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-01-30 16:21:29', + 'creation': '2012-02-17 15:53:22', 'docstatus': 0, - 'modified': '2012-02-06 16:15:29', + 'modified': '2012-02-22 18:32:46', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -18,12 +18,13 @@ 'colour': u'White:FFF', 'description': u'A Product is shown on the website and is linked to an item.', 'doctype': 'DocType', + 'document_type': u'Master', 'max_attachments': 5, 'module': u'Website', 'name': '__common__', 'section_style': u'Simple', 'show_in_menu': 0, - 'version': 11 + 'version': 12 }, # These values are common for all DocField From 8569b7400a2a00be18702e479ad028463446ef8a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 23 Feb 2012 10:46:24 +0530 Subject: [PATCH 10/13] Update erpnext/production/doctype/bill_of_materials/bill_of_materials.py --- .../production/doctype/bill_of_materials/bill_of_materials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/production/doctype/bill_of_materials/bill_of_materials.py b/erpnext/production/doctype/bill_of_materials/bill_of_materials.py index 117742576d0..decb9fefe2a 100644 --- a/erpnext/production/doctype/bill_of_materials/bill_of_materials.py +++ b/erpnext/production/doctype/bill_of_materials/bill_of_materials.py @@ -268,7 +268,7 @@ class DocType: def check_if_item_repeated(self, item, op, check_list): if [cstr(item), cstr(op)] in check_list: - msgprint("Item %s has been entered twice against same operation" % d.item_code, raise_exception = 1) + msgprint("Item %s has been entered twice against same operation" % item, raise_exception = 1) else: check_list.append([cstr(item), cstr(op)]) From 9f94275d65c54e6d0663cc74295fefde1688f5bc Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 23 Feb 2012 11:27:40 +0530 Subject: [PATCH 11/13] allow deletion of products --- erpnext/patches/jan_mar_2012/website/all.py | 2 ++ .../patches/jan_mar_2012/website/allow_product_delete.py | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 erpnext/patches/jan_mar_2012/website/allow_product_delete.py diff --git a/erpnext/patches/jan_mar_2012/website/all.py b/erpnext/patches/jan_mar_2012/website/all.py index c68e65369c9..1443f361fbb 100644 --- a/erpnext/patches/jan_mar_2012/website/all.py +++ b/erpnext/patches/jan_mar_2012/website/all.py @@ -5,6 +5,7 @@ import patches.jan_mar_2012.website.cleanups import patches.jan_mar_2012.website.domain_list import patches.jan_mar_2012.website.file_data_rename import patches.jan_mar_2012.website.analytics +import patches.jan_mar_2012.website.allow_product_delete def execute(): @@ -15,3 +16,4 @@ def execute(): patches.jan_mar_2012.website.domain_list.execute() patches.jan_mar_2012.website.file_data_rename.execute() patches.jan_mar_2012.website.analytics.execute() + patches.jan_mar_2012.website.allow_product_delete.execute() diff --git a/erpnext/patches/jan_mar_2012/website/allow_product_delete.py b/erpnext/patches/jan_mar_2012/website/allow_product_delete.py new file mode 100644 index 00000000000..54c0447a196 --- /dev/null +++ b/erpnext/patches/jan_mar_2012/website/allow_product_delete.py @@ -0,0 +1,7 @@ +def execute(): + """ + Allow deletion of products + """ + import webnotes + webnotes.conn.sql("""UPDATE `tabDocPerm` SET cancel=1 + WHERE parent='Product' AND role='Website Manager'""") From bfa58a35168d52e22387ddd77c1e09f29a4cc07a Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 23 Feb 2012 11:31:17 +0530 Subject: [PATCH 12/13] allow deletion of products --- erpnext/patches/jan_mar_2012/website/allow_product_delete.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/jan_mar_2012/website/allow_product_delete.py b/erpnext/patches/jan_mar_2012/website/allow_product_delete.py index 54c0447a196..fbef48f11e0 100644 --- a/erpnext/patches/jan_mar_2012/website/allow_product_delete.py +++ b/erpnext/patches/jan_mar_2012/website/allow_product_delete.py @@ -4,4 +4,5 @@ def execute(): """ import webnotes webnotes.conn.sql("""UPDATE `tabDocPerm` SET cancel=1 - WHERE parent='Product' AND role='Website Manager'""") + WHERE parent='Product' AND role='Website Manager' + AND permlevel=0""") From ef041114bbdfc1a67b514ca85b750476e95927b4 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 23 Feb 2012 12:56:45 +0530 Subject: [PATCH 13/13] show submittable warning --- .../permission_engine/permission_engine.html | 6 +- .../permission_engine/permission_engine.js | 774 +++++++++--------- 2 files changed, 404 insertions(+), 376 deletions(-) diff --git a/erpnext/setup/page/permission_engine/permission_engine.html b/erpnext/setup/page/permission_engine/permission_engine.html index 1b9cab20680..7831447a6a5 100644 --- a/erpnext/setup/page/permission_engine/permission_engine.html +++ b/erpnext/setup/page/permission_engine/permission_engine.html @@ -1,4 +1,8 @@
-
\ No newline at end of file + + diff --git a/erpnext/setup/page/permission_engine/permission_engine.js b/erpnext/setup/page/permission_engine/permission_engine.js index 378ad0cff2e..f4f6fe8b320 100644 --- a/erpnext/setup/page/permission_engine/permission_engine.js +++ b/erpnext/setup/page/permission_engine/permission_engine.js @@ -1,397 +1,421 @@ pscript['onload_Permission Engine'] = function() { - // header and toolbar - var h = new PageHeader('pe_header','Permissions Manager','Set specific permissions for Roles') - - if(!pscript.perm_engine) pscript.perm_engine = new pscript.PermEngine(); + // header and toolbar + var h = new PageHeader('pe_header','Permissions Manager','Set specific permissions for Roles') + + if(!pscript.perm_engine) pscript.perm_engine = new pscript.PermEngine(); } pscript.PermEngine = function() { - // create UI elements - this.wrapper = $i('perm_engine_div'); - - this.head = $a(this.wrapper, 'div'); - this.body = $a(this.wrapper, 'div'); - this.footer = $a(this.wrapper, 'div'); + // create UI elements + this.wrapper = $i('perm_engine_div'); + + this.head = $a(this.wrapper, 'div'); + this.body = $a(this.wrapper, 'div'); + this.footer = $a(this.wrapper, 'div'); - var lab = $a(this.body,'div', '', {backgroundColor:'#FFD', padding:'8px', margin:'16px 0px'}); - lab.innerHTML = 'Please select the item for which you want to set permissions'; - - this.make_head(); - this.load_options(); + var lab = $a(this.body,'div', '', {backgroundColor:'#FFD', padding:'8px', margin:'16px 0px'}); + lab.innerHTML = 'Please select the item for which you want to set permissions'; + + this.make_head(); + this.load_options(); } // Make Head // ------------- pscript.PermEngine.prototype.make_head = function() { - var me = this; - - var make_select = function(label) { - var w = $a(me.head, 'div', '', {margin:'8px 0px'}); - var t = make_table(w,1,2,'300px',['50%','50%']); - $td(t,0,0).innerHTML = label; - var s = $a($td(t,0,1),'select','',{width:'140px'}); - s.wrapper = w; - return s; - } - - var make_button = function(label, parent, green) { - return $btn(parent, label, null, {margin:'8px 0px', display:'none'}, (green ? 'green' : null)); - } - - - // Set Permissions for - this.type_select = make_select('Set Permissions For'); - this.type_select.onchange = function() { - me.get_permissions(); - } - - // Update Button - this.add_button = make_button('+ Add A New Rule', this.head, 0); - this.add_button.onclick = function() { - me.add_permission(); - } + var me = this; + + var make_select = function(label) { + var w = $a(me.head, 'div', '', {margin:'8px 0px'}); + var t = make_table(w,1,2,'300px',['50%','50%']); + $td(t,0,0).innerHTML = label; + var s = $a($td(t,0,1),'select','',{width:'140px'}); + s.wrapper = w; + return s; + } + + var make_button = function(label, parent, green) { + return $btn(parent, label, null, {margin:'8px 0px', display:'none'}, (green ? 'green' : null)); + } + + + // Set Permissions for + this.type_select = make_select('Set Permissions For'); + this.type_select.onchange = function() { + me.get_permissions(); + } + + // Update Button + this.add_button = make_button('+ Add A New Rule', this.head, 0); + this.add_button.onclick = function() { + me.add_permission(); + } - // Update Button - this.update_button = make_button('Update', this.footer, 1); - this.update_button.onclick = function() { - me.update_permissions(); - } + // Update Button + this.update_button = make_button('Update', this.footer, 1); + this.update_button.onclick = function() { + me.update_permissions(); + } } // Add Permissions // ----------------- pscript.PermEngine.prototype.add_permission = function() { - var me = this; - if(!this.add_permission_dialog) { - - // dialog - var d = new Dialog(400,400,'Add Permission'); - d.make_body([['Select','Role'],['Select','Level'],['Button','Add']]) + var me = this; + if(!this.add_permission_dialog) { + + // dialog + var d = new Dialog(400,400,'Add Permission'); + d.make_body([['Select','Role'],['Select','Level'],['Button','Add']]) - add_sel_options(d.widgets['Role'], this.roles, ''); - add_sel_options(d.widgets['Level'], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0); + add_sel_options(d.widgets['Role'], this.roles, ''); + add_sel_options(d.widgets['Level'], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0); - // add - d.widgets['Add'].onclick = function() { - if(!sel_val(d.widgets['Role'])) { - msgprint('Please select Role'); return; - } - var callback = function(r, rt) { - // reload - me.get_permissions(); - d.hide(); - } - $c_obj('Permission Control','add_permission',JSON.stringify([sel_val(me.type_select), sel_val(d.widgets['Role']), sel_val(d.widgets['Level'])]), callback); - } + // add + d.widgets['Add'].onclick = function() { + if(!sel_val(d.widgets['Role'])) { + msgprint('Please select Role'); return; + } + var callback = function(r, rt) { + // reload + me.get_permissions(); + d.hide(); + } + $c_obj('Permission Control','add_permission',JSON.stringify([sel_val(me.type_select), sel_val(d.widgets['Role']), sel_val(d.widgets['Level'])]), callback); + } - this.add_permission_dialog = d; - } - this.add_permission_dialog.show(); + this.add_permission_dialog = d; + } + this.add_permission_dialog.show(); } // Hide Fields // ----------------- pscript.PermEngine.prototype.hide_fields = function() { - $dh(this.role_select.wrapper); - this.type_select.disabled = false; - this.body.innerHTML = ''; + $dh(this.role_select.wrapper); + this.type_select.disabled = false; + this.body.innerHTML = ''; } // Load Roles And Modules // ----------------------- pscript.PermEngine.prototype.load_options = function() { - var me = this; - $dh(me.update_button); - $dh(me.add_button); + var me = this; + $dh(me.update_button); + $dh(me.add_button); - $c_obj('Permission Control','get_doctype_list','', function(r,rt) { - me.roles = r.message.roles; - - // Type - empty_select(me.type_select); - add_sel_options(me.type_select,add_lists([''], r.message.doctypes)); - - }); + $c_obj('Permission Control','get_doctype_list','', function(r,rt) { + me.roles = r.message.roles; + + // Type + empty_select(me.type_select); + add_sel_options(me.type_select,add_lists([''], r.message.doctypes)); + + }); } // Get DocType and Permissions related to module // -------------------------------------------------- pscript.PermEngine.prototype.get_permissions = function() { - var me = this; - - if(!sel_val(me.type_select)) { - msgprint('Please select a type first!'); return; - } - - $c_obj('Permission Control','get_permissions',sel_val(me.type_select), function(r,rt) { - // Get permissions - if(r.message.perms.length)me.get_results(r.message); - else me.body.innerHTML = '
No Records Found
' - }); + var me = this; + + if(!sel_val(me.type_select)) { + msgprint('Please select a type first!'); return; + } + + $c_obj('Permission Control','get_permissions',sel_val(me.type_select), function(r,rt) { + // Get permissions + if(r.message.perms.length) { + me.get_results(r.message); + } + else me.body.innerHTML = '
No Records Found
' + pscript.show_submittable(); + }); } // Get Results // ------------------ pscript.PermEngine.prototype.get_results = function(r){ - var perms = r.perms; - var me = this; - var doctype = sel_val(me.type_select); - - // show update button - $ds(me.update_button); - $ds(me.add_button); + var perms = r.perms; + var me = this; + var doctype = sel_val(me.type_select); + + // show update button + $ds(me.update_button); + $ds(me.add_button); - this.body.innerHTML = '' - pscript.all_checkboxes = []; - pscript.all_matches = []; - - var head = $a(this.body, 'h3'); head.innerHTML = 'Rules for ' + doctype; - var permt = make_table(me.body, perms.length+1,9,'80%',[],{border:'1px solid #AAA', padding:'3px', verticalAlign:'middle', height:'30px'}); - - // Create Grid for particular DocType - // ------------------------------------ - - // Columns - var col_labels = ['Role','Level','Read','Write','Create','Submit','Cancel','Amend','Restrict By'] - for(var n = 0; n < col_labels.length; n++){ - $y($td(permt,0,n), {backgroundColor:'#DDD', width:(n==0?'30%':(n==8?'21%':'7%'))}) - $td(permt,0,n).innerHTML = col_labels[n]; - $td(permt,0,n).fieldname = col_labels[n].toLowerCase(); - } - - // Rows for Column Level / Role - for(var j = 0; j < perms.length; j++){ - var plevel = $a($td(permt,j+1,1), 'span', 'link_type'); - plevel.innerHTML = perms[j].permlevel; - plevel.doctype = doctype; - plevel.value = perms[j].permlevel; - plevel.onclick = function() {me.get_fields(this.doctype, this.value)} + this.body.innerHTML = '' + pscript.all_checkboxes = []; + pscript.all_matches = []; + + var head = $a(this.body, 'h3'); head.innerHTML = 'Rules for ' + doctype; + var permt = make_table(me.body, perms.length+1,9,'80%',[],{border:'1px solid #AAA', padding:'3px', verticalAlign:'middle', height:'30px'}); + + // Create Grid for particular DocType + // ------------------------------------ + + // Columns + var col_labels = ['Role','Level','Read','Write','Create','Submit','Cancel','Amend','Restrict By'] + for(var n = 0; n < col_labels.length; n++){ + $y($td(permt,0,n), {backgroundColor:'#DDD', width:(n==0?'30%':(n==8?'21%':'7%'))}) + $td(permt,0,n).innerHTML = col_labels[n]; + $td(permt,0,n).fieldname = col_labels[n].toLowerCase(); + } + + // Rows for Column Level / Role + for(var j = 0; j < perms.length; j++){ + var plevel = $a($td(permt,j+1,1), 'span', 'link_type'); + plevel.innerHTML = perms[j].permlevel; + plevel.doctype = doctype; + plevel.value = perms[j].permlevel; + plevel.onclick = function() {me.get_fields(this.doctype, this.value)} - // role - $td(permt,j+1,0).innerHTML = perms[j].role; + // role + $td(permt,j+1,0).innerHTML = perms[j].role; - } - - // Get values - for(var l = 0; l < perms.length; l++){ - for(var m = 0; m < 6; m++){ // (read,write,create,submit,cancel,amend) - var chk = $a_input($td(permt,l+1,m+2), 'checkbox'); - var val = perms[l][$td(permt,0,m+2).fieldname]; - if(val == 1) chk.checked = 1; - else chk.checked = 0; - chk.doctype = doctype; - chk.permlevel = perms[l].permlevel; chk.perm_type = col_labels[m+2].toLowerCase(); chk.role = perms[l].role; - pscript.all_checkboxes.push(chk); - } - } - - // add selects for match - me.add_match_select(r, perms, permt, doctype); + } + + // Get values + for(var l = 0; l < perms.length; l++){ + for(var m = 0; m < 6; m++){ // (read,write,create,submit,cancel,amend) + var chk = $a_input($td(permt,l+1,m+2), 'checkbox'); + var val = perms[l][$td(permt,0,m+2).fieldname]; + if(val == 1) chk.checked = 1; + else chk.checked = 0; + + if(m==3) { chk.onclick = pscript.show_submittable } + + chk.doctype = doctype; + chk.permlevel = perms[l].permlevel; chk.perm_type = col_labels[m+2].toLowerCase(); chk.role = perms[l].role; + pscript.all_checkboxes.push(chk); + } + } + + // add selects for match + me.add_match_select(r, perms, permt, doctype); } +// Show submittable warning +pscript.show_submittable = function() { + var submittable = 0; + for(i in pscript.all_checkboxes) { + c = pscript.all_checkboxes[i]; + if(c.perm_type=='submit' && c.checked) { + submittable = 1; + break; + } + } + if(submittable) { + $('#submittable_warning').toggle(true); + } else { + $('#submittable_warning').toggle(false); + } +} + + // render selects for match // -------------------------------------------- pscript.PermEngine.prototype.add_match_select = function(r, perms, permt, doctype) { - var me = this; - - // add select for match - for(var i=0; i'],['Button','OK']]); - } - else $i('perm_engine_get_fields').innerHTML = ''; + if(!pscript.get_field_dialog) { + pscript.get_field_dialog = new Dialog(750,500,'Fields'); + pscript.get_field_dialog.make_body([['HTML','Fields','
'],['Button','OK']]); + } + else $i('perm_engine_get_fields').innerHTML = ''; } // Get Fields // -------------------- pscript.PermEngine.prototype.get_fields = function(dt, permlevel) { - var me = this; - var callback = function(r,rt){ - // Get Parent DocType Fields - var parent_fields_dict = r.message.parent_fields_dict; - - // Get Child Table Fields if any - var table_fields_dict = r.message.table_fields_dict; - - // Make Fields Dialog Box - me.make_fields_dialog(); - - me.make_fields_table(dt, parent_fields_dict, table_fields_dict, permlevel); - - pscript.get_field_dialog.show(); - pscript.get_field_dialog.widgets['OK'].onclick=function(){ - pscript.get_field_dialog.hide(); - } - } - var args = "{'dt':'"+dt+"','permlevel':"+permlevel+"}" - $c_obj('Permission Control','get_fields', args, callback); + var me = this; + var callback = function(r,rt){ + // Get Parent DocType Fields + var parent_fields_dict = r.message.parent_fields_dict; + + // Get Child Table Fields if any + var table_fields_dict = r.message.table_fields_dict; + + // Make Fields Dialog Box + me.make_fields_dialog(); + + me.make_fields_table(dt, parent_fields_dict, table_fields_dict, permlevel); + + pscript.get_field_dialog.show(); + pscript.get_field_dialog.widgets['OK'].onclick=function(){ + pscript.get_field_dialog.hide(); + } + } + var args = "{'dt':'"+dt+"','permlevel':"+permlevel+"}" + $c_obj('Permission Control','get_fields', args, callback); } @@ -436,90 +460,90 @@ pscript.PermEngine.prototype.get_fields = function(dt, permlevel) { // Make Table of Fields for Dialog Box // -------------------------------------- pscript.PermEngine.prototype.make_fields_table = function(dt, parent_fields_dict, table_fields_dict, permlevel) { - - var make_grid = function(table, fields_dict) { - var col_labels = ['Label','Fieldtype','Fieldname','Options']; - for(var n = 0; n < col_labels.length; n++){ - $a_input(($td(table,0,n)), 'data'); - $td(table,0,n).innerHTML = ''+col_labels[n]+''; - $td(table,0,n).fieldname = col_labels[n].toLowerCase(); - } - - // Add values - for(var i = 0; i < keys(fields_dict).length; i++){ - for(var j = 0; j < 4; j++){ - $a_input(($td(table,i+1,j)), 'data'); - $td(table,i+1,j).innerHTML = cstr(fields_dict[i][$td(table,0,j).fieldname]) - } - } - } + + var make_grid = function(table, fields_dict) { + var col_labels = ['Label','Fieldtype','Fieldname','Options']; + for(var n = 0; n < col_labels.length; n++){ + $a_input(($td(table,0,n)), 'data'); + $td(table,0,n).innerHTML = ''+col_labels[n]+''; + $td(table,0,n).fieldname = col_labels[n].toLowerCase(); + } + + // Add values + for(var i = 0; i < keys(fields_dict).length; i++){ + for(var j = 0; j < 4; j++){ + $a_input(($td(table,i+1,j)), 'data'); + $td(table,i+1,j).innerHTML = cstr(fields_dict[i][$td(table,0,j).fieldname]) + } + } + } - - $i('perm_engine_get_fields').innerHTML = ''+ dt + ' Fields at Level '+ permlevel +':

'; - var parent_field_table = make_table('perm_engine_get_fields',keys(parent_fields_dict).length+1, 4,'100%',['25%','25%','25%','25%'],{border:'1px solid #AAA',padding:'2px'}); - make_grid(parent_field_table, parent_fields_dict); - - child_tables = keys(table_fields_dict) - if(child_tables.length > 0){ - for(var k = 0; k < child_tables.length; k++){ - var tab_fields_det = table_fields_dict[child_tables[k]]; - if(keys(tab_fields_det).length > 0){ - $i('perm_engine_get_fields').innerHTML += '
'+ child_tables[k] + ' Fields at Level '+ permlevel +':

' - var child_field_table = make_table('perm_engine_get_fields',keys(tab_fields_det).length+1, 4,'100%',['25%','25%','25%','25%'],{border:'1px solid #AAA',padding:'2px'}); - make_grid(child_field_table, tab_fields_det); - } - } - } + + $i('perm_engine_get_fields').innerHTML = ''+ dt + ' Fields at Level '+ permlevel +':

'; + var parent_field_table = make_table('perm_engine_get_fields',keys(parent_fields_dict).length+1, 4,'100%',['25%','25%','25%','25%'],{border:'1px solid #AAA',padding:'2px'}); + make_grid(parent_field_table, parent_fields_dict); + + child_tables = keys(table_fields_dict) + if(child_tables.length > 0){ + for(var k = 0; k < child_tables.length; k++){ + var tab_fields_det = table_fields_dict[child_tables[k]]; + if(keys(tab_fields_det).length > 0){ + $i('perm_engine_get_fields').innerHTML += '
'+ child_tables[k] + ' Fields at Level '+ permlevel +':

' + var child_field_table = make_table('perm_engine_get_fields',keys(tab_fields_det).length+1, 4,'100%',['25%','25%','25%','25%'],{border:'1px solid #AAA',padding:'2px'}); + make_grid(child_field_table, tab_fields_det); + } + } + } } // Update Permissions // ----------------------- pscript.PermEngine.prototype.update_permissions = function() { - var me = this; - var out = {}; + var me = this; + var out = {}; - var add_to_out = function(doctype, permlevel, role, key, value) { - if(!out[doctype]) out[doctype] = {}; - if(!out[doctype][permlevel]) out[doctype][permlevel] = {}; - if(!out[doctype][permlevel][role]) out[doctype][permlevel][role] = {}; - out[doctype][permlevel][role][key] = value; - } + var add_to_out = function(doctype, permlevel, role, key, value) { + if(!out[doctype]) out[doctype] = {}; + if(!out[doctype][permlevel]) out[doctype][permlevel] = {}; + if(!out[doctype][permlevel][role]) out[doctype][permlevel][role] = {}; + out[doctype][permlevel][role][key] = value; + } - // check boxes - for(i in pscript.all_checkboxes) { - c = pscript.all_checkboxes[i]; - add_to_out(c.doctype, c.permlevel, c.role, c.perm_type, c.checked ? 1 : 0); - } - - // matches - for(var i=0; i