From a5e972dd89e9d4c5b840daa7f7d151670b2f83f7 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 25 Jun 2012 18:06:37 +0530 Subject: [PATCH 1/6] reserved warehouse in so and delivery warehouse in dn can be different --- .../doctype/sales_common/sales_common.py | 63 ++++++++++++------- .../doctype/sales_order/sales_order.py | 11 ++-- .../doctype/delivery_note/delivery_note.py | 55 ++++++++-------- 3 files changed, 76 insertions(+), 53 deletions(-) diff --git a/erpnext/selling/doctype/sales_common/sales_common.py b/erpnext/selling/doctype/sales_common/sales_common.py index f942a2f0f6..94fabeccdc 100644 --- a/erpnext/selling/doctype/sales_common/sales_common.py +++ b/erpnext/selling/doctype/sales_common/sales_common.py @@ -358,46 +358,64 @@ class DocType(TransactionBase): 'rate' : rate and flt(rate[0]['tax_rate']) or 0 } return ret - - # -------------- - # get item list - # -------------- + + def get_item_list(self, obj, is_stopped): + """get item list""" il = [] for d in getlist(obj.doclist,obj.fname): - reserved_qty = 0 # used for delivery note + reserved_wh, reserved_qty = '', 0 # used for delivery note qty = flt(d.qty) if is_stopped: qty = flt(d.qty) > flt(d.delivered_qty) and flt(flt(d.qty) - flt(d.delivered_qty)) or 0 - if d.prevdoc_doctype == 'Sales Order': # used in delivery note to reduce reserved_qty + if d.prevdoc_doctype == 'Sales Order': + # used in delivery note to reduce reserved_qty # Eg.: if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. # But in this case reserved qty should only be reduced by 10 and not 12. - tot_qty, max_qty, tot_amt, max_amt = self.get_curr_and_ref_doc_details(d.doctype, 'prevdoc_detail_docname', d.prevdoc_detail_docname, 'Sales Order Item', obj.doc.name, obj.doc.doctype) + tot_qty, max_qty, tot_amt, max_amt, reserved_wh = self.get_curr_and_ref_doc_details(d.doctype, 'prevdoc_detail_docname', d.prevdoc_detail_docname, obj.doc.name, obj.doc.doctype) if((flt(tot_qty) + flt(qty) > flt(max_qty))): reserved_qty = -(flt(max_qty)-flt(tot_qty)) else: reserved_qty = - flt(qty) - - warehouse = (obj.fname == "sales_order_details") and d.reserved_warehouse or d.warehouse - + + if obj.doc.doctype == 'Sales Order': + reserved_wh = d.reserved_warehouse + if self.has_sales_bom(d.item_code): for p in getlist(obj.doclist, 'packing_details'): - #if p.parent_item == d.item_code: -- this fails when item with same name appears more than once in delivery note item table if p.parent_detail_docname == d.name: # the packing details table's qty is already multiplied with parent's qty - il.append([warehouse, p.item_code, flt(p.qty), (flt(p.qty)/qty)*(reserved_qty), p.uom, p.batch_no, p.serial_no]) + il.append({ + 'warehouse': d.warehouse, + 'reserved_warehouse': reserved_wh, + 'item_code': p.item_code, + 'qty': flt(p.qty), + 'reserved_qty': (flt(p.qty)/qty)*(reserved_qty), + 'uom': p.uom, + 'batch_no': p.batch_no, + 'serial_no': p.serial_no + }) else: - il.append([warehouse, d.item_code, qty, reserved_qty, d.stock_uom, d.batch_no, d.serial_no]) + il.append({ + 'warehouse': d.warehouse, + 'reserved_warehouse': reserved_wh, + 'item_code': d.item_code, + 'qty': qty, + 'reserved_qty': reserved_qty, + 'uom': d.stock_uom, + 'batch_no': d.batch_no, + 'serial_no': d.serial_no + }) return il - # --------------------------------------------------------------------------------------------- - # get qty, amount already billed or delivered against curr line item for current doctype - # For Eg: SO-RV get total qty, amount from SO and also total qty, amount against that SO in RV - # --------------------------------------------------------------------------------------------- - def get_curr_and_ref_doc_details(self, curr_doctype, ref_tab_fname, ref_tab_dn, ref_doc_tname, curr_parent_name, curr_parent_doctype): - # Get total qty, amt of current doctype (eg RV) except for qty, amt of this transaction + + def get_curr_and_ref_doc_details(self, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name, curr_parent_doctype): + """ Get qty, amount already billed or delivered against curr line item for current doctype + For Eg: SO-RV get total qty, amount from SO and also total qty, amount against that SO in RV + """ + #Get total qty, amt of current doctype (eg RV) except for qty, amt of this transaction if curr_parent_doctype == 'Installation Note': curr_det = webnotes.conn.sql("select sum(qty) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% (curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) qty, amt = curr_det and flt(curr_det[0][0]) or 0, 0 @@ -406,10 +424,9 @@ class DocType(TransactionBase): qty, amt = curr_det and flt(curr_det[0][0]) or 0, curr_det and flt(curr_det[0][1]) or 0 # get total qty of ref doctype - ref_det = webnotes.conn.sql("select qty, amount from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn)) - max_qty, max_amt = ref_det and flt(ref_det[0][0]) or 0, ref_det and flt(ref_det[0][1]) or 0 - - return qty, max_qty, amt, max_amt + so_det = webnotes.conn.sql("select qty, amount, reserved_warehouse from `tabSales Order Item` where name = '%s' and docstatus = 1"% ref_tab_dn) + max_qty, max_amt, res_wh = so_det and flt(so_det[0][0]) or 0, so_det and flt(so_det[0][1]) or 0, so_det and cstr(so_det[0][2]) or '' + return qty, max_qty, amt, max_amt, res_wh # Make Packing List from Sales BOM diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 660a288c25..1c24cfb578 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -457,12 +457,15 @@ class DocType(TransactionBase): # =============================================================================================== def update_stock_ledger(self, update_stock, clear = 0): for d in self.get_item_list(clear): - stock_item = sql("SELECT is_stock_item FROM tabItem where name = '%s'"%(d[1]),as_dict = 1) # stock ledger will be updated only if it is a stock item + stock_item = sql("SELECT is_stock_item FROM tabItem where name = '%s'"%(d['item_code']),as_dict = 1) + # stock ledger will be updated only if it is a stock item if stock_item and stock_item[0]['is_stock_item'] == "Yes": - if not d[0]: - msgprint("Message: Please enter Reserved Warehouse for item %s as it is stock item."% d[1]) + if not d['reserved_warehouse']: + msgprint("Message: Please enter Reserved Warehouse for item %s as it is stock item."% d['item_code']) raise Exception - bin = get_obj('Warehouse', d[0]).update_bin( 0, flt(update_stock) * flt(d[2]), 0, 0, 0, d[1], self.doc.transaction_date,doc_type=self.doc.doctype,doc_name=self.doc.name, is_amended = (self.doc.amended_from and 'Yes' or 'No')) + bin = get_obj('Warehouse', d['reserved_warehouse']).update_bin( 0, flt(update_stock) * flt(d['qty']), \ + 0, 0, 0, d['item_code'], self.doc.transaction_date,doc_type=self.doc.doctype,\ + doc_name=self.doc.name, is_amended = (self.doc.amended_from and 'Yes' or 'No')) # Gets Items from packing list #================================= diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 9c640f4d3c..dce4eaedf6 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -297,13 +297,13 @@ class DocType(TransactionBase): # check if same item, warehouse present in prevdoc # ------------------------------------------------------------------ def validate_items_with_prevdoc(self, d): - if d.prevdoc_doctype == 'Sales Order': - data = sql("select item_code, reserved_warehouse from `tabSales Order Item` where parent = '%s' and name = '%s'" % (d.prevdoc_docname, d.prevdoc_detail_docname)) - if d.prevdoc_doctype == 'Purchase Receipt': - data = sql("select item_code, rejected_warehouse from `tabPurchase Receipt Item` where parent = '%s' and name = '%s'" % (d.prevdoc_docname, d.prevdoc_detail_docname)) - if not data or data[0][0] != d.item_code or data[0][1] != d.warehouse: - msgprint("Item: %s / Warehouse: %s is not matching with Sales Order: %s. Sales Order might be modified after fetching data from it. Please delete items and fetch again." % (d.item_code, d.warehouse, d.prevdoc_docname)) - raise Exception + prev_item_dt = (d.prevdoc_doctype == 'Sales Order') and 'Sales Order Item' or 'Purchase Receipt Item' + data = sql("select item_code from `tab%s` where parent = '%s' and name = '%s'"\ + % (prev_item_dt, d.prevdoc_docname, d.prevdoc_detail_docname)) + if not data or data[0][0] != d.item_code: + msgprint("Item: %s is not matching with Sales Order: %s. Sales Order might be modified after \ + fetching data from it. Please delete items and fetch again." \ + % (d.item_code, d.prevdoc_docname), raise_exception=1) # ********* UPDATE CURRENT STOCK ***************************** @@ -413,16 +413,19 @@ class DocType(TransactionBase): def update_stock_ledger(self, update_stock, is_stopped = 0): self.values = [] for d in self.get_item_list(is_stopped): - stock_item = sql("SELECT is_stock_item, is_sample_item FROM tabItem where name = '%s'"%(d[1]), as_dict = 1) # stock ledger will be updated only if it is a stock item + stock_item = sql("SELECT is_stock_item, is_sample_item FROM tabItem where name = '%s'"%(d['item_code']), as_dict = 1) # stock ledger will be updated only if it is a stock item if stock_item[0]['is_stock_item'] == "Yes": - if not d[0]: - msgprint("Message: Please enter Warehouse for item %s as it is stock item."% d[1]) + if not d['warehouse']: + msgprint("Message: Please enter Warehouse for item %s as it is stock item."% d['item_code']) raise Exception - if d[3] < 0 : - # Reduce Reserved Qty from warehouse - bin = get_obj('Warehouse', d[0]).update_bin(0, flt(update_stock) * flt(d[3]), 0, 0, 0, d[1], self.doc.transaction_date,doc_type=self.doc.doctype,doc_name=self.doc.name, is_amended = (self.doc.amended_from and 'Yes' or 'No')) + if d['reserved_qty'] < 0 : + # Reduce reserved qty from reserved warehouse mentioned in so + bin = get_obj('Warehouse', d['reserved_warehouse']).update_bin(0, flt(update_stock) * flt(d['reserved_qty']), \ + 0, 0, 0, d['item_code'], self.doc.transaction_date,doc_type=self.doc.doctype, \ + doc_name=self.doc.name, is_amended = (self.doc.amended_from and 'Yes' or 'No')) + # Reduce actual qty from warehouse - self.make_sl_entry(d, d[0], - flt(d[2]) , 0, update_stock) + self.make_sl_entry(d, d['warehouse'], - flt(d['qty']) , 0, update_stock) get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values) @@ -434,22 +437,22 @@ class DocType(TransactionBase): # ********************** Make Stock Entry ************************************ def make_sl_entry(self, d, wh, qty, in_value, update_stock): self.values.append({ - 'item_code' : d[1], - 'warehouse' : wh, - 'transaction_date' : getdate(self.doc.modified).strftime('%Y-%m-%d'), + 'item_code' : d['item_code'], + 'warehouse' : wh, + 'transaction_date' : getdate(self.doc.modified).strftime('%Y-%m-%d'), 'posting_date' : self.doc.posting_date, 'posting_time' : self.doc.posting_time, 'voucher_type' : 'Delivery Note', - 'voucher_no' : self.doc.name, - 'voucher_detail_no' : '', - 'actual_qty' : qty, - 'stock_uom' : d[4], - 'incoming_rate' : in_value, - 'company' : self.doc.company, - 'fiscal_year' : self.doc.fiscal_year, + 'voucher_no' : self.doc.name, + 'voucher_detail_no' : '', + 'actual_qty' : qty, + 'stock_uom' : d['uom'], + 'incoming_rate' : in_value, + 'company' : self.doc.company, + 'fiscal_year' : self.doc.fiscal_year, 'is_cancelled' : (update_stock==1) and 'No' or 'Yes', - 'batch_no' : d[5], - 'serial_no' : d[6] + 'batch_no' : d['batch_no'], + 'serial_no' : d['serial_no'] }) From 74962a92131ccbe2f6298be4c732f8b2210ca7a6 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 26 Jun 2012 12:47:14 +0530 Subject: [PATCH 2/6] auto create email digest after setup is completed --- .../doctype/setup_control/setup_control.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/erpnext/setup/doctype/setup_control/setup_control.py b/erpnext/setup/doctype/setup_control/setup_control.py index bcdd0938da..444b796f3c 100644 --- a/erpnext/setup/doctype/setup_control/setup_control.py +++ b/erpnext/setup/doctype/setup_control/setup_control.py @@ -89,6 +89,8 @@ class DocType: self.set_cp_defaults(**cp_args) self.create_feed_and_todo() + + self.create_email_digest() webnotes.clear_cache() msgprint("Company setup is complete") @@ -127,6 +129,44 @@ class DocType: d.reference_type = 'Supplier' d.save(1) + def create_email_digest(self): + """ + create a default weekly email digest + * Weekly Digest + * For all companies + * Recipients: System Managers + * Full content + * Enabled by default + """ + import webnotes + companies_list = webnotes.conn.sql("SELECT company_name FROM `tabCompany`", as_list=1) + + import webnotes.utils + system_managers = webnotes.utils.get_system_managers_list() + if not system_managers: return + + from webnotes.model.doc import Document + for company in companies_list: + if company and company[0]: + edigest = Document('Email Digest') + edigest.name = "Default Weekly Digest - " + company[0] + edigest.company = company[0] + edigest.frequency = 'Weekly' + edigest.recipient_list = "\n".join(system_managers) + for f in ['new_leads', 'new_enquiries', 'new_quotations', + 'new_sales_orders', 'new_purchase_orders', + 'new_transactions', 'payables', 'payments', + 'expenses_booked', 'invoiced_amount', 'collections', + 'income', 'bank_balance', 'stock_below_rl', + 'income_year_to_date', 'enabled']: + edigest.fields[f] = 1 + exists = webnotes.conn.sql("""\ + SELECT name FROM `tabEmail Digest` + WHERE name = %s""", edigest.name) + if (exists and exists[0]) and exists[0][0]: + continue + else: + edigest.save(1) # Get Fiscal year Details # ------------------------ From b8108c68e958f42b6214cafa595db5f11b09f1f0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 27 Jun 2012 11:16:28 +0530 Subject: [PATCH 3/6] Issue fixed in stock reconciliation --- .../doctype/purchase_receipt/listview.js | 2 +- .../stock_reconciliation.py | 34 +++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/listview.js b/erpnext/stock/doctype/purchase_receipt/listview.js index 870485953e..c1b8b42f75 100644 --- a/erpnext/stock/doctype/purchase_receipt/listview.js +++ b/erpnext/stock/doctype/purchase_receipt/listview.js @@ -13,7 +13,7 @@ wn.doclistviews['Purchase Receipt'] = wn.views.ListView.extend({ {width: '3%', content:'docstatus'}, {width: '15%', content:'name'}, {width: '47%', content:'supplier_name+tags', css: {color:'#222'}}, - {width: '15%', content:'purchase_order_no', type:'link', doctype:'Purchase Order Order'}, + {width: '15%', content:'purchase_order_no', type:'link', doctype:'Purchase Order'}, {width: '12%', content:'modified', css: {'text-align': 'right', 'color':'#777'}} ] }); diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 1f3df46678..384363e0fd 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -60,7 +60,12 @@ class DocType: count = 1 for s in data: count += 1 - if count == 2: continue + if count == 2: + if s[0] != 'Item Code' or s[1] != 'Warehouse': + msgprint("First row of the attachment always should be 'Item Code, Warehouse, Quantity \ + and Valuation Rate/Incoming Rate'", raise_exception=1) + else: + continue # validate if (submit and len(s) != 4) or (not submit and len(s) != 6): msgprint("Data entered at Row No " + cstr(count) + " in Attachment File is not in correct format.", raise_exception=1) @@ -172,6 +177,7 @@ class DocType: Make stock entry of qty diff, calculate incoming rate to maintain valuation rate. If no qty diff, but diff in valuation rate, make (+1,-1) entry to update valuation """ + self.diff_info = '' for row in self.data: # Get qty as per system sys_stock = self.get_system_stock(row[0],row[1]) @@ -190,29 +196,28 @@ class DocType: self.make_entry_for_valuation(row, sys_stock, is_submit) if is_submit == 1: - self.store_diff_info(qty_diff, rate_diff) + r = [cstr(i) for i in row] + [cstr(qty_diff), cstr(rate_diff)] + self.store_diff_info(r) msgprint("Stock Reconciliation Completed Successfully...") - def store_diff_info(self, qty_diff, rate_diff): + def store_diff_info(self, r): """Add diffs column in attached file""" # add header - if self.val_method == 'Moving Average': - out = "Item Code, Warehouse, Qty, Valuation Rate, Qty Diff, Rate Diff" - else: - out = "Item Code, Warehouse, Qty, Incoming Rate, Qty Diff, Rate Diff" + if not self.diff_info: + if self.val_method == 'Moving Average': + self.diff_info += "Item Code, Warehouse, Qty, Valuation Rate, Qty Diff, Rate Diff" + else: + self.diff_info += "Item Code, Warehouse, Qty, Incoming Rate, Qty Diff, Rate Diff" # add data - for d in self.data: - s = [cstr(i) for i in d] + [cstr(qty_diff), cstr(rate_diff)] - out += "\n" + ','.join(s) - - webnotes.conn.set(self.doc, 'diff_info', out) + self.diff_info += "\n" + ','.join(r) + + webnotes.conn.set(self.doc, 'diff_info', self.diff_info) - def on_submit(self): if not self.doc.file_list: @@ -221,7 +226,6 @@ class DocType: self.do_stock_reco(is_submit = 1) - def on_cancel(self): self.get_reconciliation_data(submit = 0) - self.do_stock_reco(is_submit = -1) + self.do_stock_reco(is_submit = -1) \ No newline at end of file From 7ce737be3de4f64e8991fbc44b07a350b7b8dd3d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 27 Jun 2012 11:33:05 +0530 Subject: [PATCH 4/6] Issue fixed in stock reconciliation --- .../doctype/stock_reconciliation/stock_reconciliation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 384363e0fd..0cc81ffa79 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -62,8 +62,8 @@ class DocType: count += 1 if count == 2: if s[0] != 'Item Code' or s[1] != 'Warehouse': - msgprint("First row of the attachment always should be 'Item Code, Warehouse, Quantity \ - and Valuation Rate/Incoming Rate'", raise_exception=1) + msgprint("First row of the attachment always should be same as template(Item Code, Warehouse, Quantity \ + and Valuation Rate/Incoming Rate)", raise_exception=1) else: continue # validate @@ -199,7 +199,7 @@ class DocType: r = [cstr(i) for i in row] + [cstr(qty_diff), cstr(rate_diff)] self.store_diff_info(r) - msgprint("Stock Reconciliation Completed Successfully...") + msgprint("Stock Reconciliation Completed Successfully...") def store_diff_info(self, r): From b81aa88091d2938d4b42014300898a95b20b1fc0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 27 Jun 2012 12:00:24 +0530 Subject: [PATCH 5/6] Lease agreement link removed from account home page --- erpnext/accounts/page/accounts_home/accounts_home.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/erpnext/accounts/page/accounts_home/accounts_home.html b/erpnext/accounts/page/accounts_home/accounts_home.html index 4f43f66295..5e1b1c8b45 100644 --- a/erpnext/accounts/page/accounts_home/accounts_home.html +++ b/erpnext/accounts/page/accounts_home/accounts_home.html @@ -48,11 +48,6 @@ title="Export multiple Account Ledgers (GL) to spreadsheet (csv)" href="#!Form/Multi Ledger Report/Multi Ledger Report">Export Multiple Ledgers (GL) -
Date: Wed, 27 Jun 2012 13:21:12 +0530 Subject: [PATCH 6/6] maintenance visit cleanup and integrated with maintenance schedule --- ...Maintenance Schedule-Maintenance Visit.txt | 99 ++++++ .../maintenance_visit/maintenance_visit.js | 58 ++-- .../maintenance_visit/maintenance_visit.py | 253 ++++++++------- .../maintenance_visit/maintenance_visit.txt | 295 ++++++++++-------- 4 files changed, 415 insertions(+), 290 deletions(-) create mode 100644 erpnext/support/DocType Mapper/Maintenance Schedule-Maintenance Visit/Maintenance Schedule-Maintenance Visit.txt diff --git a/erpnext/support/DocType Mapper/Maintenance Schedule-Maintenance Visit/Maintenance Schedule-Maintenance Visit.txt b/erpnext/support/DocType Mapper/Maintenance Schedule-Maintenance Visit/Maintenance Schedule-Maintenance Visit.txt new file mode 100644 index 0000000000..42901486b1 --- /dev/null +++ b/erpnext/support/DocType Mapper/Maintenance Schedule-Maintenance Visit/Maintenance Schedule-Maintenance Visit.txt @@ -0,0 +1,99 @@ +# DocType Mapper, Maintenance Schedule-Maintenance Visit +[ + + # These values are common in all dictionaries + { + 'creation': '2012-06-27 13:18:25', + 'docstatus': 0, + 'modified': '2012-06-27 13:18:25', + 'modified_by': u'Administrator', + 'owner': u'Administrator' + }, + + # These values are common for all Table Mapper Detail + { + 'doctype': u'Table Mapper Detail', + 'name': '__common__', + 'parent': u'Maintenance Schedule-Maintenance Visit', + 'parentfield': u'table_mapper_details', + 'parenttype': u'DocType Mapper', + 'validation_logic': u'docstatus=1' + }, + + # These values are common for all Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'map': u'Yes', + 'name': '__common__', + 'parent': u'Maintenance Schedule-Maintenance Visit', + 'parentfield': u'field_mapper_details', + 'parenttype': u'DocType Mapper' + }, + + # These values are common for all DocType Mapper + { + 'doctype': u'DocType Mapper', + 'from_doctype': u'Maintenance Schedule', + 'module': u'Support', + 'name': '__common__', + 'ref_doc_submitted': 1, + 'to_doctype': u'Maintenance Visit' + }, + + # DocType Mapper, Maintenance Schedule-Maintenance Visit + { + 'doctype': u'DocType Mapper', + 'name': u'Maintenance Schedule-Maintenance Visit' + }, + + # Field Mapper Detail + { + 'checking_operator': u'=', + 'doctype': u'Field Mapper Detail', + 'from_field': u'customer', + 'match_id': 0, + 'to_field': u'customer' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'name', + 'match_id': 0, + 'to_field': u'maintenance_schedule' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'parent', + 'match_id': 1, + 'to_field': u'prevdoc_docname' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'parenttype', + 'match_id': 1, + 'to_field': u'prevdoc_doctype' + }, + + # Table Mapper Detail + { + 'doctype': u'Table Mapper Detail', + 'from_field': u'item_maintenance_detail', + 'from_table': u'Maintenance Schedule Item', + 'match_id': 1, + 'to_field': u'maintenance_visit_details', + 'to_table': u'Maintenance Visit Purpose' + }, + + # Table Mapper Detail + { + 'doctype': u'Table Mapper Detail', + 'from_table': u'Maintenance Schedule', + 'match_id': 0, + 'to_table': u'Maintenance Visit' + } +] \ No newline at end of file diff --git a/erpnext/support/doctype/maintenance_visit/maintenance_visit.js b/erpnext/support/doctype/maintenance_visit/maintenance_visit.js index a2c0772c94..1e5e9c8009 100644 --- a/erpnext/support/doctype/maintenance_visit/maintenance_visit.js +++ b/erpnext/support/doctype/maintenance_visit/maintenance_visit.js @@ -16,16 +16,19 @@ cur_frm.cscript.onload = function(doc, dt, dn) { if(!doc.status) set_multiple(dt,dn,{status:'Draft'}); - if(doc.customer) cur_frm.cscript.customer(doc,cdt,cdn); - - if(doc.__islocal){ - set_multiple(dt,dn,{mntc_date:get_today()}); - hide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']); - } - - //if(doc.maintenance_type) cur_frm.cscript.maintenance_type(doc,cdt,cdn); + if(doc.__islocal) set_multiple(dt,dn,{mntc_date:get_today()}); + hide_contact_info(doc); } +var hide_contact_info = function(doc) { + if(doc.customer) $(cur_frm.fields_dict.contact_info_section.row.wrapper).toggle(true); + else $(cur_frm.fields_dict.contact_info_section.row.wrapper).toggle(false); + +} + +cur_frm.cscript.refresh = function(doc) { + hide_contact_info(doc); +} //customer cur_frm.cscript.customer = function(doc,dt,dn) { @@ -35,7 +38,7 @@ cur_frm.cscript.customer = function(doc,dt,dn) { } if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', '', callback); - if(doc.customer) unhide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']); + hide_contact_info(doc); } cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) { @@ -62,36 +65,12 @@ cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) { cur_frm.cscript.get_items = function(doc, dt, dn) { var callback = function(r,rt) { - unhide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']); + hide_contact_info(doc); cur_frm.refresh(); } get_server_fields('fetch_items','','',doc, dt, dn,1,callback); } - -/* -cur_frm.cscript.maintenance_type = function(doc,cdt,cdn){ - if(doc.maintenance_type == 'Scheduled') { - hide_field('sales_order_no'); - hide_field('customer_issue_no'); - hide_field('Get Items'); - doc.customer_issue_no = ''; - doc.sales_order_no = ''; - } - else if(doc.maintenance_type == 'Unscheduled') { - unhide_field('sales_order_no'); - hide_field('customer_issue_no'); - unhide_field('Get Items'); - doc.customer_issue_no = ''; - } - else if(doc.maintenance_type == 'Breakdown') { - hide_field('sales_order_no'); - unhide_field('customer_issue_no'); - unhide_field('Get Items'); - doc.sales_order_no = ''; - } -}*/ - cur_frm.fields_dict['maintenance_visit_details'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) { return 'SELECT tabItem.name,tabItem.item_name,tabItem.description FROM tabItem WHERE tabItem.is_service_item="Yes" AND tabItem.docstatus != 2 AND tabItem.%(key)s LIKE "%s" LIMIT 50'; } @@ -110,7 +89,6 @@ cur_frm.fields_dict['sales_order_no'].get_query = function(doc) { if(doc.customer) { cond = '`tabSales Order`.customer = "'+doc.customer+'" AND'; } - //return repl('SELECT DISTINCT `tabSales Order`.name FROM `tabSales Order`, `tabSales Order Item` WHERE `tabSales Order`.company = "%(company)s" AND `tabSales Order`.docstatus = 1 AND %(cond)s `tabSales Order`.name LIKE "%s" ORDER BY `tabSales Order`.name DESC LIMIT 50', {company:doc.company, cond:cond}); return repl('SELECT DISTINCT `tabSales Order`.name FROM `tabSales Order`, `tabSales Order Item`, `tabItem` WHERE `tabSales Order`.company = "%(company)s" AND `tabSales Order`.docstatus = 1 AND `tabSales Order Item`.parent = `tabSales Order`.name AND `tabSales Order Item`.item_code = `tabItem`.name AND `tabItem`.is_service_item = "Yes" AND %(cond)s `tabSales Order`.name LIKE "%s" ORDER BY `tabSales Order`.name DESC LIMIT 50', {company:doc.company, cond:cond}); } @@ -123,8 +101,16 @@ cur_frm.fields_dict['customer_issue_no'].get_query = function(doc) { return repl('SELECT `tabCustomer Issue`.name FROM `tabCustomer Issue` WHERE `tabCustomer Issue`.company = "%(company)s" AND %(cond)s `tabCustomer Issue`.docstatus = 1 AND (`tabCustomer Issue`.status = "Open" OR `tabCustomer Issue`.status = "Work In Progress") AND `tabCustomer Issue`.name LIKE "%s" ORDER BY `tabCustomer Issue`.name DESC LIMIT 50', {company:doc.company, cond:cond}); } +cur_frm.fields_dict['maintenance_schedule'].get_query = function(doc) { + doc = locals[this.doctype][this.docname]; + var cond = ''; + if(doc.customer) { + cond = '`tabMaintenance Schedule`.customer = "'+doc.customer+'" AND'; + } + return repl('SELECT `tabMaintenance Schedule`.name FROM `tabMaintenance Schedule` WHERE `tabMaintenance Schedule`.company = "%(company)s" AND %(cond)s `tabMaintenance Schedule`.docstatus = 1 AND `tabMaintenance Schedule`.name LIKE "%s" ORDER BY `tabMaintenance Schedule`.name DESC LIMIT 50', {company:doc.company, cond:cond}); +} + //get query select Territory -//======================================================================================================================= cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) { return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` FROM `tabTerritory` WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50'; } diff --git a/erpnext/support/doctype/maintenance_visit/maintenance_visit.py b/erpnext/support/doctype/maintenance_visit/maintenance_visit.py index 70b39eca95..278e3651b0 100644 --- a/erpnext/support/doctype/maintenance_visit/maintenance_visit.py +++ b/erpnext/support/doctype/maintenance_visit/maintenance_visit.py @@ -8,11 +8,11 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # Please edit this list and import only required elements import webnotes @@ -35,130 +35,129 @@ convert_to_lists = webnotes.conn.convert_to_lists from utilities.transaction_base import TransactionBase class DocType(TransactionBase): - def __init__(self, doc, doclist=[]): - self.doc = doc - self.doclist = doclist - - #get item details - #------------------ - def get_item_details(self, item_code): - item = sql("select item_name,description from `tabItem` where name = '%s'" %(item_code), as_dict=1) - ret = { - 'item_name' : item and item[0]['item_name'] or '', - 'description' : item and item[0]['description'] or '' - } - return ret - - # fetch details of resp Sales order or customer issue - #----------------------------------------------------------- - def fetch_items(self): - if self.doc.sales_order_no and self.doc.customer_issue_no: - msgprint("You can not fetch details of both, Sales Order and Customer Issue, in same Maintenance Visit") - raise Exception - - self.doc.clear_table(self.doclist, 'maintenance_visit_details') - - if self.doc.sales_order_no: - self.doclist = get_obj('DocType Mapper', 'Sales Order-Maintenance Visit').dt_map('Sales Order', 'Maintenance Visit', self.doc.sales_order_no, self.doc, self.doclist, "[['Sales Order', 'Maintenance Visit'],['Sales Order Item', 'Maintenance Visit Purpose']]") - - elif self.doc.customer_issue_no: - self.doclist = get_obj('DocType Mapper', 'Customer Issue-Maintenance Visit').dt_map('Customer Issue', 'Maintenance Visit', self.doc.customer_issue_no, self.doc, self.doclist, "[['Customer Issue', 'Maintenance Visit'],['Customer Issue', 'Maintenance Visit Purpose']]") - - #validate reference value using doctype mapper - #----------------------------------------------------- - def validate_reference_value(self, check_for): - if check_for == 'Sales Order': - get_obj('DocType Mapper', 'Sales Order-Maintenance Visit', with_children = 1).validate_reference_value(self, self.doc.name) - elif check_for == 'Customer Issue': - get_obj('DocType Mapper', 'Customer Issue-Maintenance Visit', with_children = 1).validate_reference_value(self, self.doc.name) - - #check if serial no exist in system - #-------------------------------------- - def validate_serial_no(self): - for d in getlist(self.doclist, 'maintenance_visit_details'): - if d.serial_no and not sql("select name from `tabSerial No` where name = '%s' and docstatus != 2" % d.serial_no): - msgprint("Serial No: "+ d.serial_no + " not exists in the system") - raise Exception - #elif not d.serial_no and d.item_code: - # ser = sql("select has_serial_no from tabItem where name = '%s'" % d.item_code) - # ser = ser and ser[0][0] or 'No' - # if ser == 'Yes': - # msgprint("Serial No is mandatory for item: " + d.item_code) - # raise Exception - - def validate(self): - if not getlist(self.doclist, 'maintenance_visit_details'): - msgprint("Please enter maintenance details") - raise Exception - - for d in getlist(self.doclist, 'maintenance_visit_details'): - if d.prevdoc_doctype == 'Sales Order': - check_for = 'Sales Order' - elif d.prevdoc_doctype == 'Customer Issue': - check_for = 'Customer Issue' - else: - msgprint("Maintenance Visit must be created either against Sales Order or against Customer Issue") - raise Exception - - if check_for: - self.validate_reference_value(check_for) + def __init__(self, doc, doclist=[]): + self.doc = doc + self.doclist = doclist + + #get item details + #------------------ + def get_item_details(self, item_code): + item = sql("select item_name,description from `tabItem` where name = '%s'" %(item_code), as_dict=1) + ret = { + 'item_name' : item and item[0]['item_name'] or '', + 'description' : item and item[0]['description'] or '' + } + return ret + + # fetch details of resp Sales order or customer issue + #----------------------------------------------------------- + def fetch_items(self): + if self.doc.sales_order_no and self.doc.customer_issue_no : + msgprint("You can not fetch details of both, Sales Order and Customer Issue, in same Maintenance Visit") + raise Exception + + self.doc.clear_table(self.doclist, 'maintenance_visit_details') + + if self.doc.sales_order_no: + self.doclist = get_obj('DocType Mapper', 'Sales Order-Maintenance Visit').dt_map('Sales Order', \ + 'Maintenance Visit', self.doc.sales_order_no, self.doc, self.doclist, "[['Sales Order', 'Maintenance Visit'],\ + ['Sales Order Item', 'Maintenance Visit Purpose']]") + elif self.doc.customer_issue_no: + self.doclist = get_obj('DocType Mapper', 'Customer Issue-Maintenance Visit').dt_map('Customer Issue', \ + 'Maintenance Visit', self.doc.customer_issue_no, self.doc, self.doclist, "[['Customer Issue', 'Maintenance Visit'],\ + ['Customer Issue', 'Maintenance Visit Purpose']]") + elif self.doc.maintenance_schedule: + self.doclist = get_obj('DocType Mapper', 'Maintenance Schedule-Maintenance Visit').dt_map('Maintenance Schedule',\ + 'Maintenance Visit', self.doc.maintenance_schedule, self.doc, self.doclist, "[['Maintenance Schedule', \ + 'Maintenance Visit'], ['Maintenance Schedule Item', 'Maintenance Visit Purpose']]") + + #validate reference value using doctype mapper + #----------------------------------------------------- + def validate_reference_value(self, check_for): + if check_for == 'Sales Order': + get_obj('DocType Mapper', 'Sales Order-Maintenance Visit', with_children = 1).validate_reference_value(self, self.doc.name) + elif check_for == 'Customer Issue': + get_obj('DocType Mapper', 'Customer Issue-Maintenance Visit', with_children = 1).validate_reference_value(self, self.doc.name) + + #check if serial no exist in system + #-------------------------------------- + def validate_serial_no(self): + for d in getlist(self.doclist, 'maintenance_visit_details'): + if d.serial_no and not sql("select name from `tabSerial No` where name = '%s' and docstatus != 2" % d.serial_no): + msgprint("Serial No: "+ d.serial_no + " not exists in the system") + raise Exception - self.validate_serial_no() - - def update_customer_issue(self, flag): - for d in getlist(self.doclist, 'maintenance_visit_details'): - if d.prevdoc_docname and d.prevdoc_doctype == 'Customer Issue' : - if flag==1: - mntc_date = self.doc.mntc_date - service_person = d.service_person - work_done = d.work_done - if self.doc.completion_status == 'Fully Completed': - status = 'Closed' - elif self.doc.completion_status == 'Partially Completed': - status = 'Work In Progress' - else: - nm = sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.doc.name)) - - if nm: - status = 'Work In Progress' - mntc_date = nm and nm[0][1] or '' - service_person = nm and nm[0][2] or '' - work_done = nm and nm[0][3] or '' - else: - status = 'Open' - mntc_date = '' - service_person = '' - work_done = '' - - sql("update `tabCustomer Issue` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname)) - - # check if last maintenance visit against same sales order/ customer issue - #----------------------------------------------------------------------------------- - def check_if_last_visit(self): - for d in getlist(self.doclist, 'maintenance_visit_details'): - if d.prevdoc_docname: - check_for_docname = d.prevdoc_docname - check_for_doctype = d.prevdoc_doctype - - if check_for_docname: - check = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.name!=%s and t2.prevdoc_docname=%s and t1.docstatus = 1 and (t1.mntc_date > %s or (t1.mntc_date = %s and t1.mntc_time > %s))", (self.doc.name, check_for_docname, self.doc.mntc_date, self.doc.mntc_date, self.doc.mntc_time)) - - if check: - check_lst = [x[0] for x in check] - check_lst =','.join(check_lst) - msgprint("To cancel this, you need to cancel Maintenance Visit(s) "+cstr(check_lst)+" created after this maintenance visit against same "+check_for_doctype) - raise Exception - else: - self.update_customer_issue(0) - - def on_submit(self): - self.update_customer_issue(1) - set(self.doc, 'status', 'Submitted') - - def on_cancel(self): - self.check_if_last_visit() - set(self.doc, 'status', 'Cancelled') + + def validate(self): + if not getlist(self.doclist, 'maintenance_visit_details'): + msgprint("Please enter maintenance details") + raise Exception + + check_for = '' + for d in getlist(self.doclist, 'maintenance_visit_details'): + if d.prevdoc_doctype == 'Sales Order': + check_for = 'Sales Order' + elif d.prevdoc_doctype == 'Customer Issue': + check_for = 'Customer Issue' + + if check_for: + self.validate_reference_value(check_for) - def on_update(self): - pass - + self.validate_serial_no() + + def update_customer_issue(self, flag): + for d in getlist(self.doclist, 'maintenance_visit_details'): + if d.prevdoc_docname and d.prevdoc_doctype == 'Customer Issue' : + if flag==1: + mntc_date = self.doc.mntc_date + service_person = d.service_person + work_done = d.work_done + if self.doc.completion_status == 'Fully Completed': + status = 'Closed' + elif self.doc.completion_status == 'Partially Completed': + status = 'Work In Progress' + else: + nm = sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.doc.name)) + + if nm: + status = 'Work In Progress' + mntc_date = nm and nm[0][1] or '' + service_person = nm and nm[0][2] or '' + work_done = nm and nm[0][3] or '' + else: + status = 'Open' + mntc_date = '' + service_person = '' + work_done = '' + + sql("update `tabCustomer Issue` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname)) + + + def check_if_last_visit(self): + """check if last maintenance visit against same sales order/ customer issue""" + for d in getlist(self.doclist, 'maintenance_visit_details'): + if d.prevdoc_docname: + check_for_docname = d.prevdoc_docname + check_for_doctype = d.prevdoc_doctype + + if check_for_docname: + check = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.name!=%s and t2.prevdoc_docname=%s and t1.docstatus = 1 and (t1.mntc_date > %s or (t1.mntc_date = %s and t1.mntc_time > %s))", (self.doc.name, check_for_docname, self.doc.mntc_date, self.doc.mntc_date, self.doc.mntc_time)) + + if check: + check_lst = [x[0] for x in check] + check_lst =','.join(check_lst) + msgprint("To cancel this, you need to cancel Maintenance Visit(s) "+cstr(check_lst)+" created after this maintenance visit against same "+check_for_doctype) + raise Exception + else: + self.update_customer_issue(0) + + def on_submit(self): + self.update_customer_issue(1) + set(self.doc, 'status', 'Submitted') + + def on_cancel(self): + self.check_if_last_visit() + set(self.doc, 'status', 'Cancelled') + + def on_update(self): + pass \ No newline at end of file diff --git a/erpnext/support/doctype/maintenance_visit/maintenance_visit.txt b/erpnext/support/doctype/maintenance_visit/maintenance_visit.txt index 93ed656465..3b2cec9b50 100644 --- a/erpnext/support/doctype/maintenance_visit/maintenance_visit.txt +++ b/erpnext/support/doctype/maintenance_visit/maintenance_visit.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:36:42', + 'creation': '2012-06-11 12:10:15', 'docstatus': 0, - 'modified': '2012-03-27 14:45:49', + 'modified': '2012-06-27 12:50:00', 'modified_by': u'Administrator', 'owner': u'ashwini@webnotestech.com' }, @@ -26,7 +26,7 @@ 'show_in_menu': 0, 'subject': u'To %(customer_name)s on %(mntc_date)s', 'tag_fields': u'completion_status,maintenance_type', - 'version': 95 + 'version': 1 }, # These values are common for all DocField @@ -144,38 +144,17 @@ 'permlevel': 0, 'print_hide': 1, 'reqd': 1, - 'search_index': 1, + 'search_index': 0, 'trigger': u'Client' }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'customer_address', - 'fieldtype': u'Link', - 'label': u'Customer Address', - 'options': u'Address', - 'permlevel': 0, - 'print_hide': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'contact_person', - 'fieldtype': u'Link', - 'label': u'Contact Person', - 'options': u'Contact', - 'permlevel': 0, - 'print_hide': 1 - }, - # DocField { 'doctype': u'DocField', 'fieldname': u'customer_name', 'fieldtype': u'Data', - 'label': u'Name', + 'hidden': 1, + 'label': u'Customer Name', 'permlevel': 1 }, @@ -184,6 +163,7 @@ 'doctype': u'DocField', 'fieldname': u'address_display', 'fieldtype': u'Small Text', + 'hidden': 1, 'label': u'Address', 'permlevel': 1 }, @@ -193,6 +173,7 @@ 'doctype': u'DocField', 'fieldname': u'contact_display', 'fieldtype': u'Small Text', + 'hidden': 1, 'label': u'Contact', 'permlevel': 1 }, @@ -202,6 +183,7 @@ 'doctype': u'DocField', 'fieldname': u'contact_mobile', 'fieldtype': u'Data', + 'hidden': 1, 'label': u'Mobile No', 'permlevel': 1 }, @@ -211,42 +193,11 @@ 'doctype': u'DocField', 'fieldname': u'contact_email', 'fieldtype': u'Data', + 'hidden': 1, 'label': u'Contact Email', 'permlevel': 1 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'company', - 'fieldtype': u'Select', - 'in_filter': 1, - 'label': u'Company', - 'oldfieldname': u'company', - 'oldfieldtype': u'Select', - 'options': u'link:Company', - 'permlevel': 0, - 'print_hide': 1, - 'reqd': 1, - 'search_index': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'fiscal_year', - 'fieldtype': u'Select', - 'in_filter': 1, - 'label': u'Fiscal Year', - 'oldfieldname': u'fiscal_year', - 'oldfieldtype': u'Select', - 'options': u'link:Fiscal Year', - 'permlevel': 0, - 'print_hide': 1, - 'reqd': 1, - 'search_index': 0 - }, - # DocField { 'doctype': u'DocField', @@ -283,72 +234,6 @@ 'permlevel': 0 }, - # DocField - { - 'colour': u'White:FFF', - 'default': u'Draft', - 'doctype': u'DocField', - 'fieldname': u'status', - 'fieldtype': u'Data', - 'label': u'Status', - 'no_copy': 1, - 'oldfieldname': u'status', - 'oldfieldtype': u'Data', - 'options': u'\nDraft\nCancelled\nSubmitted', - 'permlevel': 1, - 'reqd': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'amended_from', - 'fieldtype': u'Data', - 'label': u'Amended From', - 'no_copy': 1, - 'oldfieldname': u'amended_from', - 'oldfieldtype': u'Data', - 'permlevel': 1, - 'print_hide': 1, - 'width': u'150px' - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'amendment_date', - 'fieldtype': u'Date', - 'label': u'Amendment Date', - 'no_copy': 1, - 'oldfieldname': u'amendment_date', - 'oldfieldtype': u'Date', - 'permlevel': 0, - 'print_hide': 1, - 'width': u'100px' - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'territory', - 'fieldtype': u'Link', - 'label': u'Territory', - 'options': u'Territory', - 'permlevel': 0, - 'print_hide': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'customer_group', - 'fieldtype': u'Link', - 'label': u'Customer Group', - 'options': u'Customer Group', - 'permlevel': 0, - 'print_hide': 1 - }, - # DocField { 'doctype': u'DocField', @@ -432,6 +317,17 @@ 'trigger': u'Client' }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'maintenance_schedule', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'Maintenance Schedule', + 'options': u'Maintenance Schedule', + 'permlevel': 0 + }, + # DocField { 'doctype': u'DocField', @@ -470,9 +366,9 @@ # DocField { 'doctype': u'DocField', - 'fieldname': u'feedback', + 'fieldname': u'more_info', 'fieldtype': u'Section Break', - 'label': u'Feedback', + 'label': u'More Info', 'oldfieldtype': u'Section Break', 'permlevel': 0 }, @@ -486,5 +382,150 @@ 'oldfieldname': u'customer_feedback', 'oldfieldtype': u'Small Text', 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'col_break3', + 'fieldtype': u'Column Break', + 'permlevel': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'default': u'Draft', + 'doctype': u'DocField', + 'fieldname': u'status', + 'fieldtype': u'Data', + 'label': u'Status', + 'no_copy': 1, + 'oldfieldname': u'status', + 'oldfieldtype': u'Data', + 'options': u'\nDraft\nCancelled\nSubmitted', + 'permlevel': 1, + 'reqd': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'amended_from', + 'fieldtype': u'Data', + 'label': u'Amended From', + 'no_copy': 1, + 'oldfieldname': u'amended_from', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1, + 'width': u'150px' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'amendment_date', + 'fieldtype': u'Date', + 'label': u'Amendment Date', + 'no_copy': 1, + 'oldfieldname': u'amendment_date', + 'oldfieldtype': u'Date', + 'permlevel': 0, + 'print_hide': 1, + 'width': u'100px' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'company', + 'fieldtype': u'Select', + 'in_filter': 1, + 'label': u'Company', + 'oldfieldname': u'company', + 'oldfieldtype': u'Select', + 'options': u'link:Company', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'fiscal_year', + 'fieldtype': u'Select', + 'in_filter': 1, + 'label': u'Fiscal Year', + 'oldfieldname': u'fiscal_year', + 'oldfieldtype': u'Select', + 'options': u'link:Fiscal Year', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'contact_info_section', + 'fieldtype': u'Section Break', + 'label': u'Contact Info', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'customer_address', + 'fieldtype': u'Link', + 'label': u'Customer Address', + 'options': u'Address', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'contact_person', + 'fieldtype': u'Link', + 'label': u'Contact Person', + 'options': u'Contact', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'col_break4', + 'fieldtype': u'Column Break', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'territory', + 'fieldtype': u'Link', + 'label': u'Territory', + 'options': u'Territory', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'customer_group', + 'fieldtype': u'Link', + 'label': u'Customer Group', + 'options': u'Customer Group', + 'permlevel': 0, + 'print_hide': 1 } ] \ No newline at end of file