From 68f9ad31ae05ba773b6d6d568eb52afff77a676f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 9 May 2012 15:26:27 +0530 Subject: [PATCH 01/12] serialized inventory fixes : serial no for sales bom child item and rejected qty --- .../doctype/sales_invoice/sales_invoice.js | 1 - .../installation_note/installation_note.py | 2 +- .../doctype/sales_common/sales_common.py | 60 +++++++------ .../doctype/delivery_note/delivery_note.py | 1 - .../delivery_note_packing_item.txt | 84 +++---------------- .../purchase_receipt/purchase_receipt.py | 42 ++++++---- .../purchase_receipt_item.txt | 18 +++- erpnext/stock/doctype/sales_bom/sales_bom.js | 4 +- erpnext/stock/doctype/sales_bom/sales_bom.py | 22 ++--- .../doctype/stock_ledger/stock_ledger.py | 45 ++++++---- 10 files changed, 129 insertions(+), 150 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 8272fb2513..abea87ca97 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -119,7 +119,6 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { // Show / Hide button cur_frm.clear_custom_buttons(); - if (!cur_frm.cscript.is_onload) cur_frm.cscript.hide_price_list_currency(doc, dt, dn); if(doc.docstatus==1) { diff --git a/erpnext/selling/doctype/installation_note/installation_note.py b/erpnext/selling/doctype/installation_note/installation_note.py index 846d143646..0dedf549cc 100644 --- a/erpnext/selling/doctype/installation_note/installation_note.py +++ b/erpnext/selling/doctype/installation_note/installation_note.py @@ -138,7 +138,7 @@ class DocType(TransactionBase): if d.serial_no: - sr_list = get_sr_no_list(d.serial_no, d.qty) + sr_list = get_sr_no_list(d.serial_no, d.qty, d.item_code) self.is_serial_no_exist(d.item_code, sr_list) prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname, d.prevdoc_docname) diff --git a/erpnext/selling/doctype/sales_common/sales_common.py b/erpnext/selling/doctype/sales_common/sales_common.py index f9f8adbaba..1a60a06fd2 100644 --- a/erpnext/selling/doctype/sales_common/sales_common.py +++ b/erpnext/selling/doctype/sales_common/sales_common.py @@ -311,16 +311,6 @@ class DocType(TransactionBase): } return ret - - # Make Packing List from Sales BOM - # ======================================================================= - def has_sales_bom(self, item_code): - return webnotes.conn.sql("select name from `tabSales BOM` where name=%s and docstatus != 2", item_code) - - def get_sales_bom_items(self, item_code): - return webnotes.conn.sql("select item_code, qty, uom from `tabSales BOM Item` where parent=%s", item_code) - - # -------------- # get item list # -------------- @@ -345,8 +335,9 @@ class DocType(TransactionBase): warehouse = (obj.fname == "sales_order_details") and d.reserved_warehouse or d.warehouse if self.has_sales_bom(d.item_code): - for i in self.get_sales_bom_items(d.item_code): - il.append([warehouse, i[0], flt(flt(i[1])* qty), flt(flt(i[1])*reserved_qty), i[2], d.batch_no, d.serial_no]) + for p in getlist(obj.doclist, 'packing_details'): + if p.parent_item == d.item_code: + il.append([warehouse, p.item_code, flt(p.qty)*qty, flt(p.qty)* reserved_qty, p.uom, p.batch_no, p.serial_no]) else: il.append([warehouse, d.item_code, qty, reserved_qty, d.stock_uom, d.batch_no, d.serial_no]) return il @@ -371,12 +362,16 @@ class DocType(TransactionBase): return qty, max_qty, amt, max_amt + # Make Packing List from Sales BOM + # ======================================================================= + def has_sales_bom(self, item_code): + return webnotes.conn.sql("select name from `tabSales BOM` where new_item_code=%s and docstatus != 2", item_code) + + def get_sales_bom_items(self, item_code): + return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom + from `tabSales BOM Item` t1, `tabSales BOM` t2 + where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1) - - - # ----------------------- - # add packing list items - # ----------------------- def get_packing_item_details(self, item): return webnotes.conn.sql("select item_name, description, stock_uom from `tabItem` where name = %s", item, as_dict = 1)[0] @@ -384,12 +379,22 @@ class DocType(TransactionBase): det = webnotes.conn.sql("select actual_qty, projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (item, warehouse), as_dict = 1) return det and det[0] or '' - def add_packing_list_item(self,obj, item_code, qty, warehouse, line): - bin = self.get_bin_qty(item_code, warehouse) - item = self.get_packing_item_details(item_code) - pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item', 1, obj.doclist) - pi.parent_item = item_code - pi.item_code = item_code + def update_packing_list_item(self,obj, packing_item_code, qty, warehouse, line): + bin = self.get_bin_qty(packing_item_code, warehouse) + item = self.get_packing_item_details(packing_item_code) + + # check if exists + exists = 0 + for d in getlist(obj.doclist, 'packing_details'): + if d.parent_item == line.item_code and d.item_code == packing_item_code: + pi, exists = d, 1 + break + + if not exists: + pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item', 1, obj.doclist) + + pi.parent_item = line.item_code + pi.item_code = packing_item_code pi.item_name = item['item_name'] pi.parent_detail_docname = line.name pi.description = item['description'] @@ -399,7 +404,9 @@ class DocType(TransactionBase): pi.projected_qty = bin and flt(bin['projected_qty']) or 0 pi.warehouse = warehouse pi.prevdoc_doctype = line.prevdoc_doctype - pi.serial_no = cstr(line.serial_no) + if packing_item_code == line.item_code: + pi.serial_no = cstr(line.serial_no) + pi.batch_no = cstr(line.batch_no) pi.idx = self.packing_list_idx self.packing_list_idx += 1 @@ -408,15 +415,14 @@ class DocType(TransactionBase): # make packing list from sales bom if exists or directly copy item with balance # ------------------ def make_packing_list(self, obj, fname): - obj.doc.clear_table(obj.doclist, 'packing_details') self.packing_list_idx = 0 for d in getlist(obj.doclist, fname): warehouse = fname == "sales_order_details" and d.reserved_warehouse or d.warehouse if self.has_sales_bom(d.item_code): for i in self.get_sales_bom_items(d.item_code): - self.add_packing_list_item(obj, i[0], flt(i[1])*flt(d.qty), warehouse, d) + self.update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), warehouse, d) else: - self.add_packing_list_item(obj, d.item_code, d.qty, warehouse, d) + self.update_packing_list_item(obj, d.item_code, d.qty, warehouse, d) # Get total in words diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 445e93b883..e2d2ca3f53 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -416,7 +416,6 @@ class DocType(TransactionBase): if not d[0]: msgprint("Message: Please enter Warehouse for item %s as it is stock item."% d[1]) raise Exception - # if prevdoc_doctype = "Sales Order" 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')) diff --git a/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt b/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt index 4299fcc0f7..51001fc9a0 100644 --- a/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt +++ b/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:36:30', + 'creation': '2012-04-13 11:56:35', 'docstatus': 0, - 'modified': '2012-03-27 14:36:30', + 'modified': '2012-05-09 12:55:23', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -20,7 +20,7 @@ 'section_style': u'Tray', 'server_code_error': u' ', 'show_in_menu': 0, - 'version': 17 + 'version': 1 }, # These values are common for all DocField @@ -134,6 +134,15 @@ 'permlevel': 0 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'batch_no', + 'fieldtype': u'Data', + 'label': u'Batch No', + 'permlevel': 0 + }, + # DocField { 'doctype': u'DocField', @@ -171,34 +180,6 @@ 'search_index': 0 }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'planned_qty', - 'fieldtype': u'Currency', - 'hidden': 1, - 'label': u'Planned Qty ', - 'no_copy': 1, - 'oldfieldname': u'planned_qty', - 'oldfieldtype': u'Currency', - 'permlevel': 1, - 'print_hide': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'produced_qty', - 'fieldtype': u'Currency', - 'hidden': 1, - 'label': u'Produced Qty', - 'no_copy': 1, - 'oldfieldname': u'produced_qty', - 'oldfieldtype': u'Currency', - 'permlevel': 1, - 'print_hide': 1 - }, - # DocField { 'colour': u'White:FFF', @@ -213,47 +194,6 @@ 'print_hide': 1 }, - # DocField - { - 'description': u'The date at which current entry is made in system.', - 'doctype': u'DocField', - 'fieldname': u'transaction_date', - 'fieldtype': u'Date', - 'hidden': 0, - 'label': u'Sales Order Date', - 'oldfieldname': u'transaction_date', - 'oldfieldtype': u'Date', - 'permlevel': 1, - 'print_hide': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'delivery_date', - 'fieldtype': u'Date', - 'hidden': 0, - 'label': u'Expected Delivery Date', - 'oldfieldname': u'delivery_date', - 'oldfieldtype': u'Date', - 'permlevel': 1, - 'print_hide': 1 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'confirmation_date', - 'fieldtype': u'Date', - 'hidden': 1, - 'label': u'Confirmed delivery date', - 'no_copy': 1, - 'oldfieldname': u'confirmation_date', - 'oldfieldtype': u'Date', - 'permlevel': 1, - 'print_hide': 1 - }, - # DocField { 'allow_on_submit': 1, diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 798a2c56de..37bc8a56e3 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -114,7 +114,7 @@ class DocType(TransactionBase): # If Reject Qty than Rejected warehouse is mandatory if flt(d.rejected_qty) and (not self.doc.rejected_warehouse): - msgprint("Rejected Warehouse is necessary if there are rejections. See 'Receipt Items'") + msgprint("Rejected Warehouse is necessary if there are rejections.") raise Exception # Check Received Qty = Accepted Qty + Rejected Qty @@ -198,6 +198,15 @@ class DocType(TransactionBase): self.update_rw_material_detail() get_obj('Stock Ledger').scrub_serial_nos(self) + self.scrub_rejected_serial_nos() + + + def scrub_rejected_serial_nos(self): + for d in getlist(self.doclist, 'purchase_receipt_details'): + if d.rejected_serial_no: + d.rejected_serial_no = d.rejected_serial_no.replace(',', '\n') + d.save() + # On Submit @@ -232,7 +241,7 @@ class DocType(TransactionBase): self.make_sl_entry(d, d.warehouse, flt(pr_qty), d.valuation_rate, is_submit) # UPDATE actual to rejected warehouse by rejected qty if flt(d.rejected_qty) > 0: - self.make_sl_entry(d, self.doc.rejected_warehouse, flt(d.rejected_qty) * flt(d.conversion_factor), d.valuation_rate, is_submit) + self.make_sl_entry(d, self.doc.rejected_warehouse, flt(d.rejected_qty) * flt(d.conversion_factor), d.valuation_rate, is_submit, rejected = 1) self.bk_flush_supp_wh(is_submit) @@ -241,24 +250,29 @@ class DocType(TransactionBase): # make Stock Entry - def make_sl_entry(self, d, wh, qty, in_value, is_submit): + def make_sl_entry(self, d, wh, qty, in_value, is_submit, rejected = 0): + if rejected: + serial_no = d.rejected_serial_no + else: + serial_no = d.serial_no + self.values.append({ - 'item_code' : d.fields.has_key('item_code') and d.item_code or d.rm_item_code, - 'warehouse' : wh, + 'item_code' : d.fields.has_key('item_code') and d.item_code or d.rm_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' : 'Purchase Receipt', - 'voucher_no' : self.doc.name, - 'voucher_detail_no' : d.name, - 'actual_qty' : qty, - 'stock_uom' : d.stock_uom, - 'incoming_rate' : in_value, - 'company' : self.doc.company, - 'fiscal_year' : self.doc.fiscal_year, + 'voucher_no' : self.doc.name, + 'voucher_detail_no' : d.name, + 'actual_qty' : qty, + 'stock_uom' : d.stock_uom, + 'incoming_rate' : in_value, + 'company' : self.doc.company, + 'fiscal_year' : self.doc.fiscal_year, 'is_cancelled' : (is_submit==1) and 'No' or 'Yes', - 'batch_no' : d.batch_no, - 'serial_no' : d.serial_no + 'batch_no' : d.batch_no, + 'serial_no' : serial_no }) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt index 1a2c383fd9..b316bd870a 100755 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:36:35', + 'creation': '2012-04-13 11:56:36', 'docstatus': 0, - 'modified': '2012-03-27 14:36:35', + 'modified': '2012-05-09 14:25:12', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -22,7 +22,7 @@ 'section_style': u'Tray', 'server_code_error': u' ', 'show_in_menu': 0, - 'version': 78 + 'version': 1 }, # These values are common for all DocField @@ -299,6 +299,16 @@ 'report_hide': 0 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'rejected_serial_no', + 'fieldtype': u'Text', + 'label': u'Rejected Serial No', + 'permlevel': 0, + 'print_hide': 1 + }, + # DocField { 'colour': u'White:FFF', @@ -579,4 +589,4 @@ 'permlevel': 0, 'print_hide': 1 } -] +] \ No newline at end of file diff --git a/erpnext/stock/doctype/sales_bom/sales_bom.js b/erpnext/stock/doctype/sales_bom/sales_bom.js index 7d857a2063..275af6a85a 100644 --- a/erpnext/stock/doctype/sales_bom/sales_bom.js +++ b/erpnext/stock/doctype/sales_bom/sales_bom.js @@ -23,7 +23,7 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { cur_frm.cscript.refresh = function(doc, cdt, cdn) { if(!doc.__islocal) { - hide_field('new_item_code'); + get_field(doc.doctype, 'new_item_code', doc.name).permlevel = 1; } } @@ -45,4 +45,4 @@ cur_frm.cscript.currency = function(doc, cdt, cdn) { cur_frm.cscript.find_sales_bom = function(doc, dt, dn) { $c_obj(make_doclist(dt,dn), 'check_duplicate', 1, ''); -} \ No newline at end of file +} diff --git a/erpnext/stock/doctype/sales_bom/sales_bom.py b/erpnext/stock/doctype/sales_bom/sales_bom.py index 7dea6922e1..437c91e7e3 100644 --- a/erpnext/stock/doctype/sales_bom/sales_bom.py +++ b/erpnext/stock/doctype/sales_bom/sales_bom.py @@ -62,13 +62,9 @@ class DocType: if d.is_main_item == 'Yes': is_main_item.append(d.item_code) # Check that Sales Bom Item cannot be child of Sales Bom. - if sql("select name from `tabSales BOM` where name = '%s' " % d.item_code): - msgprint("Sales Bom Item " + d.item_code +" cannot be child item.") + if d.item_code == self.doc.new_item_code: + msgprint("Sales Bom Item " + d.new_item_code +" cannot be child item.") raise Exception - # Check if is_main_item is modified once saved - #if not self.doc.fields.get('__islocal') and d.is_main_item == "Yes" and cstr(d.item_code) != cstr(self.doc.new_item_code)[:-3] : - # msgprint("Modifying the main item is not allowed.") - # raise Exception if len(is_main_item) > 1: msgprint('Main item cannot be more than one.') raise Exception , " Validation Error." @@ -81,8 +77,7 @@ class DocType: # Make Item # --------- def create_new_item(self): - i = Document("Item") - + i = Document("Item") i.item_code = self.doc.new_item_code i.item_name = self.doc.new_item_name i.name = i.item_code @@ -106,7 +101,7 @@ class DocType: sql("delete from `tabItem Price` where parent=%s and price_list_name = %s", (i.name, self.doc.price_list)) pld = addchild(i,"ref_rate_details", "Item Price") - pld.price_list_name = self.doc.price_List + pld.price_list_name = self.doc.price_list pld.ref_rate = flt(ref_rate) pld.ref_currency = self.doc.currency pld.save() @@ -121,14 +116,11 @@ class DocType: i.stock_uom = self.doc.stock_uom i.item_group = self.doc.item_group - # update rates - new_rates = {} - self.update_ref_rate(i) i.item_name = self.doc.new_item_name i.description = self.doc.description - # set default as 'No' or 0 in Item Master as per TIC/3456 + # set default as 'No' or 0 i.is_sample_item = 'No' i.is_asset_item = 'No' i.is_purchase_item = 'No' @@ -138,8 +130,10 @@ class DocType: i.inspection_required = 'No' i.has_serial_no = 'No' i.lead_time_days = flt(0) + # update rates + self.update_ref_rate(i) i.save() - msgprint("Items updated successfully.") + msgprint("Items: %s updated successfully. To update more details open and edit item master" % self.doc.new_item_code) def validate(self): diff --git a/erpnext/stock/doctype/stock_ledger/stock_ledger.py b/erpnext/stock/doctype/stock_ledger/stock_ledger.py index 1d3aabe57f..9ee1f62754 100644 --- a/erpnext/stock/doctype/stock_ledger/stock_ledger.py +++ b/erpnext/stock/doctype/stock_ledger/stock_ledger.py @@ -32,7 +32,7 @@ convert_to_lists = webnotes.conn.convert_to_lists # ----------------------------------------------------------------------------------------- -def get_sr_no_list(sr_nos, qty = 0): +def get_sr_no_list(sr_nos, qty = 0, item_code = ''): serial_nos = cstr(sr_nos).strip().replace(',', '\n').split('\n') valid_serial_nos = [] for val in serial_nos: @@ -41,9 +41,8 @@ def get_sr_no_list(sr_nos, qty = 0): msgprint("You have entered duplicate serial no: %s" % val, raise_exception=1) else: valid_serial_nos.append(val.strip()) - - if qty > 0 and cstr(sr_nos).strip() and len(valid_serial_nos) != flt(qty): - msgprint("Please enter serial nos for all "+ cstr(qty) + " quantity", raise_exception = 1) + if qty and cstr(sr_nos).strip() and len(valid_serial_nos) != abs(qty): + msgprint("Please enter serial nos for "+ cstr(abs(qty)) + " quantity against item code: " + item_code , raise_exception = 1) return valid_serial_nos class DocType: @@ -92,36 +91,46 @@ class DocType: if is_stock_item != 'Yes': msgprint("Serial No is not required for non-stock item: %s" % d.item_code, raise_exception=1) elif ar_required != 'Yes': - msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :" + d.item_code + ', otherwise please remove serial no', raise_exception=1) + msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :" + d.item_code + \ + ', otherwise please remove serial no', raise_exception=1) elif ar_required == 'Yes' and not d.serial_no: msgprint("Serial no is mandatory for item: "+ d.item_code, raise_exception = 1) + # validate rejected serial nos + if fname == 'purchase_receipt_details' and d.rejected_qty and ar_required == 'Yes' and not d.rejected_serial_no: + msgprint("Rejected serial no is mandatory for rejected qty of item: "+ d.item_code, raise_exception = 1) + + + # ------------------- # get serial no list # ------------------- - def get_sr_no_list(self, sr_nos, qty = 0): - return get_sr_no_list(sr_nos, qty) + def get_sr_no_list(self, sr_nos, qty = 0, item_code = ''): + return get_sr_no_list(sr_nos, qty, item_code) # --------------------- # set serial no values # --------------------- def set_pur_serial_no_values(self, obj, serial_no, d, s, new_rec): - item_details = sql("select item_group, warranty_period from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now()) " %(d.item_code), as_dict=1) + item_details = sql("select item_group, warranty_period from `tabItem` where name = '%s' and \ + (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now()) " %(d.item_code), as_dict=1) + s.purchase_document_type = obj.doc.doctype s.purchase_document_no = obj.doc.name s.purchase_date = obj.doc.posting_date s.purchase_time = obj.doc.posting_time s.purchase_rate = d.valuation_rate or d.incoming_rate s.item_code = d.item_code + s.item_name = d.item_name s.brand = d.brand s.description = d.description s.item_group = item_details and item_details[0]['item_group'] or '' s.warranty_period = item_details and item_details[0]['warranty_period'] or 0 s.supplier = obj.doc.supplier s.supplier_name = obj.doc.supplier_name - s.supplier_address = obj.doc.supplier_address + s.address_display = obj.doc.address_display or obj.doc.supplier_address s.warehouse = d.warehouse or d.t_warehouse s.docstatus = 0 s.status = 'In Store' @@ -184,7 +193,7 @@ class DocType: s.delivery_time = obj.doc.posting_time s.customer = obj.doc.customer s.customer_name = obj.doc.customer_name - s.delivery_address = obj.doc.delivery_address + s.delivery_address = obj.doc.address_display s.territory = obj.doc.territory s.warranty_expiry_date = s.warranty_period and add_days(cstr(obj.doc.posting_date), s.warranty_period) or '' s.docstatus = 1 @@ -220,6 +229,13 @@ class DocType: else: self.update_serial_delivery_details(obj, d, serial_no, is_submit) + if fname == 'purchase_receipt_details' and d.rejected_qty and d.rejected_serial_no: + serial_nos = self.get_sr_no_list(d.rejected_serial_no) + for a in serial_nos: + self.update_serial_purchase_details(obj, d, a, is_submit) + + + # ------------- # update stock @@ -227,21 +243,22 @@ class DocType: def update_stock(self, values, is_amended = 'No'): for v in values: sle_id, serial_nos = '', '' - # get serial nos if v["serial_no"]: - serial_nos = self.get_sr_no_list(v["serial_no"], v['actual_qty']) + serial_nos = self.get_sr_no_list(v["serial_no"], v['actual_qty'], v['item_code']) # reverse quantities for cancel if v['is_cancelled'] == 'Yes': v['actual_qty'] = -flt(v['actual_qty']) # cancel matching entry - sql("update `tabStock Ledger Entry` set is_cancelled='Yes' where voucher_no=%s and voucher_type=%s", (v['voucher_no'], v['voucher_type'])) + sql("update `tabStock Ledger Entry` set is_cancelled='Yes' where voucher_no=%s \ + and voucher_type=%s", (v['voucher_no'], v['voucher_type'])) if v["actual_qty"]: sle_id = self.make_entry(v) - get_obj('Warehouse', v["warehouse"]).update_bin(flt(v["actual_qty"]), 0, 0, 0, 0, v["item_code"], v["posting_date"], sle_id, v["posting_time"], '', v["is_cancelled"],v["voucher_type"],v["voucher_no"], is_amended) + get_obj('Warehouse', v["warehouse"]).update_bin(flt(v["actual_qty"]), 0, 0, 0, 0, v["item_code"], \ + v["posting_date"], sle_id, v["posting_time"], '', v["is_cancelled"],v["voucher_type"],v["voucher_no"], is_amended) # ----------- From 08f4cb7f6a53ceaf5cae67e0243fd899f1a2011d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 10 May 2012 12:13:47 +0530 Subject: [PATCH 02/12] stock reco fix in valuation and cancellation --- erpnext/patches/patch_list.py | 5 + .../selling/doctype/sms_center/sms_center.py | 1 - erpnext/stock/doctype/bin/bin.py | 3 +- .../stock_reconciliation.py | 93 ++++++++++++------- .../stock_reconciliation.txt | 17 +++- 5 files changed, 79 insertions(+), 40 deletions(-) diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py index 01f4a0efdd..ea8e5d6588 100644 --- a/erpnext/patches/patch_list.py +++ b/erpnext/patches/patch_list.py @@ -332,5 +332,10 @@ patch_list = [ 'patch_file': 'renamedt_in_custom_search_criteria', 'description': 'raname dt in custom search criteria' }, + { + 'patch_module': 'patches.may_2012', + 'patch_file': 'stock_reco_patch', + 'description': 'stock reco patch: store diff info in field' + }, ] diff --git a/erpnext/selling/doctype/sms_center/sms_center.py b/erpnext/selling/doctype/sms_center/sms_center.py index 0e54dd6dd1..0d54f72bd7 100644 --- a/erpnext/selling/doctype/sms_center/sms_center.py +++ b/erpnext/selling/doctype/sms_center/sms_center.py @@ -46,7 +46,6 @@ class DocType: where_clause = self.doc.supplier and " and ifnull(is_supplier, 0) = 1 and supplier = '%s'" % self.doc.supplier or " and ifnull(is_supplier, 0) = 1" if self.doc.send_to == 'All Sales Partner Contact': where_clause = self.doc.sales_partner and " and ifnull(is_sales_partner, 0) = 1 and sales_aprtner = '%s'" % self.doc.sales_partner or " and ifnull(is_sales_partner, 0) = 1" - msgprint(1) if self.doc.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']: msgprint("select CONCAT(ifnull(first_name,''),'',ifnull(last_name,'')), mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and docstatus != 2 %s" % where_clause) rec = sql("select CONCAT(ifnull(first_name,''),'',ifnull(last_name,'')), mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and docstatus != 2 %s" % where_clause) diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index ce2cae68f3..fe96c9f022 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -181,8 +181,7 @@ class DocType: # get moving average inventory values # ------------------------------------ def get_moving_average_inventory_values(self, val_rate, in_rate, opening_qty, actual_qty, is_cancelled): - #msgprint(actual_qty) - if flt(in_rate) <= 0: # In case of delivery/stock issue in_rate = 0 or wrong incoming rate + if flt(in_rate) == 0: # In case of delivery/stock issue in_rate = 0 or wrong incoming rate in_rate = val_rate # val_rate is same as previous entry if : diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index f3742b3b2d..1f3df46678 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -16,7 +16,7 @@ import webnotes from webnotes.utils import cstr, flt, get_defaults, nowdate -from webnotes import msgprint +from webnotes import msgprint, errprint from webnotes.model.code import get_obj sql = webnotes.conn.sql @@ -28,22 +28,30 @@ class DocType: self.doclist = doclist self.validated = 1 self.data = [] + self.val_method = get_defaults()['valuation_method'] def get_template(self): - return [['Item Code', 'Warehouse', 'Quantity', 'Valuation Rate']] + if self.val_method == 'Moving Average': + return [['Item Code', 'Warehouse', 'Quantity', 'Valuation Rate']] + else: + return [['Item Code', 'Warehouse', 'Quantity', 'Incoming Rate']] - def get_csv_file_data(self): + + def get_csv_file_data(self, submit = 1): """Get csv data""" - filename = self.doc.file_list.split(',') - if not filename: - msgprint("Please Attach File. ", raise_exception=1) + if submit: + filename = self.doc.file_list.split(',') + if not filename: + msgprint("Please Attach File. ", raise_exception=1) - from webnotes.utils import file_manager - fn, content = file_manager.get_file(filename[1]) + from webnotes.utils import file_manager + fn, content = file_manager.get_file(filename[1]) - # NOTE: Don't know why this condition exists - if not isinstance(content, basestring) and hasattr(content, 'tostring'): - content = content.tostring() + # NOTE: Don't know why this condition exists + if not isinstance(content, basestring) and hasattr(content, 'tostring'): + content = content.tostring() + else: + content = self.doc.diff_info return content @@ -69,7 +77,7 @@ class DocType: def get_reconciliation_data(self,submit = 1): """Read and validate csv data""" import csv - data = csv.reader(self.get_csv_file_data().splitlines()) + data = csv.reader(self.get_csv_file_data(submit).splitlines()) self.convert_into_list(data, submit) @@ -96,7 +104,6 @@ class DocType: def validate(self): """Validate attachment data""" - #self.data = [['it', 'wh1', 20, 150]] if self.doc.file_list: self.get_reconciliation_data() @@ -105,17 +112,32 @@ class DocType: def get_system_stock(self, it, wh): """get actual qty on reconciliation date and time as per system""" bin = sql("select name from tabBin where item_code=%s and warehouse=%s", (it, wh)) - prev_sle = bin and get_obj('Bin', bin[0][0]).get_sle_prev_timebucket(self.doc.reconciliation_date, self.doc.reconciliation_time) or {} + prev_sle = bin and get_obj('Bin', bin[0][0]).get_prev_sle(self.doc.reconciliation_date, self.doc.reconciliation_time) or {} return { 'actual_qty': prev_sle.get('bin_aqat', 0), 'stock_uom' : sql("select stock_uom from tabItem where name = %s", it)[0][0], 'val_rate' : prev_sle.get('valuation_rate', 0) } + + def get_incoming_rate(self, row, qty_diff, sys_stock, is_submit): + """Calculate incoming rate to maintain valuation rate""" + if qty_diff and is_submit: + if self.val_method == 'Moving Average': + in_rate = flt(row[3]) + (flt(sys_stock['actual_qty'])*(flt(row[3]) - flt(sys_stock['val_rate'])))/ flt(qty_diff) + elif not sys_stock and not row[3]: + msgprint("Incoming Rate is mandatory for item: %s and warehouse: %s" % (rpw[0], row[1]), raise_exception=1) + else: + in_rate = qty_diff > 0 and row[3] or 0 + else: + in_rate = 0 + + return in_rate + def make_sl_entry(self, is_submit, row, qty_diff, sys_stock): """Make stock ledger entry""" - in_rate = self.get_incoming_rate(row, qty_diff, sys_stock) + in_rate = self.get_incoming_rate(row, qty_diff, sys_stock, is_submit) values = [{ 'item_code' : row[0], 'warehouse' : row[1], @@ -133,14 +155,16 @@ class DocType: 'is_cancelled' : (is_submit==1) and 'No' or 'Yes', 'batch_no' : '', 'serial_no' : '' - }] + }] get_obj('Stock Ledger', 'Stock Ledger').update_stock(values) - - def get_incoming_rate(self, row, qty_diff, sys_stock): - """Calculate incoming rate to maintain valuation rate""" - in_rate = flt(row[3]) + (flt(sys_stock['actual_qty'])*(flt(row[3]) - flt(sys_stock['val_rate'])))/ flt(qty_diff) - return in_rate + + + def make_entry_for_valuation(self, row, sys_stock, is_submit): + self.make_sl_entry(is_submit, row, 1, sys_stock) + sys_stock['val_rate'] = row[3] + sys_stock['actual_qty'] += 1 + self.make_sl_entry(is_submit, row, -1, sys_stock) def do_stock_reco(self, is_submit = 1): @@ -159,33 +183,34 @@ class DocType: # Make sl entry if qty_diff: self.make_sl_entry(is_submit, row, qty_diff, sys_stock) - elif rate_diff: - self.make_sl_entry(is_submit, row, 1, sys_stock) - sys_stock['val_rate'] = row[3] - sys_stock['actual_qty'] += 1 - self.make_sl_entry(is_submit, row, -1, sys_stock) + sys_stock['actual_qty'] += qty_diff + + + if (not qty_diff and rate_diff) or qty_diff < 0 and self.val_method == 'Moving Average': + self.make_entry_for_valuation(row, sys_stock, is_submit) if is_submit == 1: - self.add_data_in_CSV(qty_diff, rate_diff) + self.store_diff_info(qty_diff, rate_diff) msgprint("Stock Reconciliation Completed Successfully...") - def add_data_in_CSV(self, qty_diff, rate_diff): + def store_diff_info(self, qty_diff, rate_diff): """Add diffs column in attached file""" # add header - out = "Item Code, Warehouse, Qty, Valuation Rate, Qty Diff, Val Rate Diff" + 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" + # add data for d in self.data: s = [cstr(i) for i in d] + [cstr(qty_diff), cstr(rate_diff)] out += "\n" + ','.join(s) - - # write to file - fname = self.doc.file_list.split(',') - from webnotes.utils import file_manager - file_manager.write_file(fname[1], out) + + webnotes.conn.set(self.doc, 'diff_info', out) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt index c2fe30a87e..ac23d59c8d 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:36:40', + 'creation': '2012-04-13 11:56:39', 'docstatus': 0, - 'modified': '2012-03-27 14:45:52', + 'modified': '2012-05-10 11:54:52', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -27,7 +27,7 @@ 'server_code_error': u' ', 'show_in_menu': 0, 'subject': u'Date: %(reconciliation_date)s, Time: %(reconciliation_time)s', - 'version': 107 + 'version': 1 }, # These values are common for all DocField @@ -160,6 +160,17 @@ 'print_hide': 1 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'diff_info', + 'fieldtype': u'Text', + 'hidden': 1, + 'label': u'Diff Info', + 'permlevel': 0, + 'print_hide': 1 + }, + # DocField { 'depends_on': u'eval:doc.amended_from', From fdeb55ba69def1564108b659aaef95c7ea243718 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 10 May 2012 12:18:11 +0530 Subject: [PATCH 03/12] stock reco patch --- erpnext/patches/may_2012/stock_reco_patch.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 erpnext/patches/may_2012/stock_reco_patch.py diff --git a/erpnext/patches/may_2012/stock_reco_patch.py b/erpnext/patches/may_2012/stock_reco_patch.py new file mode 100644 index 0000000000..7eb050fd5d --- /dev/null +++ b/erpnext/patches/may_2012/stock_reco_patch.py @@ -0,0 +1,17 @@ +def execute(): + import webnotes + from webnotes.modules import reload_doc + reload_doc('stock', 'doctype', 'stock_reconciliation') + + sr = webnotes.conn.sql("select name, file_list from `tabStock Reconciliation` where docstatus = 1") + for d in sr: + if d[1]: + filename = d[1].split(',')[1] + + from webnotes.utils import file_manager + fn, content = file_manager.get_file(filename) + + if not isinstance(content, basestring) and hasattr(content, 'tostring'): + content = content.tostring() + + webnotes.conn.sql("update `tabStock Reconciliation` set diff_info = %s where name = %s and ifnull(diff_info, '') = ''", (content, d[0])) From 17fb35fa4a2e9c5d3781ec63763561f169369f73 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 10 May 2012 12:39:25 +0530 Subject: [PATCH 04/12] erpnext installer --- install_erpnext.py | 117 ++++++++++++++++++++++++++++++++++++ public/css/wn-web.css | 19 ++---- public/js/wn-web.js | 136 +++++++++++++++++++++++++++--------------- 3 files changed, 210 insertions(+), 62 deletions(-) create mode 100644 install_erpnext.py diff --git a/install_erpnext.py b/install_erpnext.py new file mode 100644 index 0000000000..44485ea18b --- /dev/null +++ b/install_erpnext.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +import os, commands + +# ask for root mysql password +import getpass + +root_pwd = None +while not root_pwd: + root_pwd = getpass.getpass("MySQL Root user's Password: ") + +# test root connection +op = commands.getoutput("mysql -u root -p%s -e 'exit'" % \ + root_pwd.replace('$', '\$').replace(' ', '\ ')) +if "access denied" in op.lower(): + raise Exception("Incorrect MySQL Root user's password") + +# ask for new dbname +new_dbname = None +while not new_dbname: + new_dbname = raw_input("New ERPNext Database Name: ") + +# ask for new dbpassword +new_dbpassword = None +while not new_dbpassword: + new_dbpassword = raw_input("New ERPNext Database's Password: ") + +# get erpnext path +erpnext_path = os.path.dirname(os.path.abspath(__file__)) +os.chdir(erpnext_path) + +# setup backups +if not os.path.exists(os.path.join(erpnext_path, 'backups')): + os.makedirs('backups') + os.symlink(os.path.join(erpnext_path, 'backups'), + os.path.join(erpnext_path, 'public', 'backups')) + +# setup files +if not os.path.exists(os.path.join(erpnext_path, 'files')): + os.makedirs('files') + os.symlink(os.path.join(erpnext_path, 'files'), + os.path.join(erpnext_path, 'public', 'files')) + +# setup logs +if not os.path.exists(os.path.join(erpnext_path, 'logs')): + os.makedirs('logs') + os.system('touch logs/error_log.txt') + +# setup lib -- framework repo with read only access +# change this if you have your own fork +if not os.path.exists(os.path.join(erpnext_path, 'lib')): + os.system('git clone git://github.com/webnotes/wnframework.git') + +# setup symlinks in public +if not os.path.exists(os.path.join(erpnext_path, 'public', 'js', 'lib')): + os.symlink(os.path.join(erpnext_path, 'lib', 'js', 'lib'), + os.path.join(erpnext_path, 'public', 'js', 'lib')) +if not os.path.exists(os.path.join(erpnext_path, 'public', 'images', 'lib')): + os.symlink(os.path.join(eprnext_path, 'lib', 'images'), + os.path.join(erpnext_path, 'public', 'images', 'lib')) + +# extract master +if os.path.exists(os.path.join(erpnext_path, 'data', 'master.sql.gz')): + os.system('gunzip data/master.sql.gz') + +# setup conf +if not os.path.exists(os.path.join(erpnext_path, 'conf.py')): + # read template conf file + with open(os.path.join(erpnext_path, 'lib', 'conf', 'conf.py'), 'r') as template: + content = template.read() + + # manipulate content + import re + + # set new_dbname, new_dbpassword, modules_path, files_path, backup_path, log_file_name + content = re.sub("db_name.*", "db_name = '%s'" % new_dbname, content) + content = re.sub("db_password.*", "db_password = '%s'" % new_dbpassword, content) + content = re.sub("modules_path.*", "modules_path = '%s'" % \ + os.path.join(erpnext_path, 'erpnext'), content) + content = re.sub("files_path.*", "files_path = '%s'" % \ + os.path.join(erpnext_path, 'files'), content) + content = re.sub("backup_path.*", "backup_path = '%s'" % \ + os.path.join(erpnext_path, 'backups'), content) + content = re.sub("log_file_name.*", "log_file_name = '%s'" % \ + os.path.join(erpnext_path, 'logs', 'error_log.txt'), content) + + + # write conf file + with open(os.path.join(erpnext_path, 'conf.py'), 'w') as new_conf: + new_conf.write(content) + +# install db +import sys +sys.path.append(erpnext_path) +sys.path.append(os.path.join(erpnext_path, 'lib')) +import conf +sys.path.append(conf.modules_path) + +from webnotes.install_lib.install import Installer +inst = Installer('root', root_pwd) +inst.import_from_db(new_dbname, source_path=os.path.join(erpnext_path, 'data', 'master.sql'), verbose = 1) + +# apply patches +os.chdir(erpnext_path) +os.system("lib/wnf.py -l") + +# force sync all +os.system("lib/wnf.py --sync_all -f") + +steps_remaining = """ +To Do: + +* Configure apache/http conf file to point to public folder +* chown recursively all files in your folder to apache user +""" + +print steps_remaining + diff --git a/public/css/wn-web.css b/public/css/wn-web.css index 8814437afa..78cb222249 100644 --- a/public/css/wn-web.css +++ b/public/css/wn-web.css @@ -1,9 +1,9 @@ #body_div { - background: url("files/indian-textile-5.gif") repeat; + background: url("../files/indian-textile-5.gif") repeat; - font-family: 'Lato', Verdana, Sans !important; + font-family: 'Arial', Verdana, Sans !important; font-size: 14px !important; @@ -17,10 +17,8 @@ - - h1, h2, h3, h4, h5 { - font-family: 'Lato', Arial, 'Helvetica Neue' !important; + font-family: 'Arial', Arial, 'Helvetica Neue' !important; } @@ -93,7 +91,7 @@ h2 { clear: both; margin: -50px; margin-top: 50px; - background-color: #DEE1D0; //#E7DFCA; + background-color: #FFFAED; padding: 50px; } @@ -119,19 +117,12 @@ h2 { padding: 4px; } -.avatar { - height: 75px; - width: 75px; - border-radius: 100px 100px 100px 100px; - overflow: hidden; -} - .link-big { font-size: 140%; } .sticky { - background-color: #FFFBC4; + background-color: #F0EDDD; padding: 15px; margin-left: 15px; font-size: 12px; diff --git a/public/js/wn-web.js b/public/js/wn-web.js index cd6552ab75..e45acf239c 100644 --- a/public/js/wn-web.js +++ b/public/js/wn-web.js @@ -1,4 +1,4 @@ -window.home_page = "index"; +window.home_page = "home"; // footer signup widget // automatically adds it to the .layout-main div of the page // adds events and also random goodies. @@ -8,18 +8,30 @@ erpnext.set_request_signup = function(page_name) { // goodies var goodies = [ "ERPNext also contains a module to build your website. \ -The way it works is, when you log out, the app becomes your website. \ -This website is generated from ERPNext.", + The way it works is, when you log out, the app becomes your website. \ + This website is generated from ERPNext.", - "You can add custom fields to your transactions in ERPNext to capture specific information about your business.", + "You can add custom fields to your transactions in ERPNext to \ + capture specific information about your business.", - "All forms in ERPNext can be customized, if you feel there are features you do not want to use, you can hide them.", + "All forms in ERPNext can be customized, if you feel there are \ + features you do not want to use, you can hide them.", - "You can email transactions like Quotations and Invoices directly from the system. You can also set this process to become automatic", + "You can email transactions like Quotations and Invoices directly \ + from the system. You can also set this process to become automatic", - "You can create your own Roles and assign user to those roles. You can also set detailed permissions for each role in transactions.", + "You can create your own Roles and assign user to those roles. \ + You can also set detailed permissions for each role in transactions.", - "ERPNext allows you to assign any transaction like an Invoice or Customer Issue to a user. You can also add comments on any transaction." + "ERPNext allows you to assign any transaction like an Invoice \ + or Customer Issue to a user. You can also add comments on any \ + transaction.", + + "Stay on top with a daily, weekly or montly email summarizing all your business\ + activites and accounting data like Income, Receivables, Paybles etc.", + + "Integrate incoming Support queries to your email into ERPNext. \ + Keep track of open tickets and allocate tickets to your users." ]; @@ -28,54 +40,82 @@ This website is generated from ERPNext.", $('#page-' + page_name + ' .layout-main').append(' """).render(top_bar_items = top_bar_items, - brand=website_settings.brand_html or webnotes.get_default('company') or 'ERPNext') + brand=website_settings.brand_html or webnotes.utils.get_defaults('company') or 'ERPNext') def get_footer(page_name): """get page footer""" @@ -143,4 +144,4 @@ def get_footer(page_name): {% endfor %} """).render(website_settings.fields) \ No newline at end of file + """).render(website_settings.fields) diff --git a/public/css/wn-web.css b/public/css/wn-web.css index 78cb222249..e69de29bb2 100644 --- a/public/css/wn-web.css +++ b/public/css/wn-web.css @@ -1,134 +0,0 @@ -#body_div { - - background: url("../files/indian-textile-5.gif") repeat; - - - font-family: 'Arial', Verdana, Sans !important; - - - font-size: 14px !important; - -} - - -.small { - font-size: 12px !important; -} - - - -h1, h2, h3, h4, h5 { - font-family: 'Arial', Arial, 'Helvetica Neue' !important; -} - - -/* User CSS */ - -hr { - clear: both; -} - -p { - margin-top: 2px; -} - - -.hand { - font-family: Pacifico; - font-size: 18px; -} - -h1.top { - text-align: center; -} - -.sub-head { - text-align: center; - color: #888; - font-size: 18px; - margin: 10px 0px; -} - -.layout-main, .layout-main-section { - padding: 50px; -} - -.layout-main-section { - width: 60%; -} - -.layout-side-section { - padding-top: 50px; -} - -h2 { - //font-family: Pacifico; - font-size: 20px; - font-weight: bold; - color: #CC0000; - padding: 25px 0px 25px 0px; - clear: both; - text-align: left; -} - -.center { - text-align: center; -} - -.left { - width: 375px; - padding-right: 25px; - float: left; -} - -.right { - width: 375px; - padding-left: 25px; - float: left; -} - -.page-footer { - clear: both; - margin: -50px; - margin-top: 50px; - background-color: #FFFAED; - padding: 50px; -} - -.page-footer input { - width: 140px; - font-size: 17px; - padding: 4px; - margin-top: 2px; -} - -.page-footer .section-head { - padding: 0px; - margin-bottom: 7px; -} - -.green { - color: green; -} - -.web-form input, .web-form textarea { - width: 400px; - font-size: 17px; - padding: 4px; -} - -.link-big { - font-size: 140%; -} - -.sticky { - background-color: #F0EDDD; - padding: 15px; - margin-left: 15px; - font-size: 12px; - color: #444; - width: 240px; - min-height: 120px; - float: right; - box-shadow: 2px 2px 6px #973; -} \ No newline at end of file diff --git a/public/js/wn-web.js b/public/js/wn-web.js index e45acf239c..028515e3a0 100644 --- a/public/js/wn-web.js +++ b/public/js/wn-web.js @@ -1,121 +1 @@ -window.home_page = "home"; -// footer signup widget -// automatically adds it to the .layout-main div of the page -// adds events and also random goodies. - -erpnext.set_request_signup = function(page_name) { - - // goodies - var goodies = [ - "ERPNext also contains a module to build your website. \ - The way it works is, when you log out, the app becomes your website. \ - This website is generated from ERPNext.", - - "You can add custom fields to your transactions in ERPNext to \ - capture specific information about your business.", - - "All forms in ERPNext can be customized, if you feel there are \ - features you do not want to use, you can hide them.", - - "You can email transactions like Quotations and Invoices directly \ - from the system. You can also set this process to become automatic", - - "You can create your own Roles and assign user to those roles. \ - You can also set detailed permissions for each role in transactions.", - - "ERPNext allows you to assign any transaction like an Invoice \ - or Customer Issue to a user. You can also add comments on any \ - transaction.", - - "Stay on top with a daily, weekly or montly email summarizing all your business\ - activites and accounting data like Income, Receivables, Paybles etc.", - - "Integrate incoming Support queries to your email into ERPNext. \ - Keep track of open tickets and allocate tickets to your users." - - ]; - - - // add the footer - - $('#page-' + page_name + ' .layout-main').append('');if(in_list(user_roles,'System Manager')&&(wn.boot.setup_complete=='No')){wn.require("js/complete_setup.js");erpnext.complete_setup.show();} if(wn.boot.expires_on&&in_list(user_roles,'System Manager')){var today=dateutil.str_to_obj(dateutil.get_today());var expires_on=dateutil.str_to_obj(wn.boot.expires_on);var diff=dateutil.get_diff(expires_on,today);if(0<=diff&&diff<=15){var expiry_string=diff==0?"today":repl("in %(diff)s day(s)",{diff:diff});$('header').append(repl('
\ Your ERPNext subscription will expire %(expiry_string)s. \ Please renew your subscription to continue using ERPNext \ diff --git a/public/js/all-web.js b/public/js/all-web.js index cfc2f5548d..1dc35ac0e6 100644 --- a/public/js/all-web.js +++ b/public/js/all-web.js @@ -710,7 +710,7 @@ wn.provide('wn.modules');$.extend(wn.modules,erpnext.modules);wn.modules['Core'] erpnext.startup.start=function(){console.log('Starting up...');$('#startup_div').html('Starting up...').toggle(true);erpnext.startup.set_globals();if(user!='Guest'){if(wn.boot.user_background){erpnext.set_user_background(wn.boot.user_background);} wn.boot.profile.allow_modules=wn.boot.profile.allow_modules.concat(['To Do','Knowledge Base','Calendar','Activity','Messages']) erpnext.toolbar.setup();erpnext.startup.set_periodic_updates();$('footer').html('');if(in_list(user_roles,'System Manager')&&(wn.boot.setup_complete=='No')){wn.require("erpnext/startup/js/complete_setup.js");erpnext.complete_setup.show();} + ERPNext | Attributions and License
');if(in_list(user_roles,'System Manager')&&(wn.boot.setup_complete=='No')){wn.require("js/complete_setup.js");erpnext.complete_setup.show();} if(wn.boot.expires_on&&in_list(user_roles,'System Manager')){var today=dateutil.str_to_obj(dateutil.get_today());var expires_on=dateutil.str_to_obj(wn.boot.expires_on);var diff=dateutil.get_diff(expires_on,today);if(0<=diff&&diff<=15){var expiry_string=diff==0?"today":repl("in %(diff)s day(s)",{diff:diff});$('header').append(repl('
\ Your ERPNext subscription will expire %(expiry_string)s. \ Please renew your subscription to continue using ERPNext \ diff --git a/public/js/complete_setup.js b/public/js/complete_setup.js new file mode 100644 index 0000000000..59473430e8 --- /dev/null +++ b/public/js/complete_setup.js @@ -0,0 +1,10 @@ + +/* + * erpnext/startup/js/complete_setup.js + */ +wn.provide('erpnext.complete_setup');$.extend(erpnext.complete_setup,{show:function(){d=erpnext.complete_setup.prepare_dialog();d.show();},prepare_dialog:function(){var d=new wn.widgets.Dialog({title:"Setup",fields:[{fieldname:'first_name',label:'Your First Name',fieldtype:'Data',reqd:1},{fieldname:'last_name',label:'Your Last Name',fieldtype:'Data'},{fieldname:'company_name',label:'Company Name',fieldtype:'Data',reqd:1,description:'e.g. "My Company LLC"'},{fieldname:'company_abbr',label:'Company Abbreviation',fieldtype:'Data',description:'e.g. "MC"',reqd:1},{fieldname:'fy_start',label:'Financial Year Start Date',fieldtype:'Select',description:'Your financial year begins on"',reqd:1,options:erpnext.complete_setup.fy_start_list.join('\n')},{fieldname:'currency',label:'Default Currency',reqd:1,options:erpnext.complete_setup.currency_list.join('\n'),fieldtype:'Select'},{fieldname:'industry',label:'Industry',reqd:1,options:erpnext.complete_setup.industry_list.join('\n'),fieldtype:'Select'},{fieldname:'country',label:'Country',reqd:1,options:erpnext.complete_setup.country_list.join('\n'),fieldtype:'Select'},{fieldname:'timezone',label:'Time Zone',reqd:1,options:'',fieldtype:'Select'},{fieldname:'update',label:'Setup',fieldtype:'Button'},],});if(user!='Administrator'){$(d.appframe.$titlebar).find('.close').toggle(false);$('header').toggle(false);} +d.fields_dict.update.input.onclick=function(){var data=d.get_values();if(!data)return;$(this).set_working();$c_obj('Setup Control','setup_account',data,function(r,rt){sys_defaults=r.message;user_fullname=r.message.user_fullname;wn.boot.user_info[user].fullname=user_fullname;d.hide();$('header').toggle(true);wn.container.wntoolbar.set_user_name();});};d.fields_dict.country.input.onchange=function(){var country=d.fields_dict.country.input.value;var $timezone=$(d.fields_dict.timezone.input);$timezone.empty();if(country){var timezone_list=erpnext.complete_setup.timezone_dict[country];if(timezone_list.length>1){timezone_list=[""].concat(timezone_list);} +$timezone.add_options(timezone_list);}};if(wn.control_panel.company_name){var inp=d.fields_dict.company_name.input;inp.value=wn.control_panel.company_name;inp.disabled=true;} +if(user_fullname){u=user_fullname.split(' ');if(u[0]){d.fields_dict.first_name.input.value=u[0];} +if(u[1]){d.fields_dict.last_name.input.value=u[1];}} +return d;},fy_start_list:['','1st Jan','1st Apr','1st Jul','1st Oct'],currency_list:['','AED','AFN','ALL','AMD','ANG','AOA','ARS','AUD','AZN','BAM','BBD','BDT','BGN','BHD','BIF','BMD','BND','BOB','BRL','BSD','BTN','BYR','BZD','CAD','CDF','CFA','CFP','CHF','CLP','CNY','COP','CRC','CUC','CZK','DJF','DKK','DOP','DZD','EEK','EGP','ERN','ETB','EUR','EURO','FJD','FKP','FMG','GBP','GEL','GHS','GIP','GMD','GNF','GQE','GTQ','GYD','HKD','HNL','HRK','HTG','HUF','IDR','ILS','INR','IQD','IRR','ISK','JMD','JOD','JPY','KES','KGS','KHR','KMF','KPW','KRW','KWD','KYD','KZT','LAK','LBP','LKR','LRD','LSL','LTL','LVL','LYD','MAD','MDL','MGA','MKD','MMK','MNT','MOP','MRO','MUR','MVR','MWK','MXN','MYR','MZM','NAD','NGN','NIO','NOK','NPR','NRs','NZD','OMR','PAB','PEN','PGK','PHP','PKR','PLN','PYG','QAR','RMB','RON','RSD','RUB','RWF','SAR','SCR','SDG','SDR','SEK','SGD','SHP','SOS','SRD','STD','SYP','SZL','THB','TJS','TMT','TND','TRY','TTD','TWD','TZS','UAE','UAH','UGX','USD','USh','UYU','UZS','VEB','VND','VUV','WST','XAF','XCD','XDR','XOF','XPF','YEN','YER','YTL','ZAR','ZMK','ZWR'],industry_list:['','Aerospace and Defence','Agriculture','Apparel','Automobile','Banking','Biotechnology','Chemical','Communications','Consulting','Customer Service','Education','Electronics','Energy','Engineering','Entertainment','Environmental','Finance','Food and Beverage','Government','Healthcare','Hospitality','Information Technology','Insurance','Machinery','Manufacturing','Media','Not For Profit','Recreation','Retail','Shipping','Technology','Telecommunications','Transportation','Trading','Utilities','Other'],country_list:["",'Afghanistan','Albania','Algeria','Andorra','Angola','Antigua and Barbuda','Argentina','Armenia','Australia','Austria','Azerbaijan','Bahamas','Bahrain','Bangladesh','Barbados','Belarus','Belgium','Belize','Benin','Bhutan','Bolivia','Bosnia and Herzegovina','Botswana','Brazil','Brunei Darussalam','Bulgaria','Burkina Faso','Burundi','Cambodia','Cameroon','Canada','Cape Verde','Central African Republic','Chad','Chile','Colombia','Comoros','Costa Rica','Croatia','Cuba','Cyprus','Czech Republic',"C\xc3\xb4te d'Ivoire",'Democratic Republic of the Congo','Denmark','Djibouti','Dominica','Dominican Republic','East Timor','Ecuador','Egypt','El Salvador','Equatorial Guinea','Eritrea','Estonia','Ethiopia','Federated States of Micronesia','Fiji','Finland','France','Gabon','Georgia','Germany','Ghana','Greece','Grenada','Guatemala','Guinea','Guinea-Bissau','Guyana','Haiti','Honduras','Hungary','Iceland','India','Indonesia','Iran','Iraq','Israel','Italy','Jamaica','Japan','Jordan','Kazakhstan','Kenya','Kingdom of the Netherlands','Kiribati','Kuwait','Kyrgyzstan','Laos','Latvia','Lebanon','Lesotho','Liberia','Libya','Liechtenstein','Lithuania','Luxembourg','Macedonia','Madagascar','Malawi','Malaysia','Maldives','Mali','Malta','Marshall Islands','Mauritania','Mauritius','Mexico','Moldova','Monaco','Mongolia','Montenegro','Morocco','Mozambique','Myanmar','Namibia','Nauru','Nepal','New Zealand','Nicaragua','Niger','Nigeria','North Korea','Norway','Oman','Pakistan','Palau','Panama','Papua New Guinea','Paraguay',"People's Republic of China",'Peru','Philippines','Poland','Portugal','Qatar','Republic of Ireland','Republic of the Congo','Romania','Russia','Rwanda','Saint Kitts and Nevis','Saint Lucia','Saint Vincent and the Grenadines','Samoa','San Marino','Saudi Arabia','Senegal','Serbia','Seychelles','Sierra Leone','Singapore','Slovakia','Slovenia','Solomon Islands','Somalia','South Africa','South Korea','Spain','Sri Lanka','Sudan','Suriname','Swaziland','Sweden','Switzerland','Syria','S\xc3\xa3o Tom\xc3\xa9 and Pr\xc3\xadncipe','Tajikistan','Tanzania','Thailand','The Gambia','Togo','Tonga','Trinidad and Tobago','Tunisia','Turkey','Turkmenistan','Tuvalu','Uganda','Ukraine','United Arab Emirates','United Kingdom','United States','Uruguay','Uzbekistan','Vanuatu','Vatican City','Venezuela','Vietnam','Yemen','Zambia','Zimbabwe'],timezone_dict:{'Afghanistan':['Asia/Kabul'],'Albania':['Europe/Tirane'],'Algeria':['Africa/Algiers'],'Andorra':['Europe/Andorra'],'Angola':['Africa/Luanda'],'Antigua and Barbuda':['America/Antigua'],'Argentina':['America/Argentina/Buenos_Aires','America/Argentina/Cordoba','America/Argentina/Jujuy','America/Argentina/Tucuman','America/Argentina/Catamarca','America/Argentina/La_Rioja','America/Argentina/San_Juan','America/Argentina/Mendoza','America/Argentina/Rio_Gallegos','America/Argentina/Ushuaia'],'Armenia':['Asia/Yerevan'],'Australia':['Australia/Lord_Howe','Australia/Hobart','Australia/Currie','Australia/Melbourne','Australia/Sydney','Australia/Broken_Hill','Australia/Brisbane','Australia/Lindeman','Australia/Adelaide','Australia/Darwin','Australia/Perth'],'Austria':['Europe/Vienna'],'Azerbaijan':['Asia/Baku'],'Bahamas':['America/Nassau'],'Bahrain':['Asia/Bahrain'],'Bangladesh':['Asia/Dhaka'],'Barbados':['America/Barbados'],'Belarus':['Europe/Minsk'],'Belgium':['Europe/Brussels'],'Belize':['America/Belize'],'Benin':['Africa/Porto-Novo'],'Bhutan':['Asia/Thimphu'],'Bolivia':['America/La_Paz'],'Bosnia and Herzegovina':['Europe/Sarajevo'],'Botswana':['Africa/Gaborone'],'Brazil':['America/Noronha','America/Belem','America/Fortaleza','America/Recife','America/Araguaina','America/Maceio','America/Bahia','America/Sao_Paulo','America/Campo_Grande','America/Cuiaba','America/Porto_Velho','America/Boa_Vista','America/Manaus','America/Eirunepe','America/Rio_Branco'],'Brunei Darussalam':['Asia/Brunei'],'Bulgaria':['Europe/Sofia'],'Burkina Faso':['Africa/Ouagadougou'],'Burundi':['Africa/Bujumbura'],'Cambodia':['Asia/Phnom_Penh'],'Cameroon':['Africa/Douala'],'Canada':['America/St_Johns','America/Halifax','America/Glace_Bay','America/Moncton','America/Goose_Bay','America/Blanc-Sablon','America/Montreal','America/Toronto','America/Nipigon','America/Thunder_Bay','America/Pangnirtung','America/Iqaluit','America/Atikokan','America/Rankin_Inlet','America/Winnipeg','America/Rainy_River','America/Cambridge_Bay','America/Regina','America/Swift_Current','America/Edmonton','America/Yellowknife','America/Inuvik','America/Dawson_Creek','America/Vancouver','America/Whitehorse','America/Dawson'],'Cape Verde':['Atlantic/Cape_Verde'],'Central African Republic':['Africa/Bangui'],'Chad':['Africa/Ndjamena'],'Chile':['America/Santiago','Pacific/Easter'],'Colombia':['America/Bogota'],'Comoros':['Indian/Comoro'],'Costa Rica':['America/Costa_Rica'],'Croatia':['Europe/Zagreb'],'Cuba':['America/Havana'],'Cyprus':['Asia/Nicosia'],'Czech Republic':['Europe/Prague'],"C\xc3\xb4te d'Ivoire":['Africa/Abidjan'],'Democratic Republic of the Congo':['Africa/Kinshasa','Africa/Lubumbashi'],'Denmark':['Europe/Copenhagen'],'Djibouti':['Africa/Djibouti'],'Dominica':['America/Dominica'],'Dominican Republic':['America/Santo_Domingo'],'East Timor':['Asia/Dili'],'Ecuador':['America/Guayaquil','Pacific/Galapagos'],'Egypt':['Africa/Cairo'],'El Salvador':['America/El_Salvador'],'Equatorial Guinea':['Africa/Malabo'],'Eritrea':['Africa/Asmera'],'Estonia':['Europe/Tallinn'],'Ethiopia':['Africa/Addis_Ababa'],'Federated States of Micronesia':['Pacific/Truk','Pacific/Ponape','Pacific/Kosrae'],'Fiji':['Pacific/Fiji'],'Finland':['Europe/Helsinki'],'France':['Europe/Paris'],'Gabon':['Africa/Libreville'],'Georgia':['Asia/Tbilisi'],'Germany':['Europe/Berlin'],'Ghana':['Africa/Accra'],'Greece':['Europe/Athens'],'Grenada':['America/Grenada'],'Guatemala':['America/Guatemala'],'Guinea':['Africa/Conakry'],'Guinea-Bissau':['Africa/Bissau'],'Guyana':['America/Guyana'],'Haiti':['America/Guatemala'],'Honduras':['America/Tegucigalpa'],'Hungary':['Europe/Budapest'],'Iceland':['Atlantic/Reykjavik'],'India':['Asia/Calcutta'],'Indonesia':['Asia/Jakarta','Asia/Pontianak','Asia/Makassar','Asia/Jayapura'],'Iran':['Asia/Tehran'],'Iraq':['Asia/Baghdad'],'Israel':['Asia/Jerusalem'],'Italy':['Europe/Rome'],'Jamaica':['America/Jamaica'],'Japan':['Asia/Tokyo'],'Jordan':['Asia/Amman'],'Kazakhstan':['Asia/Almaty','Asia/Qyzylorda','Asia/Aqtobe','Asia/Aqtau','Asia/Oral'],'Kenya':['Africa/Nairobi'],'Kingdom of the Netherlands':['Europe/Amsterdam'],'Kiribati':['Pacific/Tarawa','Pacific/Enderbury','Pacific/Kiritimati'],'Kuwait':['Asia/Kuwait'],'Kyrgyzstan':['Asia/Bishkek'],'Laos':['Asia/Vientiane'],'Latvia':['Europe/Riga'],'Lebanon':['Asia/Beirut'],'Lesotho':['Africa/Maseru'],'Liberia':['Africa/Monrovia'],'Libya':['Africa/Tripoli'],'Liechtenstein':['Europe/Vaduz'],'Lithuania':['Europe/Vilnius'],'Luxembourg':['Europe/Luxembourg'],'Macedonia':['Europe/Skopje'],'Madagascar':['Indian/Antananarivo'],'Malawi':['Africa/Blantyre'],'Malaysia':['Asia/Kuala_Lumpur','Asia/Kuching'],'Maldives':['Indian/Maldives'],'Mali':['Africa/Bamako'],'Malta':['Europe/Malta'],'Marshall Islands':['Pacific/Majuro','Pacific/Kwajalein'],'Mauritania':['Africa/Nouakchott'],'Mauritius':['Indian/Mauritius'],'Mexico':['America/Mexico_City','America/Cancun','America/Merida','America/Monterrey','America/Mazatlan','America/Chihuahua','America/Hermosillo','America/Tijuana'],'Moldova':['Europe/Chisinau'],'Monaco':['Europe/Monaco'],'Mongolia':['Asia/Ulaanbaatar','Asia/Hovd','Asia/Choibalsan'],'Montenegro':['Europe/Podgorica'],'Morocco':['Africa/Casablanca'],'Mozambique':['Africa/Maputo'],'Myanmar':['Asia/Rangoon'],'Namibia':['Africa/Windhoek'],'Nauru':['Pacific/Nauru'],'Nepal':['Asia/Katmandu'],'New Zealand':['Pacific/Auckland','Pacific/Chatham'],'Nicaragua':['America/Managua'],'Niger':['Africa/Niamey'],'Nigeria':['Africa/Lagos'],'North Korea':['Asia/Pyongyang'],'Norway':['Europe/Oslo'],'Oman':['Asia/Muscat'],'Pakistan':['Asia/Karachi'],'Palau':['Pacific/Palau'],'Panama':['America/Panama'],'Papua New Guinea':['Pacific/Port_Moresby'],'Paraguay':['America/Asuncion'],"People's Republic of China":['Asia/Shanghai','Asia/Harbin','Asia/Chongqing','Asia/Urumqi','Asia/Kashgar'],'Peru':['America/Lima'],'Philippines':['Asia/Manila'],'Poland':['Europe/Warsaw'],'Portugal':['Europe/Lisbon','Atlantic/Madeira','Atlantic/Azores'],'Qatar':['Asia/Qatar'],'Republic of Ireland':['Europe/Dublin'],'Republic of the Congo':['Africa/Brazzaville'],'Romania':['Europe/Bucharest'],'Russia':['Europe/Kaliningrad','Europe/Moscow','Europe/Volgograd','Europe/Samara','Asia/Yekaterinburg','Asia/Omsk','Asia/Novosibirsk','Asia/Krasnoyarsk','Asia/Irkutsk','Asia/Yakutsk','Asia/Vladivostok','Asia/Sakhalin','Asia/Magadan','Asia/Kamchatka','Asia/Anadyr'],'Rwanda':['Africa/Kigali'],'Saint Kitts and Nevis':['America/St_Kitts'],'Saint Lucia':['America/St_Lucia'],'Saint Vincent and the Grenadines':['America/St_Vincent'],'Samoa':['Pacific/Apia'],'San Marino':['Europe/San_Marino'],'Saudi Arabia':['Asia/Riyadh'],'Senegal':['Africa/Dakar'],'Serbia':['Europe/Belgrade'],'Seychelles':['Indian/Mahe'],'Sierra Leone':['Africa/Freetown'],'Singapore':['Asia/Singapore'],'Slovakia':['Europe/Bratislava'],'Slovenia':['Europe/Ljubljana'],'Solomon Islands':['Pacific/Guadalcanal'],'Somalia':['Africa/Mogadishu'],'South Africa':['Africa/Johannesburg'],'South Korea':['Asia/Seoul'],'Spain':['Europe/Madrid','Africa/Ceuta','Atlantic/Canary'],'Sri Lanka':['Asia/Colombo'],'Sudan':['Africa/Khartoum'],'Suriname':['America/Paramaribo'],'Swaziland':['Africa/Mbabane'],'Sweden':['Europe/Stockholm'],'Switzerland':['Europe/Zurich'],'Syria':['Asia/Damascus'],'S\xc3\xa3o Tom\xc3\xa9 and Pr\xc3\xadncipe':['Africa/Sao_Tome'],'Tajikistan':['Asia/Dushanbe'],'Tanzania':['Africa/Dar_es_Salaam'],'Thailand':['Asia/Bangkok'],'The Gambia':['Africa/Banjul'],'Togo':['Africa/Lome'],'Tonga':['Pacific/Tongatapu'],'Trinidad and Tobago':['America/Port_of_Spain'],'Tunisia':['Africa/Tunis'],'Turkey':['Europe/Istanbul'],'Turkmenistan':['Asia/Ashgabat'],'Tuvalu':['Pacific/Funafuti'],'Uganda':['Africa/Kampala'],'Ukraine':['Europe/Kiev','Europe/Uzhgorod','Europe/Zaporozhye','Europe/Simferopol'],'United Arab Emirates':['Asia/Dubai'],'United Kingdom':['Europe/London'],'United States':['America/New_York','America/Detroit','America/Kentucky/Louisville','America/Kentucky/Monticello','America/Indiana/Indianapolis','America/Indiana/Marengo','America/Indiana/Knox','America/Indiana/Vevay','America/Chicago','America/Indiana/Vincennes','America/Indiana/Petersburg','America/Menominee','America/North_Dakota/Center','America/North_Dakota/New_Salem','America/Denver','America/Boise','America/Shiprock','America/Phoenix','America/Los_Angeles','America/Anchorage','America/Juneau','America/Yakutat','America/Nome','America/Adak','Pacific/Honolulu'],'Uruguay':['America/Montevideo'],'Uzbekistan':['Asia/Samarkand','Asia/Tashkent'],'Vanuatu':['Pacific/Efate'],'Vatican City':['Europe/Vatican'],'Venezuela':['America/Caracas'],'Vietnam':['Asia/Saigon'],'Yemen':['Asia/Aden'],'Zambia':['Africa/Lusaka'],'Zimbabwe':['Africa/Harare'],},}); \ No newline at end of file diff --git a/public/js/kb_common.js b/public/js/kb_common.js new file mode 100644 index 0000000000..e61b5ef91b --- /dev/null +++ b/public/js/kb_common.js @@ -0,0 +1,29 @@ + +/* + * erpnext/utilities/page/kb_common/kb_common.js + */ +KBItemToolbar=function(args,kb){$.extend(this,args);var me=this;this.make=function(){this.wrapper=$a(this.parent,'div','',{});this.line1=$a(this.wrapper,'div','',{color:'#888',fontSize:'11px',margin:'7px 0px'});this.make_timestamp();if(this.with_tags) +this.make_tags();this.setup_del();} +this.make_timestamp=function(){this.line1.innerHTML=repl('By %(name)s | %(when)s',{name:wn.utils.full_name(this.det.first_name,this.det.last_name),when:wn.datetime.comment_when(this.det.modified)});if(has_common(user_roles,['Administrator','System Manager'])){this.line1.innerHTML+=' | delete';}} +this.make_tags=function(){this.line1.innerHTML+=' | ' +this.tags_area=$a(this.line1,'span','kb-tags') +this.tags=new TagList(this.tags_area,this.det._user_tags&&(this.det._user_tags.split(',')),this.doctype,this.det.name,0,kb.set_tag_filter)} +this.setup_del=function(){$(this.line1).find('.del-link').click(function(){console.log(1);this.innerHTML='deleting...';this.disabled=1;$c_page('utilities','questions','delete',{dt:me.doctype,dn:me.det.name},function(r,rt){kb.list.run()});});} +this.make();} +EditableText=function(args){$.extend(this,args);var me=this;me.$w=$(repl('
\ +
\ + [edit]\ + \ +

Formatted as markdown
\ + \ + Cancel\ +
',args)).appendTo(me.parent);this.set_display=function(txt){me.$w.find('.ed-text-display').html(wn.markdown(txt));me.text=txt;} +this.set_display(me.text);if(me.height)me.$w.find('.ed-text-input').css('height',me.height);me.$w.find('.ed-text-edit').click(function(){me.$w.find('.ed-text-input').val(me.text);me.show_as_input();}) +me.$w.find('.ed-text-save').click(function(){var v=me.$w.find('.ed-text-input').val();if(!v){msgprint('Please write something!');return;} +var btn=this;$(btn).set_working();$c_page('utilities','question_view','update_item',{dt:me.dt,dn:me.dn,fn:me.fieldname,text:v},function(r){$(btn).done_working();if(r.exc){msgprint(r.exc);return;} +me.set_display(v);me.show_as_text();});}) +me.$w.find('.ed-text-cancel').click(function(){me.show_as_text();}) +this.show_as_text=function(){me.$w.find('.ed-text-display, .ed-text-edit').toggle(true);me.$w.find('.ed-text-input, .ed-text-save, .ed-text-cancel, .help').toggle(false);} +this.show_as_input=function(){me.$w.find('.ed-text-display, .ed-text-edit').toggle(false);me.$w.find('.ed-text-input, .ed-text-save, .ed-text-cancel, .help').toggle(true);}} \ No newline at end of file diff --git a/public/js/product_category.js b/public/js/product_category.js new file mode 100644 index 0000000000..aac872f16d --- /dev/null +++ b/public/js/product_category.js @@ -0,0 +1,7 @@ + +/* + * erpnext/website/js/product_category.js + */ +erpnext.make_product_categories=function(wrapper){wrapper.category_list=new wn.ui.Listing({parent:$(wrapper).find('.more-categories').get(0),query:'select count(name) as items, item_group \ + from tabItem where is_sales_item="Yes" \ + group by item_group order by items desc',hide_refresh:true,render_row:function(parent,data){parent.innerHTML=repl('%(item_group)s (%(items)s)',data);}});wrapper.category_list.run();} \ No newline at end of file diff --git a/public/js/wn-web.js b/public/js/wn-web.js index 028515e3a0..e45acf239c 100644 --- a/public/js/wn-web.js +++ b/public/js/wn-web.js @@ -1 +1,121 @@ -window.home_page = "Login Page"; +window.home_page = "home"; +// footer signup widget +// automatically adds it to the .layout-main div of the page +// adds events and also random goodies. + +erpnext.set_request_signup = function(page_name) { + + // goodies + var goodies = [ + "ERPNext also contains a module to build your website. \ + The way it works is, when you log out, the app becomes your website. \ + This website is generated from ERPNext.", + + "You can add custom fields to your transactions in ERPNext to \ + capture specific information about your business.", + + "All forms in ERPNext can be customized, if you feel there are \ + features you do not want to use, you can hide them.", + + "You can email transactions like Quotations and Invoices directly \ + from the system. You can also set this process to become automatic", + + "You can create your own Roles and assign user to those roles. \ + You can also set detailed permissions for each role in transactions.", + + "ERPNext allows you to assign any transaction like an Invoice \ + or Customer Issue to a user. You can also add comments on any \ + transaction.", + + "Stay on top with a daily, weekly or montly email summarizing all your business\ + activites and accounting data like Income, Receivables, Paybles etc.", + + "Integrate incoming Support queries to your email into ERPNext. \ + Keep track of open tickets and allocate tickets to your users." + + ]; + + + // add the footer + + $('#page-' + page_name + ' .layout-main').append('