From 90762fcb2d6aef7bb08655ca51f31a1ea89bd3f3 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 21 Feb 2013 14:56:44 +0530 Subject: [PATCH 01/73] added html5 header --- website/templates/html/outer.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/website/templates/html/outer.html b/website/templates/html/outer.html index a8b73ad122..de961227b3 100644 --- a/website/templates/html/outer.html +++ b/website/templates/html/outer.html @@ -1,7 +1,3 @@ -{# - requires, brand_html, top_bar_items, footer_items, copyright, content, address -#} - {% extends "html/base.html" %} {% block body %} From d0db70507c8b3aefac3d6b2c95c6312b0cdc90d0 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 21 Feb 2013 14:58:48 +0530 Subject: [PATCH 02/73] added html5 header --- website/templates/html/base.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/templates/html/base.html b/website/templates/html/base.html index 2724e578ed..d2545cb99d 100644 --- a/website/templates/html/base.html +++ b/website/templates/html/base.html @@ -1,4 +1,5 @@ + {{ title }} @@ -24,4 +25,5 @@ {% block body %} {% endblock %} - \ No newline at end of file + + \ No newline at end of file From 6f27d024aabe042a66fbccb975b846d7b3d1e8f0 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 21 Feb 2013 15:01:55 +0530 Subject: [PATCH 03/73] added html5 header --- website/templates/html/base.html | 1 + 1 file changed, 1 insertion(+) diff --git a/website/templates/html/base.html b/website/templates/html/base.html index d2545cb99d..fa01f8aad7 100644 --- a/website/templates/html/base.html +++ b/website/templates/html/base.html @@ -2,6 +2,7 @@ + {{ title }} From 58b2a101aee16bddef75f704042e81dedc0abd71 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 7 Mar 2013 11:42:14 +0530 Subject: [PATCH 04/73] aii: testcases for sales invoice gl entries --- .../doctype/sales_invoice/sales_invoice.py | 2 +- .../sales_invoice/test_sales_invoice.py | 237 ++++++++++++++---- .../delivery_note/test_delivery_note.py | 2 +- 3 files changed, 184 insertions(+), 57 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 47e3195d71..b31d54919c 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -8,7 +8,7 @@ # # 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 diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index fb290d27e3..1f165f0c33 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -38,72 +38,199 @@ class TestSalesInvoice(unittest.TestCase): si.insert() si.submit() - self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"), - "Billed") + self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", + "status"), "Billed") self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Billed") si.cancel() - self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"), - "Submitted") + self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", + "status"), "Submitted") self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing") + def test_sales_invoice_gl_entry_without_aii(self): + si = webnotes.bean(webnotes.copy_doclist(test_records[1])) + si.insert() + si.submit() + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc""", si.doc.name, as_dict=1) + self.assertTrue(gl_entries) + expected_values = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [test_records[1][1]["income_account"], 0.0, 500.0], + [test_records[1][2]["account_head"], 0.0, 80.0], + [test_records[1][3]["account_head"], 0.0, 50.0], + ]) + + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + def test_sales_invoice_gl_entry_with_aii(self): + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + self._insert_purchase_receipt() + dn = self._insert_delivery_note() + + si_against_dn = webnotes.copy_doclist(test_records[1]) + si_against_dn[1]["delivery_note"] = dn.doc.name + si = webnotes.bean(si_against_dn) + si.insert() + si.submit() + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc""", si.doc.name, as_dict=1) + self.assertTrue(gl_entries) + + expected_values = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [test_records[1][1]["income_account"], 0.0, 500.0], + [test_records[1][2]["account_head"], 0.0, 80.0], + [test_records[1][3]["account_head"], 0.0, 50.0], + ["Stock Delivered But Not Billed - _TC", 0.0, 375.0], + [test_records[1][1]["expense_account"], 375.0, 0.0] + ]) + print expected_values + print gl_entries + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + + def _insert_purchase_receipt(self): + from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \ + as pr_test_records + pr = webnotes.bean(copy=pr_test_records[0]) + pr.run_method("calculate_taxes_and_totals") + pr.insert() + pr.submit() + + def _insert_delivery_note(self): + from stock.doctype.delivery_note.test_delivery_note import test_records \ + as dn_test_records + dn = webnotes.bean(copy=dn_test_records[0]) + dn.insert() + dn.submit() + return dn test_dependencies = ["Journal Voucher"] -test_records = [[ - { - "naming_series": "_T-Sales Invoice-", - "company": "_Test Company", - "conversion_rate": 1.0, - "currency": "INR", - "debit_to": "_Test Customer - _TC", - "customer": "_Test Customer", - "customer_name": "_Test Customer", - "doctype": "Sales Invoice", - "due_date": "2013-01-23", - "fiscal_year": "_Test Fiscal Year 2013", - "grand_total": 561.8, - "grand_total_export": 561.8, - "net_total": 500.0, - "plc_conversion_rate": 1.0, - "posting_date": "2013-01-23", - "price_list_currency": "INR", - "price_list_name": "_Test Price List", - "territory": "_Test Territory" - }, - { - "amount": 500.0, - "basic_rate": 500.0, - "description": "138-CMS Shoe", - "doctype": "Sales Invoice Item", - "export_amount": 500.0, - "export_rate": 500.0, - "income_account": "Sales - _TC", - "cost_center": "_Test Cost Center - _TC", - "item_name": "138-CMS Shoe", - "parentfield": "entries", - "qty": 1.0 - }, - { - "account_head": "_Test Account VAT - _TC", - "charge_type": "On Net Total", - "description": "VAT", - "doctype": "Sales Taxes and Charges", - "parentfield": "other_charges", - "tax_amount": 30.0, - }, - { - "account_head": "_Test Account Service Tax - _TC", - "charge_type": "On Net Total", - "description": "Service Tax", - "doctype": "Sales Taxes and Charges", - "parentfield": "other_charges", - "tax_amount": 31.8, - } -]] \ No newline at end of file +test_records = [ + [ + { + "naming_series": "_T-Sales Invoice-", + "company": "_Test Company", + "conversion_rate": 1.0, + "currency": "INR", + "debit_to": "_Test Customer - _TC", + "customer": "_Test Customer", + "customer_name": "_Test Customer", + "doctype": "Sales Invoice", + "due_date": "2013-01-23", + "fiscal_year": "_Test Fiscal Year 2013", + "grand_total": 561.8, + "grand_total_export": 561.8, + "net_total": 500.0, + "plc_conversion_rate": 1.0, + "posting_date": "2013-01-23", + "price_list_currency": "INR", + "price_list_name": "_Test Price List", + "territory": "_Test Territory" + }, + { + "amount": 500.0, + "basic_rate": 500.0, + "description": "138-CMS Shoe", + "doctype": "Sales Invoice Item", + "export_amount": 500.0, + "export_rate": 500.0, + "income_account": "Sales - _TC", + "cost_center": "_Test Cost Center - _TC", + "item_name": "138-CMS Shoe", + "parentfield": "entries", + "qty": 1.0 + }, + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "tax_amount": 30.0, + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "tax_amount": 31.8, + } + ], + [ + { + "naming_series": "_T-Sales Invoice-", + "company": "_Test Company", + "conversion_rate": 1.0, + "currency": "INR", + "debit_to": "_Test Customer - _TC", + "customer": "_Test Customer", + "customer_name": "_Test Customer", + "doctype": "Sales Invoice", + "due_date": "2013-01-23", + "fiscal_year": "_Test Fiscal Year 2013", + "grand_total": 630.0, + "grand_total_export": 630.0, + "net_total": 500.0, + "plc_conversion_rate": 1.0, + "posting_date": "2013-03-07", + "price_list_currency": "INR", + "price_list_name": "_Test Price List", + "territory": "_Test Territory" + }, + { + "item_code": "_Test Item", + "item_name": "_Test Item", + "description": "_Test Item", + "doctype": "Sales Invoice Item", + "parentfield": "entries", + "qty": 1.0, + "basic_rate": 500.0, + "amount": 500.0, + "export_rate": 500.0, + "export_amount": 500.0, + "income_account": "Sales - _TC", + "expense_account": "_Test Account Cost for Goods Sold", + "cost_center": "_Test Cost Center - _TC", + }, + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "tax_amount": 80.0, + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "tax_amount": 50.0, + } + ], +] \ No newline at end of file diff --git a/stock/doctype/delivery_note/test_delivery_note.py b/stock/doctype/delivery_note/test_delivery_note.py index c2bb5d07ca..acdf8b9e07 100644 --- a/stock/doctype/delivery_note/test_delivery_note.py +++ b/stock/doctype/delivery_note/test_delivery_note.py @@ -109,7 +109,7 @@ test_records = [ "description": "CPU", "doctype": "Delivery Note Item", "item_code": "_Test Item", - "item_name": "CPU", + "item_name": "_Test Item", "parentfield": "delivery_note_details", "qty": 5.0, "basic_rate": 100.0, From 9f3c72775365d47d0d15f28835fb506b35e8ec43 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 7 Mar 2013 14:47:41 +0530 Subject: [PATCH 05/73] website navbar color change --- website/css/website.css | 8 +- .../style_settings/custom_template.css | 75 +++++++++++++++++++ .../doctype/style_settings/style_settings.js | 1 + .../doctype/style_settings/style_settings.txt | 37 +++++++-- 4 files changed, 108 insertions(+), 13 deletions(-) diff --git a/website/css/website.css b/website/css/website.css index 956f22e8bc..a0f4e1b3ca 100644 --- a/website/css/website.css +++ b/website/css/website.css @@ -4,14 +4,14 @@ div.outer { box-shadow: 0px 0px 3px rgba(0,0,0,0.9); background-color: #fff; border-radius: 5px; - padding: 20px; - margin: 30px -20px 10px -20px; + padding: 30px; + margin: 30px -30px 10px -30px; min-height: 400px; overflow: hidden; } .outer .navbar { - margin: -20px -20px 10px -20px; + margin: -30px -30px 10px -30px; } footer { @@ -121,5 +121,3 @@ p, li { .avatar-x-large img { width: 100px; } - -/* */ \ No newline at end of file diff --git a/website/doctype/style_settings/custom_template.css b/website/doctype/style_settings/custom_template.css index 9009bbe18a..52897447bd 100644 --- a/website/doctype/style_settings/custom_template.css +++ b/website/doctype/style_settings/custom_template.css @@ -26,3 +26,78 @@ h1, h2, h3, h4, h5 { font-family: '{{ doc.heading_font}}', Arial, 'Helvetica Neue' !important; } {% endif %} + +/* Bootstrap Navbar */ + +.navbar-inverse .navbar-inner { + background-color: #{{ doc.top_bar_background or "444"}}; + background-repeat: repeat-x; + border-color: transparent; + background-image: none; +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #{{ doc.top_bar_foreground or "fff"}}; + text-shadow: none; +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #{{ doc.top_bar_foreground or "fff"}}; +} + +.navbar-inverse .brand { + color: #{{ doc.top_bar_foreground or "fff"}}; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #{{ doc.top_bar_foreground or "fff"}}; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #{{ doc.top_bar_foreground or "fff"}}; + background-color: transparent; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #{{ doc.top_bar_foreground or "fff"}}; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + +} +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #424242; + text-decoration: none; + background-color: transparent; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #{{ doc.top_bar_foreground or "fff"}}; + border-bottom-color: #{{ doc.top_bar_foreground or "fff"}}; +} diff --git a/website/doctype/style_settings/style_settings.js b/website/doctype/style_settings/style_settings.js index 54091a38f2..6a17db99ee 100644 --- a/website/doctype/style_settings/style_settings.js +++ b/website/doctype/style_settings/style_settings.js @@ -18,5 +18,6 @@ cur_frm.cscript.onload_post_render = function() { wn.require('lib/public/js/lib/jscolor/jscolor.js'); cur_frm.fields_dict.background_color.input.className = 'color'; + cur_frm.fields_dict.top_bar_background.input.className = 'color'; jscolor.bind(); } \ No newline at end of file diff --git a/website/doctype/style_settings/style_settings.txt b/website/doctype/style_settings/style_settings.txt index 5f53441ea8..0063ba975e 100644 --- a/website/doctype/style_settings/style_settings.txt +++ b/website/doctype/style_settings/style_settings.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-10 16:34:32", + "creation": "2013-01-25 11:35:10", "docstatus": 0, - "modified": "2013-01-22 14:57:25", + "modified": "2013-03-07 14:46:51", "modified_by": "Administrator", "owner": "Administrator" }, @@ -24,18 +24,15 @@ "permlevel": 0 }, { - "create": 1, "doctype": "DocPerm", "name": "__common__", "parent": "Style Settings", "parentfield": "permissions", "parenttype": "DocType", - "permlevel": 0, "read": 1, - "report": 1, + "report": 0, "role": "Website Manager", - "submit": 0, - "write": 1 + "submit": 0 }, { "doctype": "DocType", @@ -56,6 +53,20 @@ "fieldtype": "Data", "label": "Background Color" }, + { + "doctype": "DocField", + "fieldname": "top_bar_background", + "fieldtype": "Data", + "label": "Top Bar Background" + }, + { + "description": "000 is black, fff is white", + "doctype": "DocField", + "fieldname": "top_bar_foreground", + "fieldtype": "Select", + "label": "Top Bar Foreground", + "options": "000\nFFF" + }, { "doctype": "DocField", "fieldname": "cb0", @@ -115,6 +126,16 @@ "print_hide": 1 }, { - "doctype": "DocPerm" + "create": 1, + "doctype": "DocPerm", + "permlevel": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1 } ] \ No newline at end of file From b96fef980238cb96b8760170e4b15dd9f2235f68 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 7 Mar 2013 15:35:36 +0530 Subject: [PATCH 06/73] remove cancelled entries from grid report when fetching data based on modified --- accounts/general_ledger.py | 8 +++++--- .../financial_analytics/financial_analytics.js | 8 +++++--- accounts/page/general_ledger/general_ledger.js | 2 +- .../page/purchase_analytics/purchase_analytics.js | 14 ++------------ selling/page/sales_analytics/sales_analytics.js | 12 +----------- 5 files changed, 14 insertions(+), 30 deletions(-) diff --git a/accounts/general_ledger.py b/accounts/general_ledger.py index 215c351421..8e0f4082bc 100644 --- a/accounts/general_ledger.py +++ b/accounts/general_ledger.py @@ -16,7 +16,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import flt, cstr +from webnotes.utils import flt, cstr, now from webnotes.model.doc import Document def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, @@ -109,5 +109,7 @@ def validate_total_debit_credit(total_debit, total_credit): (total_debit - total_credit), raise_exception=1) def set_as_cancel(voucher_type, voucher_no): - webnotes.conn.sql("""update `tabGL Entry` set is_cancelled='Yes' - where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no)) \ No newline at end of file + webnotes.conn.sql("""update `tabGL Entry` set is_cancelled='Yes', + modified=%s, modified_by=%s + where voucher_type=%s and voucher_no=%s""", + (now(), webnotes.session.user, voucher_type, voucher_no)) \ No newline at end of file diff --git a/accounts/page/financial_analytics/financial_analytics.js b/accounts/page/financial_analytics/financial_analytics.js index f0bafdb07b..f7145490a1 100644 --- a/accounts/page/financial_analytics/financial_analytics.js +++ b/accounts/page/financial_analytics/financial_analytics.js @@ -71,9 +71,11 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ setup_filters: function() { var me = this; this._super(); - this.filter_inputs.pl_or_bs.change(function() { - me.filter_inputs.refresh.click(); - }).add_options($.map(wn.report_dump.data["Cost Center"], function(v) {return v.name;})); + this.trigger_refresh_on_change(["pl_or_bs"]); + + this.filter_inputs.pl_or_bs + .add_options($.map(wn.report_dump.data["Cost Center"], function(v) {return v.name;})); + this.setup_plot_check(); }, init_filter_values: function() { diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index 8f6b598d56..4a3f21ea92 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -108,7 +108,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ // filter accounts options by company this.filter_inputs.company.change(function() { me.setup_account_filter(this); - me.filter_inputs.refresh.click(); + me.set_route() }); this.filter_inputs.account.change(function() { diff --git a/buying/page/purchase_analytics/purchase_analytics.js b/buying/page/purchase_analytics/purchase_analytics.js index 7d8171ebbd..fc082eae13 100644 --- a/buying/page/purchase_analytics/purchase_analytics.js +++ b/buying/page/purchase_analytics/purchase_analytics.js @@ -120,19 +120,9 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ setup_filters: function() { var me = this; this._super(); - - this.filter_inputs.value_or_qty.change(function() { - me.filter_inputs.refresh.click(); - }); - - this.filter_inputs.tree_type.change(function() { - me.filter_inputs.refresh.click(); - }); - - this.filter_inputs.based_on.change(function() { - me.filter_inputs.refresh.click(); - }); + this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on"]); + this.show_zero_check() this.setup_plot_check(); }, diff --git a/selling/page/sales_analytics/sales_analytics.js b/selling/page/sales_analytics/sales_analytics.js index 499c6c0156..0b35af5f31 100644 --- a/selling/page/sales_analytics/sales_analytics.js +++ b/selling/page/sales_analytics/sales_analytics.js @@ -122,18 +122,8 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ setup_filters: function() { var me = this; this._super(); - - this.filter_inputs.value_or_qty.change(function() { - me.filter_inputs.refresh.click(); - }); - - this.filter_inputs.tree_type.change(function() { - me.filter_inputs.refresh.click(); - }); - this.filter_inputs.based_on.change(function() { - me.filter_inputs.refresh.click(); - }); + this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on"]); this.show_zero_check() this.setup_plot_check(); From f1e274c8b47d34bdcb70631491a2a5830faa485d Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 7 Mar 2013 16:34:59 +0530 Subject: [PATCH 07/73] when cancelling stock ledger entry, change modified and modified by --- stock/doctype/stock_ledger/stock_ledger.py | 26 ++++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py index 05fc0e0642..5dff992ae4 100644 --- a/stock/doctype/stock_ledger/stock_ledger.py +++ b/stock/doctype/stock_ledger/stock_ledger.py @@ -17,7 +17,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import add_days, cstr, flt, nowdate, cint +from webnotes.utils import add_days, cstr, flt, nowdate, cint, now from webnotes.model.doc import Document from webnotes.model.bean import getlist from webnotes.model.code import get_obj @@ -49,7 +49,7 @@ class DocType: serial_nos = get_valid_serial_nos(d.serial_no) for s in serial_nos: s = s.strip() - sr_war = sql("select warehouse,name from `tabSerial No` where name = '%s'" % (s)) + sr_war = webnotes.conn.sql("select warehouse,name from `tabSerial No` where name = '%s'" % (s)) if not sr_war: msgprint("Serial No %s does not exists"%s, raise_exception = 1) elif not sr_war[0][0]: @@ -81,7 +81,7 @@ class DocType: def set_pur_serial_no_values(self, obj, serial_no, d, s, new_rec, rejected=None): - item_details = sql("""select item_group, warranty_period + item_details = webnotes.conn.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) @@ -112,7 +112,7 @@ class DocType: def update_serial_purchase_details(self, obj, d, serial_no, is_submit, purpose = '', rejected=None): - exists = sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no)) + exists = webnotes.conn.sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no)) if is_submit: if exists and exists[0][2] != 2 and purpose not in ['Material Transfer', 'Sales Return']: msgprint("Serial No: %s already %s" % (serial_no, exists and exists[0][1]), raise_exception = 1) @@ -126,15 +126,15 @@ class DocType: if exists and exists[0][1] == 'Delivered' and exists[0][2] != 2: msgprint("Serial No: %s is already delivered, you can not cancel the document." % serial_no, raise_exception=1) elif purpose == 'Material Transfer': - sql("update `tabSerial No` set status = 'In Store', purchase_document_type = '', purchase_document_no = '', warehouse = '%s' where name = '%s'" % (d.s_warehouse, serial_no)) + webnotes.conn.sql("update `tabSerial No` set status = 'In Store', purchase_document_type = '', purchase_document_no = '', warehouse = '%s' where name = '%s'" % (d.s_warehouse, serial_no)) elif purpose == 'Sales Return': - sql("update `tabSerial No` set status = 'Delivered', purchase_document_type = '', purchase_document_no = '' where name = '%s'" % serial_no) + webnotes.conn.sql("update `tabSerial No` set status = 'Delivered', purchase_document_type = '', purchase_document_no = '' where name = '%s'" % serial_no) else: - sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = null, purchase_rate = 0, supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no) + webnotes.conn.sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = null, purchase_rate = 0, supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no) def check_serial_no_exists(self, serial_no, item_code): - chk = sql("select name, status, docstatus, item_code from `tabSerial No` where name = %s", (serial_no), as_dict=1) + chk = webnotes.conn.sql("select name, status, docstatus, item_code from `tabSerial No` where name = %s", (serial_no), as_dict=1) if not chk: msgprint("Serial No: %s does not exists in the system" % serial_no, raise_exception=1) elif chk and chk[0]['item_code'] != item_code: @@ -169,7 +169,7 @@ class DocType: self.check_serial_no_exists(serial_no, d.item_code) self.set_delivery_serial_no_values(obj, serial_no) else: - sql("update `tabSerial No` set docstatus = 0, status = 'In Store', delivery_document_type = '', delivery_document_no = '', delivery_date = null, customer = null, customer_name = '', delivery_address = '', territory = null where name = '%s'" % (serial_no)) + webnotes.conn.sql("update `tabSerial No` set docstatus = 0, status = 'In Store', delivery_document_type = '', delivery_document_no = '', delivery_date = null, customer = null, customer_name = '', delivery_address = '', territory = null where name = '%s'" % (serial_no)) def update_serial_record(self, obj, fname, is_submit = 1, is_incoming = 0): @@ -202,8 +202,10 @@ class DocType: if v.get('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'])) + webnotes.conn.sql("""update `tabStock Ledger Entry` set is_cancelled='Yes', + modified=%s, modified_by=%s + where voucher_no=%s and voucher_type=%s""", + (now(), webnotes.session.user, v['voucher_no'], v['voucher_type'])) if v.get("actual_qty"): sle_id = self.make_entry(v) @@ -230,5 +232,5 @@ class DocType: """ Repost everything! """ - for wh in sql("select name from tabWarehouse"): + for wh in webnotes.conn.sql("select name from tabWarehouse"): get_obj('Warehouse', wh[0]).repost_stock() From 4f129239030db439a7eb04b23d6339ad9c25701d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 7 Mar 2013 18:49:50 +0530 Subject: [PATCH 08/73] fixes in sales team percentage validation --- selling/doctype/sales_common/sales_common.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index 47d139f955..12ae4a8c90 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -341,12 +341,10 @@ class DocType(TransactionBase): # ======================================================================== # it indicates % contribution of sales person in sales def get_allocated_sum(self,obj): - sum = 0 - for d in getlist(obj.doclist,'sales_team'): - sum += flt(d.allocated_percentage) - if (flt(sum) != 100) and getlist(obj.doclist,'sales_team'): - msgprint("Total Allocated % of Sales Persons should be 100%") - raise Exception + sales_team_list = obj.doclist.get({"parentfield": "sales_team"}) + total_allocation = sum([flt(d.allocated_percentage) for d in sales_team_list]) + if sales_team_list and total_allocation != 100.0: + msgprint("Total Allocated %% of Sales Persons should be 100%", raise_exception=True) # Check Conversion Rate (i.e. it will not allow conversion rate to be 1 for Currency other than default currency set in Global Defaults) # =========================================================================== From 676a568f5a13fd469699412c8b0b5381352a7380 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 7 Mar 2013 18:51:10 +0530 Subject: [PATCH 09/73] added blogger, updated style and blogs --- website/css/website.css | 19 +++- website/doctype/blog/blog.py | 7 ++ website/doctype/blog/blog.txt | 27 +++++- website/doctype/blogger/__init__.py | 0 website/doctype/blogger/blogger.py | 18 ++++ website/doctype/blogger/blogger.txt | 95 +++++++++++++++++++ .../style_settings/custom_template.css | 32 ++++++- .../doctype/style_settings/style_settings.js | 1 + .../doctype/style_settings/style_settings.py | 30 +++++- .../doctype/style_settings/style_settings.txt | 65 ++++++++++--- website/helpers/blog.py | 46 ++++----- website/page/website_home/website_home.js | 5 + website/templates/html/blog_page.html | 41 +++++--- website/templates/html/outer.html | 2 +- website/templates/js/blog.js | 28 ++++-- website/templates/pages/blog.html | 3 +- 16 files changed, 341 insertions(+), 78 deletions(-) create mode 100644 website/doctype/blogger/__init__.py create mode 100644 website/doctype/blogger/blogger.py create mode 100644 website/doctype/blogger/blogger.txt diff --git a/website/css/website.css b/website/css/website.css index a0f4e1b3ca..dc5b9670b3 100644 --- a/website/css/website.css +++ b/website/css/website.css @@ -1,9 +1,4 @@ div.outer { - -moz-box-shadow: 0px 0px 3px rgba(0,0,0,0.9); - -webkit-box-shadow: 0px 0px 3px rgba(0,0,0,0.9); - box-shadow: 0px 0px 3px rgba(0,0,0,0.9); - background-color: #fff; - border-radius: 5px; padding: 30px; margin: 30px -30px 10px -30px; min-height: 400px; @@ -24,6 +19,8 @@ footer { border: 0px; border-bottom: 1px solid #ddd; border-radius: 0px; + padding-right: 30px; + padding-left: 30px; } p, li { @@ -98,6 +95,18 @@ p, li { width: 30px; } +.avatar-medium { + margin-right: 5px; + width: 48px; + height: 48px; + border-radius: 48px; + -moz-border-radius: 48px; + -webkit-border-radius: 48px; +} +.avatar-medium img { + width: 48px; +} + .avatar-large { margin-right: 10px; width: 72px; diff --git a/website/doctype/blog/blog.py b/website/doctype/blog/blog.py index cfc0ca643e..2e96f4868b 100644 --- a/website/doctype/blog/blog.py +++ b/website/doctype/blog/blog.py @@ -27,6 +27,9 @@ class DocType: from website.utils import page_name self.doc.name = page_name(self.doc.title) + def validate(self): + self.doc.blog_intro = self.doc.blog_intro[:140] + def on_update(self): from website.utils import update_page_name update_page_name(self.doc, self.doc.title) @@ -66,6 +69,10 @@ class DocType: self.doc.full_name = get_fullname(self.doc.owner) self.doc.updated = global_date_format(self.doc.creation) self.doc.content_html = self.doc.content + if self.doc.blogger: + self.doc.blogger_info = webnotes.doc("blogger", self.doc.blogger).fields + if self.doc.blogger_info.avatar and not "/" in self.doc.blogger_info.avatar: + self.doc.blogger_info.avatar = "files/" + self.doc.blogger_info.avatar comment_list = webnotes.conn.sql("""\ select comment, comment_by_fullname, creation diff --git a/website/doctype/blog/blog.txt b/website/doctype/blog/blog.txt index af9606a71b..cdc7018f1e 100644 --- a/website/doctype/blog/blog.txt +++ b/website/doctype/blog/blog.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-25 11:35:09", "docstatus": 0, - "modified": "2013-02-21 16:54:04", + "modified": "2013-03-07 16:32:13", "modified_by": "Administrator", "owner": "Administrator" }, @@ -50,18 +50,37 @@ "label": "Published" }, { - "description": "Description for listing page, in plain text, only a couple of lines.", + "doctype": "DocField", + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "blogger", + "fieldtype": "Link", + "label": "Blogger", + "options": "Blogger", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "section_break_5", + "fieldtype": "Section Break" + }, + { + "description": "Description for listing page, in plain text, only a couple of lines. (max 140 characters)", "doctype": "DocField", "fieldname": "blog_intro", "fieldtype": "Small Text", - "label": "Blog Intro" + "label": "Blog Intro", + "reqd": 1 }, { "doctype": "DocField", "fieldname": "content", "fieldtype": "Text Editor", "label": "Content", - "reqd": 0 + "reqd": 1 }, { "doctype": "DocField", diff --git a/website/doctype/blogger/__init__.py b/website/doctype/blogger/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/website/doctype/blogger/blogger.py b/website/doctype/blogger/blogger.py new file mode 100644 index 0000000000..28d0f29b3e --- /dev/null +++ b/website/doctype/blogger/blogger.py @@ -0,0 +1,18 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl + + def on_update(self): + "if profile is set, then update all older blogs" + if self.doc.profile: + for blog in webnotes.conn.sql_list("""select name from tabBlog where owner=%s + and ifnull(blogger,'')=''""", self.doc.profile): + b = webnotes.bean("Blog", blog) + b.blogger = self.doc.name + b.save() + diff --git a/website/doctype/blogger/blogger.txt b/website/doctype/blogger/blogger.txt new file mode 100644 index 0000000000..01e0ceae20 --- /dev/null +++ b/website/doctype/blogger/blogger.txt @@ -0,0 +1,95 @@ +[ + { + "creation": "2013-03-07 16:28:19", + "docstatus": 0, + "modified": "2013-03-07 16:33:37", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "allow_attach": 1, + "autoname": "field:short_name", + "description": "Profile of a Blogger", + "doctype": "DocType", + "document_type": "Master", + "max_attachments": 1, + "module": "Website", + "name": "__common__" + }, + { + "doctype": "DocField", + "name": "__common__", + "parent": "Blogger", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0 + }, + { + "doctype": "DocPerm", + "name": "__common__", + "parent": "Blogger", + "parentfield": "permissions", + "parenttype": "DocType", + "permlevel": 0, + "read": 1, + "write": 1 + }, + { + "doctype": "DocType", + "name": "Blogger" + }, + { + "description": "Will be used in url (usually first name).", + "doctype": "DocField", + "fieldname": "short_name", + "fieldtype": "Data", + "label": "Short Name", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "full_name", + "fieldtype": "Data", + "label": "Full Name", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "profile", + "fieldtype": "Link", + "label": "Profile", + "options": "Profile" + }, + { + "doctype": "DocField", + "fieldname": "bio", + "fieldtype": "Small Text", + "label": "Bio" + }, + { + "doctype": "DocField", + "fieldname": "avatar", + "fieldtype": "Select", + "label": "Avatar", + "options": "attach_files:" + }, + { + "doctype": "DocField", + "fieldname": "file_list", + "fieldtype": "Text", + "hidden": 1, + "label": "File List", + "no_copy": 1, + "print_hide": 1 + }, + { + "create": 1, + "doctype": "DocPerm", + "role": "Website Manager" + }, + { + "doctype": "DocPerm", + "match": "owner:profile", + "role": "Blogger" + } +] \ No newline at end of file diff --git a/website/doctype/style_settings/custom_template.css b/website/doctype/style_settings/custom_template.css index 52897447bd..d5283ffbce 100644 --- a/website/doctype/style_settings/custom_template.css +++ b/website/doctype/style_settings/custom_template.css @@ -1,3 +1,7 @@ +{% if doc.at_import %} +{{ doc.at_import }} +{% endif %} + body { {% if doc.background_image %} background: url("../files/{{ doc.background_image }}") repeat; @@ -7,8 +11,8 @@ body { {% else %} background-color: #edede7; {% endif %} -{% if doc.font %} - font-family: '{{ doc.font }}', Verdana, Sans !important; +{% if doc.font or doc.google_web_font_for_text %} + font-family: '{{ doc.google_web_font_for_text or doc.font }}', Verdana, Sans !important; {% endif %} {% if doc.font_size %} font-size: {{ doc.font_size }} !important; @@ -21,14 +25,32 @@ body { } {% endif %} -{% if doc.heading_font %} +div.outer { + background-color: #{{ doc.page_background or "fff" }}; +} + +{% if doc.google_web_font_for_heading or doc.heading_font %} h1, h2, h3, h4, h5 { - font-family: '{{ doc.heading_font}}', Arial, 'Helvetica Neue' !important; + font-family: '{{ doc.google_web_font_for_heading or doc.heading_font }}', Arial, 'Helvetica Neue' !important; } {% endif %} -/* Bootstrap Navbar */ +{% if doc.page_border %} +/* Page Border*/ +div.outer { + -moz-box-shadow: 0px 0px 3px rgba(0,0,0,0.9); + -webkit-box-shadow: 0px 0px 3px rgba(0,0,0,0.9); + box-shadow: 0px 0px 3px rgba(0,0,0,0.9); + border-radius: 5px; +} +{% else %} +div.web-footer { + border-top: 1px solid #eee; + padding-top: 10px; +} +{% endif %} +/* Bootstrap Navbar */ .navbar-inverse .navbar-inner { background-color: #{{ doc.top_bar_background or "444"}}; background-repeat: repeat-x; diff --git a/website/doctype/style_settings/style_settings.js b/website/doctype/style_settings/style_settings.js index 6a17db99ee..e8ee908799 100644 --- a/website/doctype/style_settings/style_settings.js +++ b/website/doctype/style_settings/style_settings.js @@ -18,6 +18,7 @@ cur_frm.cscript.onload_post_render = function() { wn.require('lib/public/js/lib/jscolor/jscolor.js'); cur_frm.fields_dict.background_color.input.className = 'color'; + cur_frm.fields_dict.page_background.input.className = 'color'; cur_frm.fields_dict.top_bar_background.input.className = 'color'; jscolor.bind(); } \ No newline at end of file diff --git a/website/doctype/style_settings/style_settings.py b/website/doctype/style_settings/style_settings.py index 51799483d4..95bba74182 100644 --- a/website/doctype/style_settings/style_settings.py +++ b/website/doctype/style_settings/style_settings.py @@ -29,10 +29,7 @@ class DocType: 'custom_template.css'), 'r') as f: temp = Template(f.read()) - if not self.doc.font_size: - self.doc.font_size = '13px' - - self.doc.small_font_size = str(int(self.doc.font_size[:-2])-2) + 'px' + self.prepare() self.doc.custom_css = temp.render(doc = self.doc) if self.doc.add_css: @@ -41,7 +38,30 @@ class DocType: from webnotes.sessions import clear_cache clear_cache('Guest') - del self.doc.fields['small_font_size'] + for f in ["small_font_size", "at_import"]: + if f in self.doc.fields: + del self.doc.fields[f] + + def prepare(self): + if not self.doc.font_size: + self.doc.font_size = '13px' + + self.doc.small_font_size = str(int(self.doc.font_size[:-2])-2) + 'px' + self.doc.page_border = int(self.doc.page_border) + + fonts = [] + if self.doc.google_web_font_for_heading: + fonts.append(self.doc.google_web_font_for_heading) + if self.doc.google_web_font_for_text: + fonts.append(self.doc.google_web_font_for_text) + + fonts = list(set(fonts)) + + self.doc.at_import = "" + for f in fonts: + self.doc.at_import += "\n@import url(http://fonts.googleapis.com/css?family=%s);" % f.replace(" ", "+") + + def on_update(self): """rebuild pages""" diff --git a/website/doctype/style_settings/style_settings.txt b/website/doctype/style_settings/style_settings.txt index 0063ba975e..ebdc35a181 100644 --- a/website/doctype/style_settings/style_settings.txt +++ b/website/doctype/style_settings/style_settings.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-25 11:35:10", "docstatus": 0, - "modified": "2013-03-07 14:46:51", + "modified": "2013-03-07 16:06:22", "modified_by": "Administrator", "owner": "Administrator" }, @@ -38,6 +38,12 @@ "doctype": "DocType", "name": "Style Settings" }, + { + "doctype": "DocField", + "fieldname": "color", + "fieldtype": "Section Break", + "label": "Color" + }, { "description": "If image is selected, color will be ignored (attach first)", "doctype": "DocField", @@ -53,6 +59,25 @@ "fieldtype": "Data", "label": "Background Color" }, + { + "doctype": "DocField", + "fieldname": "page_background", + "fieldtype": "Data", + "label": "Page Background" + }, + { + "doctype": "DocField", + "fieldname": "page_border", + "fieldtype": "Check", + "label": "Page Border" + }, + { + "doctype": "DocField", + "fieldname": "cb0", + "fieldtype": "Column Break", + "print_width": "50%", + "width": "50%" + }, { "doctype": "DocField", "fieldname": "top_bar_background", @@ -69,31 +94,49 @@ }, { "doctype": "DocField", - "fieldname": "cb0", - "fieldtype": "Column Break", - "print_width": "50%", - "width": "50%" + "fieldname": "fonts", + "fieldtype": "Section Break", + "label": "Fonts" + }, + { + "doctype": "DocField", + "fieldname": "heading_font", + "fieldtype": "Select", + "label": "Font (Heading)", + "options": "\nHelvetica Neue\nLucida Grande\nVerdana\nArial\nGeorgia\nTahoma\nLato\nOpen Sans" }, { "doctype": "DocField", "fieldname": "font", "fieldtype": "Select", - "label": "Font", + "label": "Font (Text)", "options": "\nHelvetica Neue\nLucida Grande\nVerdana\nArial\nGeorgia\nTahoma" }, { "doctype": "DocField", "fieldname": "font_size", "fieldtype": "Select", - "label": "Font Size", + "label": "Font Size (Text)", "options": "\n12px\n13px\n14px\n15px\n16px" }, { "doctype": "DocField", - "fieldname": "heading_font", - "fieldtype": "Select", - "label": "Heading Font", - "options": "\nHelvetica Neue\nLucida Grande\nVerdana\nArial\nGeorgia\nTahoma\nLato\nOpen Sans" + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "description": "Add the name of Google Web Font e.g. \"Open Sans\"", + "doctype": "DocField", + "fieldname": "google_web_font_for_heading", + "fieldtype": "Data", + "label": "Google Web Font (Heading)" + }, + { + "description": "Add the name of Google Web Font e.g. \"Open Sans\"", + "doctype": "DocField", + "fieldname": "google_web_font_for_text", + "fieldtype": "Data", + "label": "Google Web Font (Text)" }, { "doctype": "DocField", diff --git a/website/helpers/blog.py b/website/helpers/blog.py index 2bff6e5708..dcb15cbd17 100644 --- a/website/helpers/blog.py +++ b/website/helpers/blog.py @@ -6,39 +6,39 @@ import webnotes import website.utils @webnotes.whitelist(allow_guest=True) -def get_blog_list(args=None): - """ - args = { - 'start': 0, - } - """ +def get_blog_list(start=0, by=None): import webnotes - - if not args: args = webnotes.form_dict - + condition = "" + if by: + condition = " and t1.blogger='%s'" % by.replace("'", "\'") query = """\ select - name, page_name, content, owner, creation as creation, - title, (select count(name) from `tabComment` where - comment_doctype='Blog' and comment_docname=`tabBlog`.name) as comments - from `tabBlog` - where ifnull(published,0)=1 + t1.title, t1.name, t1.page_name, t1.creation as creation, + ifnull(t1.blog_intro, t1.content) as content, + t2.full_name, t2.avatar, t1.blogger, + (select count(name) from `tabComment` where + comment_doctype='Blog' and comment_docname=t1.name) as comments + from `tabBlog` t1, `tabBlogger` t2 + where ifnull(t1.published,0)=1 + and t1.blogger = t2.name + %(condition)s order by creation desc, name asc - limit %s, 5""" % args.start + limit %(start)s, 5""" % {"start": start, "condition": condition} - result = webnotes.conn.sql(query, args, as_dict=1) + result = webnotes.conn.sql(query, as_dict=1) # strip html tags from content import webnotes.utils for res in result: from webnotes.utils import global_date_format, get_fullname - res['full_name'] = get_fullname(res['owner']) res['published'] = global_date_format(res['creation']) if not res['content']: res['content'] = website.utils.get_html(res['page_name']) - res['content'] = split_blog_content(res['content']) - + res['content'] = res['content'][:140] + if res.avatar and not "/" in res.avatar: + res.avatar = "files/" + res.avatar + return result @webnotes.whitelist(allow_guest=True) @@ -115,10 +115,4 @@ def get_blog_content(blog_page_name): import webnotes.utils content = webnotes.utils.escape_html(content) return content - -def split_blog_content(content): - content = content.split("") - content = len(content) > 1 and content[1] or content[0] - content = content.split("") - content = content[0] - return content \ No newline at end of file + \ No newline at end of file diff --git a/website/page/website_home/website_home.js b/website/page/website_home/website_home.js index c6b2253df1..d770586070 100644 --- a/website/page/website_home/website_home.js +++ b/website/page/website_home/website_home.js @@ -21,6 +21,11 @@ wn.module_page["Website"] = [ description: wn._("Embed image slideshows in website pages."), doctype:"Website Slideshow" }, + { + label: wn._("Blogger"), + description: wn._("Profile of a blog writer."), + doctype:"Blogger" + }, ] }, { diff --git a/website/templates/html/blog_page.html b/website/templates/html/blog_page.html index 24dd8d7acc..6f7796b0b6 100644 --- a/website/templates/html/blog_page.html +++ b/website/templates/html/blog_page.html @@ -13,17 +13,33 @@

{{ title }}

-
By {{ full_name }} on {{ updated }}
+
+ {{ blogger_info and blogger_info.full_name or full_name }} wrote this on {{ updated }}

{{ content_html }} - + {% if blogger_info %} +
+
+
+
+ +
+
+
+

{{ blogger_info.full_name }}

+

{{ blogger_info.bio }}

+

+ All posts by {{ blogger_info.full_name }}

+
+
+ {% endif %}

Comments


{% if not comment_list %} -
+

Be the first one to comment

{% endif %} @@ -32,22 +48,19 @@
+
+ Show posts by everyone

{% endblock %} \ No newline at end of file diff --git a/website/templates/html/outer.html b/website/templates/html/outer.html index a8b73ad122..ab6a69eb23 100644 --- a/website/templates/html/outer.html +++ b/website/templates/html/outer.html @@ -10,7 +10,7 @@

', b)).appendTo($wrap); }); blog.start += (data.length || 0); - if(!data.length) { + if(!data.length || data.length < 20) { if(blog.start) { $("#next-page").toggle(false) - .parent().append("
Nothing more to show.
"); + .parent().append("
Nothing more to show.
"); } else { $("#next-page").toggle(false) .parent().append("
No blogs written yet.
"); diff --git a/website/templates/pages/blog.html b/website/templates/pages/blog.html index 05302c63de..cfdd536696 100644 --- a/website/templates/pages/blog.html +++ b/website/templates/pages/blog.html @@ -14,6 +14,9 @@

Blog


+
+
+
From 8c7234f2704fdaf45562b15329183cb6efee4ae2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 11 Mar 2013 16:32:33 +0530 Subject: [PATCH 30/73] aii: gl_entries for sales invoice --- .../doctype/sales_invoice/sales_invoice.py | 163 +++++++++----- .../sales_invoice/test_sales_invoice.py | 201 +++++++++++++++++- .../sales_invoice_item/sales_invoice_item.txt | 56 ++++- accounts/report/gross_profit/gross_profit.py | 2 +- controllers/accounts_controller.py | 4 +- controllers/selling_controller.py | 25 ++- home/page/latest_updates/latest_updates.js | 10 +- .../march_2013/p03_update_buying_amount.py | 10 + .../doctype/sales_person/test_sales_person.py | 14 ++ stock/doctype/delivery_note/delivery_note.py | 66 ++---- .../delivery_note/test_delivery_note.py | 2 + .../delivery_note_item/delivery_note_item.txt | 36 +++- stock/doctype/item/test_item.py | 19 ++ stock/stock_ledger.py | 2 - stock/utils.py | 13 +- 15 files changed, 484 insertions(+), 139 deletions(-) create mode 100644 patches/march_2013/p03_update_buying_amount.py diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index b31d54919c..597e2ff1aa 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -25,6 +25,8 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import _, msgprint +from stock.utils import get_buying_amount, get_sales_bom + session = webnotes.session month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12} @@ -95,7 +97,8 @@ class DocType(SellingController): if not self.doc.recurring_id: get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self) - + + self.set_buying_amount() self.check_prev_docstatus() get_obj("Sales Common").update_prevdoc_detail(1,self) @@ -126,7 +129,7 @@ class DocType(SellingController): self.check_next_docstatus() sales_com_obj.update_prevdoc_detail(0, self) - self.make_gl_entries(is_cancel=1) + self.make_gl_entries() def on_update_after_submit(self): self.validate_recurring_invoice() @@ -619,8 +622,7 @@ class DocType(SellingController): 'is_cancelled' : (update_stock==1) and 'No' or 'Yes', 'batch_no' : cstr(d['batch_no']), 'serial_no' : d['serial_no'] - }) - + }) def update_stock_ledger(self, update_stock): self.values = [] @@ -648,14 +650,29 @@ class DocType(SellingController): return ret - def make_gl_entries(self, is_cancel=0): - from accounts.general_ledger import make_gl_entries - gl_entries = [] - auto_inventory_accounting = webnotes.conn.get_value("Global Defaults", None, - "automatic_inventory_accounting") - abbr = self.get_company_abbr() + def make_gl_entries(self): + from accounts.general_ledger import make_gl_entries, merge_similar_entries - # parent's gl entry + gl_entries = [] + + self.make_customer_gl_entry(gl_entries) + + self.make_tax_gl_entries(gl_entries) + + self.make_item_gl_entries(gl_entries) + + # merge gl entries before adding pos entries + gl_entries = merge_similar_entries(gl_entries) + + self.make_pos_gl_entries(gl_entries) + + update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account and 'No' or 'Yes' + + if gl_entries: + make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2), + update_outstanding=update_outstanding, merge_entries=False) + + def make_customer_gl_entry(self, gl_entries): if self.doc.grand_total: gl_entries.append( self.get_gl_dict({ @@ -665,10 +682,10 @@ class DocType(SellingController): "remarks": self.doc.remarks, "against_voucher": self.doc.name, "against_voucher_type": self.doc.doctype, - }, is_cancel) + }) ) - - # tax table gl entries + + def make_tax_gl_entries(self, gl_entries): for tax in self.doclist.get({"parentfield": "other_charges"}): if flt(tax.tax_amount): gl_entries.append( @@ -678,11 +695,21 @@ class DocType(SellingController): "credit": flt(tax.tax_amount), "remarks": self.doc.remarks, "cost_center": tax.cost_center_other_charges - }, is_cancel) + }) ) - + + def make_item_gl_entries(self, gl_entries): # item gl entries - for item in getlist(self.doclist, 'entries'): + auto_inventory_accounting = \ + cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) + + if auto_inventory_accounting: + if cint(self.doc.is_pos) and cint(self.doc.update_stock): + stock_account = self.get_stock_in_hand_account() + else: + stock_account = "Stock Delivered But Not Billed - %s" % (self.company_abbr,) + + for item in self.doclist.get({"parentfield": "entries"}): # income account gl entries if flt(item.amount): gl_entries.append( @@ -692,35 +719,31 @@ class DocType(SellingController): "credit": item.amount, "remarks": self.doc.remarks, "cost_center": item.cost_center - }, is_cancel) + }) ) - # if auto inventory accounting enabled and stock item, - # then do stock related gl entries - if auto_inventory_accounting and item.delivery_note and \ - webnotes.conn.get_value("Item", item.item_code, "is_stock_item")=="Yes": - # to-do - purchase_rate = webnotes.conn.get_value("Delivery Note Item", - item.dn_detail, "purchase_rate") - valuation_amount = purchase_rate * item.qty - # expense account gl entries - if flt(valuation_amount): - gl_entries.append( - self.get_gl_dict({ - "account": item.expense_account, - "against": "Stock Delivered But Not Billed - %s" % (abbr,), - "debit": valuation_amount, - "remarks": self.doc.remarks or "Accounting Entry for Stock" - }, is_cancel) - ) - gl_entries.append( - self.get_gl_dict({ - "account": "Stock Delivered But Not Billed - %s" % (abbr,), - "against": item.expense_account, - "credit": valuation_amount, - "remarks": self.doc.remarks or "Accounting Entry for Stock" - }, is_cancel) - ) - if self.doc.is_pos and self.doc.cash_bank_account and self.doc.paid_amount: + + # expense account gl entries + if auto_inventory_accounting and flt(item.buying_amount): + gl_entries.append( + self.get_gl_dict({ + "account": item.expense_account, + "against": stock_account, + "debit": item.buying_amount, + "remarks": self.doc.remarks or "Accounting Entry for Stock", + "cost_center": item.cost_center + }) + ) + gl_entries.append( + self.get_gl_dict({ + "account": stock_account, + "against": item.expense_account, + "credit": item.buying_amount, + "remarks": self.doc.remarks or "Accounting Entry for Stock" + }) + ) + + def make_pos_gl_entries(self, gl_entries): + if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount: # POS, make payment entries gl_entries.append( self.get_gl_dict({ @@ -730,7 +753,7 @@ class DocType(SellingController): "remarks": self.doc.remarks, "against_voucher": self.doc.name, "against_voucher_type": self.doc.doctype, - }, is_cancel) + }) ) gl_entries.append( self.get_gl_dict({ @@ -738,7 +761,7 @@ class DocType(SellingController): "against": self.doc.debit_to, "debit": self.doc.paid_amount, "remarks": self.doc.remarks, - }, is_cancel) + }) ) # write off entries, applicable if only pos if self.doc.write_off_account and self.doc.write_off_amount: @@ -750,7 +773,7 @@ class DocType(SellingController): "remarks": self.doc.remarks, "against_voucher": self.doc.name, "against_voucher_type": self.doc.doctype, - }, is_cancel) + }) ) gl_entries.append( self.get_gl_dict({ @@ -759,23 +782,45 @@ class DocType(SellingController): "debit": self.doc.write_off_amount, "remarks": self.doc.remarks, "cost_center": self.doc.write_off_cost_center - }, is_cancel) + }) ) + + def set_buying_amount(self): + if cint(self.doc.is_pos) and cint(self.doc.update_stock): + stock_ledger_entries = self.get_stock_ledger_entries() + item_sales_bom = get_sales_bom() + else: + stock_ledger_entries = item_sales_bom = None + + for item in self.doclist.get({"parentfield": "entries"}): + if item.item_code in self.stock_items: + item.buying_amount = self.get_item_buying_amount(item, stock_ledger_entries, + item_sales_bom) + webnotes.conn.set_value("Sales Invoice Item", item.name, + "buying_amount", item.buying_amount) + + def get_item_buying_amount(self, item, stock_ledger_entries, item_sales_bom): + item_buying_amount = 0 + if stock_ledger_entries: + # is pos and update stock + item_buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty, + self.doc.doctype, self.doc.name, item.name, stock_ledger_entries, item_sales_bom) + elif item.delivery_note and item.dn_detail: + # against delivery note + dn_item = webnotes.conn.get_value("Delivery Note Item", item.dn_detail, + ["buying_amount", "qty"], as_dict=1) + item_buying_rate = flt(dn_item.buying_amount) / flt(dn_item.qty) + item_buying_amount = item_buying_rate * flt(item.qty) - - update_outstanding = self.doc.is_pos and self.doc.write_off_account and 'No' or 'Yes' - merge_entries=cint(self.doc.is_pos)!=1 and 1 or 0 - if gl_entries: - make_gl_entries(gl_entries, cancel=is_cancel, - update_outstanding=update_outstanding, merge_entries=merge_entries) - + return item_buying_amount + def update_c_form(self): """Update amended id in C-form""" if self.doc.c_form_no and self.doc.amended_from: webnotes.conn.sql("""update `tabC-Form Invoice Detail` set invoice_no = %s, - invoice_date = %s, territory = %s, net_total = %s, - grand_total = %s where invoice_no = %s and parent = %s""", (self.doc.name, self.doc.amended_from, self.doc.c_form_no)) - + invoice_date = %s, territory = %s, net_total = %s, + grand_total = %s where invoice_no = %s and parent = %s""", + (self.doc.name, self.doc.amended_from, self.doc.c_form_no)) def check_next_docstatus(self): submit_jv = webnotes.conn.sql("select t1.name from `tabJournal Voucher` t1,`tabJournal Voucher Detail` t2 where t1.name = t2.parent and t2.against_invoice = '%s' and t1.docstatus = 1" % (self.doc.name)) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 1f165f0c33..84eddea218 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -53,16 +53,17 @@ class TestSalesInvoice(unittest.TestCase): "Batched for Billing") def test_sales_invoice_gl_entry_without_aii(self): + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + si = webnotes.bean(webnotes.copy_doclist(test_records[1])) si.insert() si.submit() - webnotes.defaults.set_global_default("auto_inventory_accounting", 0) - gl_entries = webnotes.conn.sql("""select account, debit, credit from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s order by account asc""", si.doc.name, as_dict=1) self.assertTrue(gl_entries) + expected_values = sorted([ [si.doc.debit_to, 630.0, 0.0], [test_records[1][1]["income_account"], 0.0, 500.0], @@ -74,8 +75,20 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(expected_values[i][0], gle.account) self.assertEquals(expected_values[i][1], gle.debit) self.assertEquals(expected_values[i][2], gle.credit) + + # cancel + si.cancel() + + gle_count = webnotes.conn.sql("""select count(name) from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=%s + and ifnull(is_cancelled, 'No') = 'Yes' + order by account asc""", si.doc.name) + + self.assertEquals(gle_count[0][0], 8) + + def test_sales_invoice_gl_entry_with_aii_delivery_note(self): + webnotes.conn.sql("delete from `tabStock Ledger Entry`") - def test_sales_invoice_gl_entry_with_aii(self): webnotes.defaults.set_global_default("auto_inventory_accounting", 1) self._insert_purchase_receipt() @@ -83,8 +96,10 @@ class TestSalesInvoice(unittest.TestCase): si_against_dn = webnotes.copy_doclist(test_records[1]) si_against_dn[1]["delivery_note"] = dn.doc.name - si = webnotes.bean(si_against_dn) + si_against_dn[1]["dn_detail"] = dn.doclist[1].name + si = webnotes.bean(si_against_dn) si.insert() + si.submit() gl_entries = webnotes.conn.sql("""select account, debit, credit @@ -100,15 +115,154 @@ class TestSalesInvoice(unittest.TestCase): ["Stock Delivered But Not Billed - _TC", 0.0, 375.0], [test_records[1][1]["expense_account"], 375.0, 0.0] ]) - print expected_values - print gl_entries for i, gle in enumerate(gl_entries): self.assertEquals(expected_values[i][0], gle.account) self.assertEquals(expected_values[i][1], gle.debit) self.assertEquals(expected_values[i][2], gle.credit) + si.cancel() + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + and ifnull(is_cancelled, 'No') = 'No' + order by account asc, name asc""", si.doc.name, as_dict=1) + + expected_values = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [si.doc.debit_to, 0.0, 630.0], + [test_records[1][1]["income_account"], 0.0, 500.0], + [test_records[1][1]["income_account"], 500.0, 0.0], + [test_records[1][2]["account_head"], 0.0, 80.0], + [test_records[1][2]["account_head"], 80.0, 0.0], + [test_records[1][3]["account_head"], 0.0, 50.0], + [test_records[1][3]["account_head"], 50.0, 0.0], + ["Stock Delivered But Not Billed - _TC", 0.0, 375.0], + ["Stock Delivered But Not Billed - _TC", 375.0, 0.0], + [test_records[1][1]["expense_account"], 375.0, 0.0], + [test_records[1][1]["expense_account"], 0.0, 375.0] + + ]) + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + def test_pos_gl_entry_with_aii(self): + webnotes.conn.sql("delete from `tabStock Ledger Entry`") webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + self._insert_purchase_receipt() + self._insert_pos_settings() + + pos = webnotes.copy_doclist(test_records[1]) + pos[0]["is_pos"] = 1 + pos[0]["update_stock"] = 1 + pos[0]["posting_time"] = "12:05" + pos[0]["cash_bank_account"] = "_Test Account Bank Account - _TC" + pos[0]["paid_amount"] = 600.0 + + si = webnotes.bean(pos) + si.insert() + si.submit() + + # check stock ledger entries + sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where voucher_type = 'Sales Invoice' and voucher_no = %s""", si.doc.name, as_dict=1)[0] + self.assertTrue(sle) + self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty], + ["_Test Item", "_Test Warehouse", -5.0]) + + # check gl entries + stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company", + "stock_in_hand_account") + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc, debit asc""", si.doc.name, as_dict=1) + self.assertTrue(gl_entries) + + expected_gl_entries = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [test_records[1][1]["income_account"], 0.0, 500.0], + [test_records[1][2]["account_head"], 0.0, 80.0], + [test_records[1][3]["account_head"], 0.0, 50.0], + [stock_in_hand_account, 0.0, 375.0], + [test_records[1][1]["expense_account"], 375.0, 0.0], + [si.doc.debit_to, 0.0, 600.0], + ["_Test Account Bank Account - _TC", 600.0, 0.0] + ]) + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_gl_entries[i][0], gle.account) + self.assertEquals(expected_gl_entries[i][1], gle.debit) + self.assertEquals(expected_gl_entries[i][2], gle.credit) + + # cancel + si.cancel() + gl_count = webnotes.conn.sql("""select count(name) + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + and ifnull(is_cancelled, 'No') = 'Yes' + order by account asc, name asc""", si.doc.name) + + self.assertEquals(gl_count[0][0], 16) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + def test_sales_invoice_gl_entry_with_aii_no_item_code(self): + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + si_copy = webnotes.copy_doclist(test_records[1]) + si_copy[1]["item_code"] = None + si = webnotes.bean(si_copy) + si.insert() + si.submit() + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc""", si.doc.name, as_dict=1) + self.assertTrue(gl_entries) + + expected_values = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [test_records[1][1]["income_account"], 0.0, 500.0], + [test_records[1][2]["account_head"], 0.0, 80.0], + [test_records[1][3]["account_head"], 0.0, 50.0], + ]) + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + si_copy = webnotes.copy_doclist(test_records[1]) + si_copy[1]["item_code"] = "_Test Non Stock Item" + si = webnotes.bean(si_copy) + si.insert() + si.submit() + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc""", si.doc.name, as_dict=1) + self.assertTrue(gl_entries) + + expected_values = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [test_records[1][1]["income_account"], 0.0, 500.0], + [test_records[1][2]["account_head"], 0.0, 80.0], + [test_records[1][3]["account_head"], 0.0, 50.0], + ]) + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + def _insert_purchase_receipt(self): from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \ @@ -126,6 +280,23 @@ class TestSalesInvoice(unittest.TestCase): dn.submit() return dn + def _insert_pos_settings(self): + ps = webnotes.bean([ + { + "cash_bank_account": "_Test Account Bank Account - _TC", + "company": "_Test Company", + "conversion_rate": 1.0, + "cost_center": "_Test Cost Center - _TC", + "currency": "INR", + "doctype": "POS Setting", + "income_account": "_Test Account Bank Account - _TC", + "price_list_name": "_Test Price List", + "territory": "_Test Territory", + "warehouse": "_Test Warehouse" + } + ]) + ps.insert() + test_dependencies = ["Journal Voucher"] test_records = [ @@ -178,7 +349,19 @@ test_records = [ "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", "tax_amount": 31.8, - } + }, + { + "parentfield": "sales_team", + "doctype": "Sales Team", + "sales_person": "_Test Sales Person 1", + "allocated_percentage": 65.5, + }, + { + "parentfield": "sales_team", + "doctype": "Sales Team", + "sales_person": "_Test Sales Person 2", + "allocated_percentage": 34.5, + }, ], [ { @@ -207,13 +390,13 @@ test_records = [ "description": "_Test Item", "doctype": "Sales Invoice Item", "parentfield": "entries", - "qty": 1.0, + "qty": 5.0, "basic_rate": 500.0, "amount": 500.0, "export_rate": 500.0, "export_amount": 500.0, "income_account": "Sales - _TC", - "expense_account": "_Test Account Cost for Goods Sold", + "expense_account": "_Test Account Cost for Goods Sold - _TC", "cost_center": "_Test Cost Center - _TC", }, { diff --git a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt index c8b18a4880..ca078b53f4 100644 --- a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt +++ b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-03-05 09:11:04", + "creation": "2013-03-07 11:42:55", "docstatus": 0, - "modified": "2013-03-07 07:03:30", + "modified": "2013-03-11 14:58:50", "modified_by": "Administrator", "owner": "Administrator" }, @@ -30,7 +30,8 @@ "fieldname": "barcode", "fieldtype": "Data", "label": "Barcode", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -42,6 +43,7 @@ "oldfieldtype": "Link", "options": "Item", "print_hide": 0, + "read_only": 0, "reqd": 0, "search_index": 1 }, @@ -63,6 +65,7 @@ "oldfieldname": "item_name", "oldfieldtype": "Data", "print_hide": 1, + "read_only": 0, "reqd": 1, "search_index": 0 }, @@ -74,6 +77,7 @@ "oldfieldname": "description", "oldfieldtype": "Text", "print_width": "200px", + "read_only": 0, "reqd": 1, "width": "200px" }, @@ -84,6 +88,7 @@ "label": "Qty", "oldfieldname": "qty", "oldfieldtype": "Currency", + "read_only": 0, "reqd": 0 }, { @@ -102,6 +107,7 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, + "read_only": 0, "reqd": 0 }, { @@ -111,7 +117,8 @@ "label": "Discount (%)", "oldfieldname": "adj_rate", "oldfieldtype": "Float", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -121,6 +128,7 @@ "oldfieldname": "export_rate", "oldfieldtype": "Currency", "options": "currency", + "read_only": 0, "reqd": 1 }, { @@ -155,6 +163,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, + "read_only": 0, "reqd": 1, "search_index": 0 }, @@ -179,7 +188,8 @@ "oldfieldname": "warehouse", "oldfieldtype": "Link", "options": "Warehouse", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -192,9 +202,20 @@ "options": "Account", "print_hide": 1, "print_width": "120px", + "read_only": 0, "reqd": 1, "width": "120px" }, + { + "doctype": "DocField", + "fieldname": "expense_account", + "fieldtype": "Link", + "hidden": 1, + "in_filter": 1, + "label": "Expense Account", + "options": "Account", + "print_hide": 1 + }, { "doctype": "DocField", "fieldname": "cost_center", @@ -206,6 +227,7 @@ "options": "Cost Center", "print_hide": 1, "print_width": "120px", + "read_only": 0, "reqd": 0, "width": "120px" }, @@ -217,7 +239,8 @@ "label": "Serial No", "oldfieldname": "serial_no", "oldfieldtype": "Small Text", - "print_hide": 0 + "print_hide": 0, + "read_only": 0 }, { "doctype": "DocField", @@ -225,7 +248,8 @@ "fieldtype": "Link", "label": "Batch No", "options": "Batch", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -249,7 +273,8 @@ "label": "Brand Name", "oldfieldname": "brand", "oldfieldtype": "Data", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -328,7 +353,8 @@ "fieldname": "time_log_batch", "fieldtype": "Link", "label": "Time Log Batch", - "options": "Time Log Batch" + "options": "Time Log Batch", + "read_only": 0 }, { "doctype": "DocField", @@ -353,6 +379,17 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "buying_amount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Buying Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { "allow_on_submit": 1, "doctype": "DocField", @@ -361,6 +398,7 @@ "label": "Page Break", "no_copy": 1, "print_hide": 1, + "read_only": 0, "report_hide": 1 } ] \ No newline at end of file diff --git a/accounts/report/gross_profit/gross_profit.py b/accounts/report/gross_profit/gross_profit.py index fa926dacde..f1ae00e13f 100644 --- a/accounts/report/gross_profit/gross_profit.py +++ b/accounts/report/gross_profit/gross_profit.py @@ -25,7 +25,7 @@ def execute(filters=None): for row in delivery_note_items: selling_amount = flt(row.amount) buying_amount = get_buying_amount(row.item_code, row.warehouse, - row.qty, row.name, row.item_row, stock_ledger_entries, item_sales_bom) + row.qty, "Delivery Note", row.name, row.item_row, stock_ledger_entries, item_sales_bom) if selling_amount: gross_profit = selling_amount - buying_amount gross_profit_percent = (gross_profit / selling_amount) * 100.0 diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index aa52b5e412..73d7608240 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -21,7 +21,7 @@ from webnotes.utils import flt from utilities.transaction_base import TransactionBase class AccountsController(TransactionBase): - def get_gl_dict(self, args, cancel): + def get_gl_dict(self, args, cancel=None): """this method populates the common properties of a gl entry record""" gl_dict = { 'company': self.doc.company, @@ -30,7 +30,7 @@ class AccountsController(TransactionBase): 'voucher_no': self.doc.name, 'aging_date': self.doc.fields.get("aging_date") or self.doc.posting_date, 'remarks': self.doc.remarks, - 'is_cancelled': cancel and "Yes" or "No", + 'is_cancelled': self.doc.docstatus == 2 and "Yes" or "No", 'fiscal_year': self.doc.fiscal_year, 'debit': 0, 'credit': 0, diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 94a56e3300..40606c3198 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -37,4 +37,27 @@ class SellingController(AccountsController): self.doc.grand_total or self.doc.rounded_total, company_currency) if self.meta.get_field("in_words_export"): self.doc.in_words_export = money_in_words(disable_rounded_total and - self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency) \ No newline at end of file + self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency) + + def get_stock_ledger_entries(self): + item_list, warehouse_list = self.get_distinct_item_warehouse() + if item_list and warehouse_list: + return webnotes.conn.sql("""select item_code, voucher_type, voucher_no, + voucher_detail_no, posting_date, posting_time, stock_value, + warehouse, actual_qty as qty from `tabStock Ledger Entry` + where ifnull(`is_cancelled`, "No") = "No" and company = %s + and item_code in (%s) and warehouse in (%s) + order by item_code desc, warehouse desc, posting_date desc, + posting_time desc, name desc""" % + ('%s', ', '.join(['%s']*len(item_list)), ', '.join(['%s']*len(warehouse_list))), + tuple([self.doc.company] + item_list + warehouse_list), as_dict=1) + + def get_distinct_item_warehouse(self): + item_list = [] + warehouse_list = [] + for item in self.doclist.get({"parentfield": self.fname}) \ + + self.doclist.get({"parentfield": "packing_details"}): + item_list.append(item.item_code) + warehouse_list.append(item.warehouse) + + return list(set(item_list)), list(set(warehouse_list)) \ No newline at end of file diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js index b387aad67a..b66fe4c9a1 100644 --- a/home/page/latest_updates/latest_updates.js +++ b/home/page/latest_updates/latest_updates.js @@ -1,6 +1,14 @@ erpnext.updates = [ + ["5th March", ["Refactored Upload Attendace Tool"]], + ["4th March", ["Lead organization added in Quotation classic/spartan/modern print format"]], ["1st March", [ - "Time Log, Time Log Batch: Created feature to batch Time Logs so that they can be tracked for billing." + "Time Log, Time Log Batch: Created feature to batch Time Logs so that they can be tracked for billing.", + "Sub-contracting code refactored for PO", + ]], + ["28th February", [ + "Datatype validation in Voucher Import Tool", + "Fixes for conversion factor in old invoices", + "Fixed asynchronus issue in purchase cycle" ]], ["27th February", [ "Time Log: Created Time Log System, with Calendar View." diff --git a/patches/march_2013/p03_update_buying_amount.py b/patches/march_2013/p03_update_buying_amount.py new file mode 100644 index 0000000000..e45a3dbd1c --- /dev/null +++ b/patches/march_2013/p03_update_buying_amount.py @@ -0,0 +1,10 @@ +import webnotes + +def execute(): + dn_list = webnotes.conn.sql("""select name from `tabDelivery Note` where docstatus < 2""") + for dn in dn_list: + webnotes.bean("Delivery Note", dn[0]).set_buying_amount() + + si_list = webnotes.conn.sql("""select name from `tabSales Invoice` where docstatus < 2""") + for si in si_list: + webnotes.bean("Sales Invoice", si[0]).set_buying_amount() \ No newline at end of file diff --git a/setup/doctype/sales_person/test_sales_person.py b/setup/doctype/sales_person/test_sales_person.py index 5af450916b..2dea3e5dee 100644 --- a/setup/doctype/sales_person/test_sales_person.py +++ b/setup/doctype/sales_person/test_sales_person.py @@ -4,5 +4,19 @@ test_records = [ "sales_person_name": "_Test Sales Person", "parent_sales_person": "All Sales Persons", "is_group": "No" + }], + [{ + "doctype": "Sales Person", + "sales_person_name": "_Test Sales Person 1", + "parent_sales_person": "All Sales Persons", + "is_group": "No" + }], + [{ + "doctype": "Sales Person", + "sales_person_name": "_Test Sales Person 2", + "parent_sales_person": "All Sales Persons", + "is_group": "No" }] + + ] \ No newline at end of file diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index c0b99166ee..3d799c4dad 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -225,7 +225,12 @@ class DocType(SellingController): bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0 - + + def on_update(self): + self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details') + sl = get_obj('Stock Ledger') + sl.scrub_serial_nos(self) + sl.scrub_serial_nos(self, 'packing_details') def on_submit(self): self.validate_packed_qty() @@ -252,6 +257,7 @@ class DocType(SellingController): self.credit_limit() + self.set_buying_amount() self.make_gl_entries() # set DN status @@ -387,13 +393,19 @@ class DocType(SellingController): if amount != 0: total = (amount/self.doc.net_total)*self.doc.grand_total get_obj('Sales Common').check_credit(self, total) - - - def on_update(self): - self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details') - sl = get_obj('Stock Ledger') - sl.scrub_serial_nos(self) - sl.scrub_serial_nos(self, 'packing_details') + + def set_buying_amount(self): + from stock.utils import get_buying_amount, get_sales_bom + stock_ledger_entries = self.get_stock_ledger_entries() + item_sales_bom = get_sales_bom() + + if stock_ledger_entries: + for item in self.doclist.get({"parentfield": "delivery_note_details"}): + item.buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty, + self.doc.doctype, self.doc.name, item.name, stock_ledger_entries, + item_sales_bom) + webnotes.conn.set_value("Delivery Note Item", item.name, "buying_amount", + item.buying_amount) def make_gl_entries(self): if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")): @@ -426,38 +438,6 @@ class DocType(SellingController): make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2) def get_total_buying_amount(self): - from stock.utils import get_buying_amount, get_sales_bom - stock_ledger_entries = self.get_stock_ledger_entries() - item_sales_bom = get_sales_bom() - total_buying_amount = 0 - - if stock_ledger_entries: - for item in self.doclist.get({"parentfield": "delivery_note_details"}): - buying_amount = get_buying_amount(item.item_code, item.warehouse, item.qty, - self.doc.name, item.name, stock_ledger_entries, item_sales_bom) - total_buying_amount += buying_amount - - return total_buying_amount - - def get_stock_ledger_entries(self): - item_list, warehouse_list = self.get_distinct_item_warehouse() - if item_list and warehouse_list: - return webnotes.conn.sql("""select item_code, voucher_type, voucher_no, - voucher_detail_no, posting_date, posting_time, stock_value, - warehouse, actual_qty as qty from `tabStock Ledger Entry` - where ifnull(`is_cancelled`, "No") = "No" and company = %s - and item_code in (%s) and warehouse in (%s) - order by item_code desc, warehouse desc, posting_date desc, - posting_time desc, name desc""" % - ('%s', ', '.join(['%s']*len(item_list)), ', '.join(['%s']*len(warehouse_list))), - tuple([self.doc.company] + item_list + warehouse_list), as_dict=1) - - def get_distinct_item_warehouse(self): - item_list = [] - warehouse_list = [] - for item in self.doclist.get({"parentfield": "delivery_note_details"}) \ - + self.doclist.get({"parentfield": "packing_details"}): - item_list.append(item.item_code) - warehouse_list.append(item.warehouse) - - return list(set(item_list)), list(set(warehouse_list)) \ No newline at end of file + total_buying_amount = sum([item.buying_amount for item in + self.doclist.get({"parentfield": "delivery_note_details"})]) + return total_buying_amount \ No newline at end of file diff --git a/stock/doctype/delivery_note/test_delivery_note.py b/stock/doctype/delivery_note/test_delivery_note.py index acdf8b9e07..d0b440cfee 100644 --- a/stock/doctype/delivery_note/test_delivery_note.py +++ b/stock/doctype/delivery_note/test_delivery_note.py @@ -48,6 +48,8 @@ class TestDeliveryNote(unittest.TestCase): def test_delivery_note_gl_entry(self): webnotes.conn.sql("""delete from `tabBin`""") + webnotes.conn.sql("delete from `tabStock Ledger Entry`") + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1) diff --git a/stock/doctype/delivery_note_item/delivery_note_item.txt b/stock/doctype/delivery_note_item/delivery_note_item.txt index 985a072756..47b0d33bcd 100644 --- a/stock/doctype/delivery_note_item/delivery_note_item.txt +++ b/stock/doctype/delivery_note_item/delivery_note_item.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-02-22 01:28:00", + "creation": "2013-03-07 11:42:59", "docstatus": 0, - "modified": "2013-03-07 07:03:20", + "modified": "2013-03-07 15:46:43", "modified_by": "Administrator", "owner": "Administrator" }, @@ -30,7 +30,8 @@ "fieldname": "barcode", "fieldtype": "Data", "label": "Barcode", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -42,6 +43,7 @@ "oldfieldtype": "Link", "options": "Item", "print_width": "150px", + "read_only": 0, "reqd": 1, "search_index": 1, "width": "150px" @@ -64,6 +66,7 @@ "oldfieldtype": "Data", "print_hide": 1, "print_width": "150px", + "read_only": 0, "reqd": 1, "width": "150px" }, @@ -75,6 +78,7 @@ "oldfieldname": "description", "oldfieldtype": "Small Text", "print_width": "300px", + "read_only": 0, "reqd": 1, "width": "300px" }, @@ -87,6 +91,7 @@ "oldfieldname": "qty", "oldfieldtype": "Currency", "print_width": "100px", + "read_only": 0, "reqd": 1, "width": "100px" }, @@ -115,6 +120,7 @@ "options": "currency", "print_hide": 1, "print_width": "100px", + "read_only": 0, "reqd": 0, "width": "100px" }, @@ -128,6 +134,7 @@ "oldfieldtype": "Float", "print_hide": 1, "print_width": "100px", + "read_only": 0, "width": "100px" }, { @@ -140,6 +147,7 @@ "options": "currency", "print_hide": 0, "print_width": "150px", + "read_only": 0, "reqd": 0, "width": "150px" }, @@ -181,6 +189,7 @@ "options": "Company:company:default_currency", "print_hide": 1, "print_width": "150px", + "read_only": 0, "reqd": 0, "width": "150px" }, @@ -208,6 +217,7 @@ "options": "Warehouse", "print_hide": 1, "print_width": "100px", + "read_only": 0, "width": "100px" }, { @@ -219,7 +229,8 @@ "no_copy": 1, "oldfieldname": "serial_no", "oldfieldtype": "Text", - "print_hide": 0 + "print_hide": 0, + "read_only": 0 }, { "doctype": "DocField", @@ -229,7 +240,8 @@ "oldfieldname": "batch_no", "oldfieldtype": "Link", "options": "Batch", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -375,6 +387,17 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "buying_amount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Buying Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, { "allow_on_submit": 1, "doctype": "DocField", @@ -383,6 +406,7 @@ "label": "Page Break", "oldfieldname": "page_break", "oldfieldtype": "Check", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 } ] \ No newline at end of file diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py index 035774b50b..f31f245e81 100644 --- a/stock/doctype/item/test_item.py +++ b/stock/doctype/item/test_item.py @@ -127,4 +127,23 @@ test_records = [ "is_sub_contracted_item": "Yes", "stock_uom": "_Test UOM" }], + [{ + "doctype": "Item", + "item_code": "_Test Non Stock Item", + "item_name": "_Test Non Stock Item", + "description": "_Test Non Stock Item", + "item_group": "_Test Item Group Desktops", + "is_stock_item": "No", + "is_asset_item": "No", + "has_batch_no": "No", + "has_serial_no": "No", + "is_purchase_item": "Yes", + "is_sales_item": "Yes", + "is_service_item": "No", + "is_sample_item": "No", + "inspection_required": "No", + "is_pro_applicable": "No", + "is_sub_contracted_item": "No", + "stock_uom": "_Test UOM" + }], ] \ No newline at end of file diff --git a/stock/stock_ledger.py b/stock/stock_ledger.py index 60b5fd4aea..883ced7f71 100644 --- a/stock/stock_ledger.py +++ b/stock/stock_ledger.py @@ -36,7 +36,6 @@ def update_entries_after(args, verbose=1): } """ previous_sle = get_sle_before_datetime(args) - qty_after_transaction = flt(previous_sle.get("qty_after_transaction")) valuation_rate = flt(previous_sle.get("valuation_rate")) stock_queue = json.loads(previous_sle.get("stock_queue") or "[]") @@ -214,7 +213,6 @@ def get_moving_average_values(qty_after_transaction, sle, valuation_rate): def get_fifo_values(qty_after_transaction, sle, stock_queue): incoming_rate = flt(sle.incoming_rate) actual_qty = flt(sle.actual_qty) - if not stock_queue: stock_queue.append([0, 0]) diff --git a/stock/utils.py b/stock/utils.py index 9055ceea25..bc6054f70b 100644 --- a/stock/utils.py +++ b/stock/utils.py @@ -164,23 +164,24 @@ def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters): wlist.append([w]) return wlist -def get_buying_amount(item_code, warehouse, qty, voucher_no, voucher_detail_no, +def get_buying_amount(item_code, warehouse, qty, voucher_type, voucher_no, voucher_detail_no, stock_ledger_entries, item_sales_bom): if item_sales_bom.get(item_code): # sales bom item buying_amount = 0.0 for bom_item in item_sales_bom[item_code]: - buying_amount += _get_buying_amount(voucher_no, "[** No Item Row **]", + buying_amount += _get_buying_amount(voucher_type, voucher_no, "[** No Item Row **]", item_code, warehouse, bom_item.qty * qty, stock_ledger_entries) return buying_amount else: # doesn't have sales bom - return _get_buying_amount(voucher_no, voucher_detail_no, item_code, warehouse, qty, - stock_ledger_entries) + return _get_buying_amount(voucher_type, voucher_no, voucher_detail_no, + item_code, warehouse, qty, stock_ledger_entries) -def _get_buying_amount(voucher_no, item_row, item_code, warehouse, qty, stock_ledger_entries): +def _get_buying_amount(voucher_type, voucher_no, item_row, item_code, warehouse, qty, + stock_ledger_entries): for i, sle in enumerate(stock_ledger_entries): - if sle.voucher_type == "Delivery Note" and sle.voucher_no == voucher_no: + if sle.voucher_type == voucher_type and sle.voucher_no == voucher_no: if (sle.voucher_detail_no == item_row) or \ (sle.item_code == item_code and sle.warehouse == warehouse and \ abs(flt(sle.qty)) == qty): From b33693db359c4d4fba2c8c0fde4121ffd3831c28 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 11 Mar 2013 17:57:57 +0530 Subject: [PATCH 31/73] added blog settings and metadata --- website/doctype/blog_post/blog_post.py | 4 ++- .../doctype/style_settings/style_settings.py | 3 ++ website/doctype/web_page/web_page.txt | 30 ++++++++++++++----- website/helpers/blog.py | 11 +++++-- website/page/website_home/website_home.js | 6 ++++ website/templates/html/base.html | 3 ++ website/templates/html/blog_page.html | 9 ++++-- website/templates/html/blogger.html | 2 +- website/templates/html/comment.html | 19 +++++++----- website/templates/js/blog.js | 4 +-- website/templates/pages/blog.html | 6 +++- website/templates/pages/writers.html | 3 ++ 12 files changed, 74 insertions(+), 26 deletions(-) diff --git a/website/doctype/blog_post/blog_post.py b/website/doctype/blog_post/blog_post.py index 1664b4fca5..ff6cc9931e 100644 --- a/website/doctype/blog_post/blog_post.py +++ b/website/doctype/blog_post/blog_post.py @@ -74,13 +74,15 @@ class DocType: # temp fields from webnotes.utils import global_date_format, get_fullname self.doc.full_name = get_fullname(self.doc.owner) - self.doc.updated = global_date_format(self.doc.creation) + self.doc.updated = global_date_format(self.doc.published_on) self.doc.content_html = self.doc.content if self.doc.blogger: self.doc.blogger_info = webnotes.doc("Blogger", self.doc.blogger).fields if self.doc.blogger_info.avatar and not "/" in self.doc.blogger_info.avatar: self.doc.blogger_info.avatar = "files/" + self.doc.blogger_info.avatar + self.doc.description = self.doc.blog_intro or self.doc.content[:140] + self.doc.categories = webnotes.conn.sql_list("select name from `tabBlog Category` order by name") self.doc.texts = { diff --git a/website/doctype/style_settings/style_settings.py b/website/doctype/style_settings/style_settings.py index 434f4b546d..ba003ae594 100644 --- a/website/doctype/style_settings/style_settings.py +++ b/website/doctype/style_settings/style_settings.py @@ -39,6 +39,9 @@ class DocType: from webnotes.sessions import clear_cache clear_cache('Guest') + + from website.utils import clear_cache + clear_cache() for f in ["small_font_size", "at_import", "heading_text_style"]: if f in self.doc.fields: diff --git a/website/doctype/web_page/web_page.txt b/website/doctype/web_page/web_page.txt index 861ac86e39..eed7d2b63b 100644 --- a/website/doctype/web_page/web_page.txt +++ b/website/doctype/web_page/web_page.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-27 16:31:21", + "creation": "2013-02-12 13:19:11", "docstatus": 0, - "modified": "2013-02-12 09:33:47", + "modified": "2013-03-11 17:41:11", "modified_by": "Administrator", "owner": "Administrator" }, @@ -24,18 +24,16 @@ "permlevel": 0 }, { - "create": 1, + "amend": 0, "doctype": "DocPerm", "name": "__common__", "parent": "Web Page", "parentfield": "permissions", "parenttype": "DocType", - "permlevel": 0, "read": 1, "report": 1, "role": "Website Manager", - "submit": 0, - "write": 1 + "submit": 0 }, { "doctype": "DocType", @@ -85,6 +83,13 @@ "label": "Slideshow", "options": "Website Slideshow" }, + { + "description": "Description for page header.", + "doctype": "DocField", + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Description" + }, { "description": "Content in markdown format that appears on the main side of your page", "doctype": "DocField", @@ -143,6 +148,17 @@ "print_hide": 1 }, { - "doctype": "DocPerm" + "cancel": 1, + "create": 1, + "doctype": "DocPerm", + "permlevel": 0, + "write": 1 + }, + { + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "write": 0 } ] \ No newline at end of file diff --git a/website/helpers/blog.py b/website/helpers/blog.py index ec57105e35..de2a3373ae 100644 --- a/website/helpers/blog.py +++ b/website/helpers/blog.py @@ -127,9 +127,11 @@ def get_blog_content(blog_page_name): return content def get_blog_template_args(): - return { + args = { "categories": webnotes.conn.sql_list("select name from `tabBlog Category` order by name") } + args.update(webnotes.doc("Blog Settings", "Blog Settings").fields) + return args def get_writers_args(): bloggers = webnotes.conn.sql("""select * from `tabBlogger` @@ -138,10 +140,13 @@ def get_writers_args(): if blogger.avatar and not "/" in blogger.avatar: blogger.avatar = "files/" + blogger.avatar - return { + args = { "bloggers": bloggers, "texts": { "all_posts_by": _("All posts by") }, "categories": webnotes.conn.sql_list("select name from `tabBlog Category` order by name") - } \ No newline at end of file + } + + args.update(webnotes.doc("Blog Settings", "Blog Settings").fields) + return args \ No newline at end of file diff --git a/website/page/website_home/website_home.js b/website/page/website_home/website_home.js index bb3d14f04a..e1122071dd 100644 --- a/website/page/website_home/website_home.js +++ b/website/page/website_home/website_home.js @@ -37,6 +37,12 @@ wn.module_page["Website"] = [ description: wn._("Categorize blog posts."), doctype:"Blog Category" }, + { + label: wn._("Blog Settings"), + description: wn._("Write titles and introductions to your blog."), + doctype:"Blog Settings", + route: "Form/Blog Settings" + }, ] }, diff --git a/website/templates/html/base.html b/website/templates/html/base.html index fa01f8aad7..2719f8db36 100644 --- a/website/templates/html/base.html +++ b/website/templates/html/base.html @@ -19,6 +19,9 @@ {% endif %} + {% if description %} + + {% endif %} {% block header %} {% endblock %} diff --git a/website/templates/html/blog_page.html b/website/templates/html/blog_page.html index e605a12248..270d427f7f 100644 --- a/website/templates/html/blog_page.html +++ b/website/templates/html/blog_page.html @@ -9,14 +9,17 @@ {% endblock %} {% block content %} -
-

{{ title }}

+
+

{{ title }}

- {{ blogger_info and blogger_info.full_name or full_name }} / {{ updated }}
+ / + {{ updated }}

+
{{ content_html }} +
{% if blogger_info %}
diff --git a/website/templates/html/blogger.html b/website/templates/html/blogger.html index eab371e45b..e18f86a4dd 100644 --- a/website/templates/html/blogger.html +++ b/website/templates/html/blogger.html @@ -1,7 +1,7 @@
- +
diff --git a/website/templates/html/comment.html b/website/templates/html/comment.html index 1323e094d2..27baaad54d 100644 --- a/website/templates/html/comment.html +++ b/website/templates/html/comment.html @@ -3,12 +3,15 @@ it is to be included in the blog/blog.html template #} -{% for comment in comment_list %} -
-
- {{ comment.comment_by_fullname }} - {{ comment.comment_date }}: +
+ {% for comment in comment_list %} +
+
+ {{ comment.comment_by_fullname }} / + {{ comment.comment_date }}: +
+

{{ comment.comment }}

+
-

{{ comment.comment }}

-
-
-{% endfor %} \ No newline at end of file + {% endfor %} +
\ No newline at end of file diff --git a/website/templates/js/blog.js b/website/templates/js/blog.js index 91d3ead65a..61e1b657f2 100644 --- a/website/templates/js/blog.js +++ b/website/templates/js/blog.js @@ -25,11 +25,11 @@ $(document).ready(function() { }) if(get_url_arg("by_name")) { - $("#blog-title").html("Posts by " + get_url_arg("by_name")); + $("#blot-subtitle").html("Posts by " + get_url_arg("by_name")).toggle(true); } if(get_url_arg("category")) { - $("#blog-title").html("Posts filed under " + get_url_arg("category")); + $("#blot-subtitle").html("Posts filed under " + get_url_arg("category")).toggle(true); } }); diff --git a/website/templates/pages/blog.html b/website/templates/pages/blog.html index cfdd536696..df258e138f 100644 --- a/website/templates/pages/blog.html +++ b/website/templates/pages/blog.html @@ -12,7 +12,11 @@ {% block content %}
-

Blog

+

{{ blog_title }}

+ {% if blog_introduction %} +

{{ blog_introduction }}

+ {% endif %} +
diff --git a/website/templates/pages/writers.html b/website/templates/pages/writers.html index 0ae8549f97..bba374946c 100644 --- a/website/templates/pages/writers.html +++ b/website/templates/pages/writers.html @@ -5,6 +5,9 @@ {% block content %}

Blog Writers

+ {% if writers_introduction %} +

{{ writers_introduction }}

+ {% endif %}
{% for blogger_info in bloggers %} {% include "html/blogger.html" %} From 770e7938d94e745891ff47b3d2af44d5f5cad6a7 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 11 Mar 2013 18:30:05 +0530 Subject: [PATCH 32/73] added footer subscribe and blog settings --- website/doctype/blog_settings/__init__.py | 0 .../doctype/blog_settings/blog_settings.py | 8 ++ .../doctype/blog_settings/blog_settings.txt | 61 ++++++++++++ website/helpers/blog.py | 9 +- website/helpers/blog_feed.py | 2 +- website/templates/html/footer.html | 66 +++++++++++++ website/templates/html/navbar.html | 57 +++++++++++ website/templates/html/outer.html | 97 +------------------ 8 files changed, 198 insertions(+), 102 deletions(-) create mode 100644 website/doctype/blog_settings/__init__.py create mode 100644 website/doctype/blog_settings/blog_settings.py create mode 100644 website/doctype/blog_settings/blog_settings.txt create mode 100644 website/templates/html/footer.html create mode 100644 website/templates/html/navbar.html diff --git a/website/doctype/blog_settings/__init__.py b/website/doctype/blog_settings/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/website/doctype/blog_settings/blog_settings.py b/website/doctype/blog_settings/blog_settings.py new file mode 100644 index 0000000000..928aa9ff9f --- /dev/null +++ b/website/doctype/blog_settings/blog_settings.py @@ -0,0 +1,8 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/website/doctype/blog_settings/blog_settings.txt b/website/doctype/blog_settings/blog_settings.txt new file mode 100644 index 0000000000..09740eb78f --- /dev/null +++ b/website/doctype/blog_settings/blog_settings.txt @@ -0,0 +1,61 @@ +[ + { + "creation": "2013-03-11 17:48:16", + "docstatus": 0, + "modified": "2013-03-11 17:48:16", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "description": "Blog Settings", + "doctype": "DocType", + "issingle": 1, + "module": "Website", + "name": "__common__" + }, + { + "doctype": "DocField", + "name": "__common__", + "parent": "Blog Settings", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0 + }, + { + "create": 1, + "doctype": "DocPerm", + "name": "__common__", + "parent": "Blog Settings", + "parentfield": "permissions", + "parenttype": "DocType", + "permlevel": 0, + "read": 1, + "role": "Website Manager", + "write": 1 + }, + { + "doctype": "DocType", + "name": "Blog Settings" + }, + { + "doctype": "DocField", + "fieldname": "blog_title", + "fieldtype": "Data", + "label": "Blog Title" + }, + { + "doctype": "DocField", + "fieldname": "blog_introduction", + "fieldtype": "Small Text", + "label": "Blog Introduction" + }, + { + "doctype": "DocField", + "fieldname": "writers_introduction", + "fieldtype": "Small Text", + "label": "Writers Introduction" + }, + { + "doctype": "DocPerm" + } +] \ No newline at end of file diff --git a/website/helpers/blog.py b/website/helpers/blog.py index de2a3373ae..5ee3451956 100644 --- a/website/helpers/blog.py +++ b/website/helpers/blog.py @@ -99,10 +99,8 @@ def add_comment(args=None): return comment_html @webnotes.whitelist(allow_guest=True) -def add_subscriber(): +def add_subscriber(name, email_id): """add blog subscriber to lead""" - full_name = webnotes.form_dict.get('your_name') - email = webnotes.form_dict.get('your_email_address') name = webnotes.conn.sql("""select name from tabLead where email_id=%s""", email) from webnotes.model.doc import Document @@ -114,14 +112,13 @@ def add_subscriber(): if not lead.source: lead.source = 'Blog' lead.unsubscribed = 0 lead.blog_subscriber = 1 - lead.lead_name = full_name + lead.lead_name = name lead.email_id = email lead.save() - + def get_blog_content(blog_page_name): import website.utils content = website.utils.get_html(blog_page_name) - content = split_blog_content(content) import webnotes.utils content = webnotes.utils.escape_html(content) return content diff --git a/website/helpers/blog_feed.py b/website/helpers/blog_feed.py index 19fc5d8ec6..c59a419fc6 100644 --- a/website/helpers/blog_feed.py +++ b/website/helpers/blog_feed.py @@ -59,7 +59,7 @@ def generate(): blog_list = webnotes.conn.sql("""\ select page_name as name, modified, creation, title from `tabBlog Post` where ifnull(published,0)=1 - order by creation desc, modified desc, name asc limit 100""", as_dict=1) + order by creation desc, modified desc, name asc limit 20""", as_dict=1) for blog in blog_list: blog.link = host + '/' + blog.name + '.html' diff --git a/website/templates/html/footer.html b/website/templates/html/footer.html new file mode 100644 index 0000000000..19aeabef65 --- /dev/null +++ b/website/templates/html/footer.html @@ -0,0 +1,66 @@ +
+
diff --git a/website/templates/html/navbar.html b/website/templates/html/navbar.html new file mode 100644 index 0000000000..5a30c6a6f1 --- /dev/null +++ b/website/templates/html/navbar.html @@ -0,0 +1,57 @@ + + diff --git a/website/templates/html/outer.html b/website/templates/html/outer.html index e582d0a9ce..9c8cd9f8d4 100644 --- a/website/templates/html/outer.html +++ b/website/templates/html/outer.html @@ -5,106 +5,13 @@
- - + {% include "html/navbar.html" %}
{% block content %} {% endblock %}
-
-
+ {% include "html/footer.html" %} {% endblock %} \ No newline at end of file From df6ff1385fabd100bc70ce60803b0c942e1d6ccb Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 11 Mar 2013 19:44:52 +0530 Subject: [PATCH 33/73] fixes in warehouse validation --- .../doctype/sales_invoice/sales_invoice.py | 3 +-- .../purchase_common/purchase_common.js | 2 +- .../doctype/purchase_order/purchase_order.py | 4 ++++ hr/doctype/employee/employee.py | 4 ++-- .../upload_attendance/upload_attendance.js | 2 +- projects/doctype/task/task.js | 2 +- public/js/controllers/stock_controller.js | 2 +- public/js/utils.js | 9 +-------- selling/doctype/sales_order/sales_order.py | 10 +++++----- stock/doctype/delivery_note/delivery_note.py | 19 +++++++++++++----- stock/doctype/item/item.py | 20 +++++++++++++------ .../purchase_receipt/purchase_receipt.py | 5 ++++- stock/doctype/stock_entry/stock_entry.py | 12 +++++++++-- 13 files changed, 59 insertions(+), 35 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index b31d54919c..a4924ac187 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -537,8 +537,7 @@ class DocType(SellingController): if not w: ps = webnotes.conn.sql("select name, warehouse from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % self.doc.company) if not ps: - msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.") - raise Exception + msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.", raise_exception=True) elif not ps[0][1]: msgprint("Please enter warehouse in POS Setting") else: diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 136ddef383..dacee80e55 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -21,7 +21,7 @@ wn.provide("erpnext.buying"); -erpnext.buying.BuyingController = erpnext.utils.Controller.extend({ +erpnext.buying.BuyingController = wn.ui.form.Controller.extend({ setup: function() { var me = this; diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 438442cf24..218d4bfeee 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -132,6 +132,10 @@ class DocType(BuyingController): for d in getlist(self.doclist, 'po_details'): #1. Check if is_stock_item == 'Yes' if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes": + # this happens when item is changed from non-stock to stock item + if not d.warehouse: + continue + ind_qty, po_qty = 0, flt(d.qty) * flt(d.conversion_factor) if is_stopped: po_qty = flt(d.qty) > flt(d.received_qty) and \ diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index 2bd7998159..d98c8a7754 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -17,7 +17,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import getdate, validate_email_add +from webnotes.utils import getdate, validate_email_add, cstr from webnotes.model.doc import make_autoname from webnotes import msgprint, _ @@ -104,7 +104,7 @@ class DocType: fname, fid = file_args.split(",") if self.doc.image == fname: new_file_args = fname + "," + fid - file_list = profile_wrapper.doc.file_list.split("\n") + file_list = cstr(profile_wrapper.doc.file_list).split("\n") if new_file_args not in file_list: file_list += [new_file_args] profile_wrapper.doc.file_list = "\n".join(file_list) diff --git a/hr/doctype/upload_attendance/upload_attendance.js b/hr/doctype/upload_attendance/upload_attendance.js index 008e1cd878..0c1d7b2574 100644 --- a/hr/doctype/upload_attendance/upload_attendance.js +++ b/hr/doctype/upload_attendance/upload_attendance.js @@ -18,7 +18,7 @@ wn.require("public/app/js/utils.js"); wn.provide("erpnext.hr"); -erpnext.hr.AttendanceControlPanel = erpnext.utils.Controller.extend({ +erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({ onload: function() { this.frm.set_value("att_fr_date", get_today()); this.frm.set_value("att_to_date", get_today()); diff --git a/projects/doctype/task/task.js b/projects/doctype/task/task.js index ea3dd6d772..8493920540 100644 --- a/projects/doctype/task/task.js +++ b/projects/doctype/task/task.js @@ -18,7 +18,7 @@ wn.provide("erpnext.projects"); cur_frm.add_fetch("project", "company", "company"); -erpnext.projects.Task = erpnext.utils.Controller.extend({ +erpnext.projects.Task = wn.ui.form.Controller.extend({ setup: function() { this.frm.fields_dict.project.get_query = function() { return "select name from `tabProject` \ diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js index d3511e1c03..15d34e0e33 100644 --- a/public/js/controllers/stock_controller.js +++ b/public/js/controllers/stock_controller.js @@ -16,7 +16,7 @@ wn.provide("erpnext.stock"); -erpnext.stock.StockController = erpnext.utils.Controller.extend({ +erpnext.stock.StockController = wn.ui.form.Controller.extend({ show_stock_ledger: function() { var me = this; this.frm.add_custom_button("Show Stock Ledger", function() { diff --git a/public/js/utils.js b/public/js/utils.js index 7340cdcb04..4df9555ae9 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -23,11 +23,4 @@ erpnext.get_currency = function(company) { return wn.model.get(":Company", company).default_currency || wn.boot.sysdefaults.currency; else return wn.boot.sysdefaults.currency; -} - -// TODO -erpnext.utils.Controller = wn.ui.form.Controller.extend({ - refresh: function() { - erpnext.hide_naming_series(); - } -}); \ No newline at end of file +} \ No newline at end of file diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 8205afbd44..5009c4ee26 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -156,9 +156,13 @@ class DocType(SellingController): f = [d.item_code, d.description] #check item is stock item - st_itm = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) + st_itm = sql("select is_stock_item from `tabItem` where name = %s", d.item_code) if st_itm and st_itm[0][0] == 'Yes': + if not d.reserved_warehouse: + msgprint("""Please enter Reserved Warehouse for item %s + as it is stock Item""" % d.item_code, raise_exception=1) + if e in check_list: msgprint("Item %s has been entered twice." % d.item_code) else: @@ -333,10 +337,6 @@ class DocType(SellingController): def update_stock_ledger(self, update_stock, is_stopped = 0): for d in self.get_item_list(is_stopped): if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": - if not d['reserved_warehouse']: - msgprint("""Please enter Reserved Warehouse for item %s - as it is stock Item""" % d['item_code'], raise_exception=1) - args = { "item_code": d['item_code'], "reserved_qty": flt(update_stock) * flt(d['reserved_qty']), diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index c0b99166ee..52f96ab7a5 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -156,7 +156,7 @@ class DocType(SellingController): if not self.doc.billing_status: self.doc.billing_status = 'Not Billed' if not self.doc.installation_status: self.doc.installation_status = 'Not Installed' - + def validate_mandatory(self): if self.doc.amended_from and not self.doc.amendment_date: msgprint("Please Enter Amendment Date") @@ -332,10 +332,10 @@ class DocType(SellingController): self.values = [] for d in self.get_item_list(): if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": - if not d['warehouse']: - msgprint("Please enter Warehouse for item %s as it is stock item" - % d['item_code'], raise_exception=1) - + # this happens when item is changed from non-stock to stock item + if not d["warehouse"]: + continue + if d['reserved_qty'] < 0 : # Reduce reserved qty from reserved warehouse mentioned in so args = { @@ -395,6 +395,15 @@ class DocType(SellingController): sl.scrub_serial_nos(self) sl.scrub_serial_nos(self, 'packing_details') + self.validate_warehouse() + + def validate_warehouse(self): + for d in self.get_item_list(): + if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": + if not d['warehouse']: + msgprint("Please enter Warehouse for item %s as it is stock item" + % d['item_code'], raise_exception=1) + def make_gl_entries(self): if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")): return diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index 334af298e9..74bf3f308c 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -20,15 +20,12 @@ import webnotes from webnotes.utils import cstr, flt from webnotes.model.doc import addchild from webnotes.model.bean import getlist -from webnotes import msgprint +from webnotes import msgprint, _ sql = webnotes.conn.sql -class DocType: - def __init__(self, doc, doclist=[]): - self.doc = doc - self.doclist = doclist - +from webnotes.model.controller import DocListController +class DocType(DocListController): def get_tax_rate(self, tax_type): rate = sql("select tax_rate from tabAccount where name = %s", tax_type) ret = { @@ -196,6 +193,8 @@ class DocType: if self.doc.name: self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name') + + self.validate_is_stock_item() def check_non_asset_warehouse(self): if self.doc.is_asset_item == "Yes": @@ -215,6 +214,15 @@ class DocType: 'description' : file and file[0]['description'] or '' } return ret + + def validate_is_stock_item(self): + if not self.doc.fields.get("__islocal"): + if webnotes.conn.get_value("Item", self.doc.name, "is_stock_item")=="Yes" and \ + ((not self.doc.is_stock_item) or self.doc.is_stock_item == "No"): + if self.check_if_sle_exists() == "exists": + webnotes.msgprint(self.meta.get_label("is_stock_item") + ": " + + _("""Cannot change to Yes. Reason: Stock Ledger Entries exist for""") + + """ "%s" """ % self.doc.name, raise_exception=True) def check_if_sle_exists(self): sle = sql("select name from `tabStock Ledger Entry` where item_code = %s and ifnull(is_cancelled, 'No') = 'No'", self.doc.name) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 12da0a6ee8..cce1493141 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -125,7 +125,7 @@ class DocType(BuyingController): self.update_raw_materials_supplied("pr_raw_material_details") self.update_valuation_rate("purchase_receipt_details") - + def on_update(self): if self.doc.rejected_warehouse: for d in getlist(self.doclist,'purchase_receipt_details'): @@ -146,6 +146,9 @@ class DocType(BuyingController): self.values = [] for d in getlist(self.doclist, 'purchase_receipt_details'): if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes": + if not d.warehouse: + continue + ord_qty = 0 pr_qty = flt(d.qty) * flt(d.conversion_factor) diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 278c283284..74b71d97b3 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -29,9 +29,9 @@ import json sql = webnotes.conn.sql -from utilities.transaction_base import TransactionBase +from controllers.accounts_controller import AccountsController -class DocType(TransactionBase): +class DocType(AccountsController): def __init__(self, doc, doclist=[]): self.doc = doc self.doclist = doclist @@ -44,12 +44,14 @@ class DocType(TransactionBase): pro_obj = self.doc.production_order and \ get_obj('Production Order', self.doc.production_order) or None + self.validate_item() self.validate_warehouse(pro_obj) self.validate_production_order(pro_obj) self.get_stock_and_rate() self.validate_incoming_rate() self.validate_bom() self.validate_finished_goods() + self.validate_return_reference_doc() self.validate_with_material_request() @@ -78,6 +80,12 @@ class DocType(TransactionBase): sl_obj.scrub_serial_nos(self) sl_obj.validate_serial_no(self, 'mtn_details') + def validate_item(self): + for item in self.doclist.get({"parentfield": "mtn_details"}): + if item.item_code not in self.stock_items: + msgprint(_("""Only Stock Items are allowed for Stock Entry"""), + raise_exception=True) + def validate_warehouse(self, pro_obj): """perform various (sometimes conditional) validations on warehouse""" From bffbc18b2d354cc57195ea353c5faf1c8c491910 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 12 Mar 2013 10:41:21 +0530 Subject: [PATCH 34/73] fixes in cleanup data --- .../doctype/sales_invoice/sales_invoice.py | 7 + utilities/cleanup_data.py | 136 +++++++++--------- 2 files changed, 74 insertions(+), 69 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 597e2ff1aa..906de23677 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -724,6 +724,8 @@ class DocType(SellingController): # expense account gl entries if auto_inventory_accounting and flt(item.buying_amount): + self.check_expense_account(item) + gl_entries.append( self.get_gl_dict({ "account": item.expense_account, @@ -813,6 +815,11 @@ class DocType(SellingController): item_buying_amount = item_buying_rate * flt(item.qty) return item_buying_amount + + def check_expense_account(self, item): + if not item.expense_account: + msgprint(_("""Expense account is mandatory for item: """) + item.item_code, + raise_exception=1) def update_c_form(self): """Update amended id in C-form""" diff --git a/utilities/cleanup_data.py b/utilities/cleanup_data.py index a9cc5c340e..ed04a94bfa 100644 --- a/utilities/cleanup_data.py +++ b/utilities/cleanup_data.py @@ -20,16 +20,14 @@ import webnotes def delete_transactions(): print "Deleting transactions..." - trans = ['Timesheet','Task','Support Ticket','Stock Reconciliation', 'Stock Ledger Entry', \ - 'Stock Entry','Sales Order','Salary Slip','Sales Invoice','Quotation', 'Quality Inspection', \ - 'Purchase Receipt','Purchase Order','Production Order', 'POS Setting','Period Closing Voucher', \ - 'Purchase Invoice','Maintenance Visit','Maintenance Schedule','Leave Application', \ - 'Leave Allocation', 'Lead', 'Journal Voucher', 'Installation Note','Material Request', \ - 'GL Entry','Expense Claim','Opportunity','Delivery Note','Customer Issue','Bin', \ - 'Authorization Rule','Attendance', 'C-Form', 'Form 16A', 'Lease Agreement', \ - 'Lease Installment', 'TDS Payment', 'TDS Return Acknowledgement', 'Appraisal', \ - 'Installation Note', 'Communication' - ] + trans = ['Timesheet', 'Task', 'Support Ticket', 'Stock Reconciliation', 'Stock Ledger Entry', + 'Stock Entry', 'Sales Order', 'Salary Slip','Sales Invoice', 'Quotation', + 'Quality Inspection', 'Purchase Receipt', 'Purchase Order', 'Production Order', + 'POS Setting', 'Period Closing Voucher', 'Purchase Invoice', 'Maintenance Visit', + 'Maintenance Schedule', 'Leave Application', 'Leave Allocation', 'Lead', 'Journal Voucher', + 'Installation Note', 'Material Request', 'GL Entry', 'Expense Claim', 'Opportunity', + 'Delivery Note', 'Customer Issue', 'Bin', 'Authorization Rule', 'Attendance', 'C-Form', + 'Appraisal', 'Installation Note', 'Communication'] for d in trans: for t in webnotes.conn.sql("select options from tabDocField where parent='%s' and fieldtype='Table'" % d): webnotes.conn.sql("delete from `tab%s`" % (t)) @@ -41,55 +39,55 @@ def delete_transactions(): def delete_masters(): print "Deleting masters...." masters = { - 'Workstation':['Default Workstation'], - 'Warehouse Type':['Default Warehouse Type', 'Fixed Asset', 'Rejected', 'Reserved', + 'Workstation': ['Default Workstation'], + 'Warehouse Type': ['Default Warehouse Type', 'Fixed Asset', 'Rejected', 'Reserved', 'Sample', 'Stores', 'WIP Warehouse'], - 'Warehouse':['Default Warehouse'], - 'UOM':['Kg', 'Mtr', 'Box', 'Ltr', 'Nos', 'Ft', 'Pair', 'Set'], - 'Territory':['All Territories', 'Default Territory'], - 'Terms and Conditions':'', - 'Tag':'', - 'Supplier Type':['Default Supplier Type'], - 'Supplier':'', - 'Serial No':'', - 'Sales Person':['All Sales Persons'], - 'Sales Partner':'', - 'Sales BOM':'', - 'Salary Structure':'', - 'Purchase Taxes and Charges Master':'', - 'Project':'', - 'Print Heading':'', - 'Price List':['Default Price List'], - 'Sales Taxes and Charges Master':'', - 'Letter Head':'', - 'Leave Type':['Leave Without Pay', 'Privilege Leave', 'Casual Leave', 'PL', 'CL', 'LWP', + 'Warehouse': ['Default Warehouse'], + 'UOM': ['Kg', 'Mtr', 'Box', 'Ltr', 'Nos', 'Ft', 'Pair', 'Set'], + 'Territory': ['All Territories', 'Default Territory'], + 'Terms and Conditions': '', + 'Tag': '', + 'Supplier Type': ['Default Supplier Type'], + 'Supplier': '', + 'Serial No': '', + 'Sales Person': ['All Sales Persons'], + 'Sales Partner': '', + 'Sales BOM': '', + 'Salary Structure': '', + 'Purchase Taxes and Charges Master': '', + 'Project': '', + 'Print Heading': '', + 'Price List': ['Default Price List'], + 'Sales Taxes and Charges Master': '', + 'Letter Head': '', + 'Leave Type': ['Leave Without Pay', 'Privilege Leave', 'Casual Leave', 'PL', 'CL', 'LWP', 'Compensatory Off', 'Sick Leave'], - 'Appraisal Template':'', - 'Item Group':['All Item Groups', 'Default'], - 'Item':'', - 'Holiday List':'', - 'Grade':'', - 'Feed':'', - 'Expense Claim Type':['Travel', 'Medical', 'Calls', 'Food', 'Others'], - 'Event':'', - 'Employment Type':'', - 'Employee':'', - 'Earning Type':['Basic', 'Conveyance', 'House Rent Allowance', 'Dearness Allowance', + 'Appraisal Template': '', + 'Item Group': ['All Item Groups', 'Default'], + 'Item': '', + 'Holiday List': '', + 'Grade': '', + 'Feed': '', + 'Expense Claim Type': ['Travel', 'Medical', 'Calls', 'Food', 'Others'], + 'Event': '', + 'Employment Type': '', + 'Employee': '', + 'Earning Type': ['Basic', 'Conveyance', 'House Rent Allowance', 'Dearness Allowance', 'Medical Allowance', 'Telephone'], - 'Designation':'', - 'Department':'', - 'Deduction Type':['Income Tax', 'Professional Tax', 'Provident Fund', 'Leave Deduction'], - 'Customer Group':['All Customer Groups', 'Default Customer Group'], - 'Customer':'', - 'Cost Center':'', - 'Contact':'', - 'Campaign':'', - 'Budget Distribution':'', - 'Brand':'', - 'Branch':'', - 'Batch':'', - 'Appraisal':'', - 'Account':'', + 'Designation': '', + 'Department': '', + 'Deduction Type': ['Income Tax', 'Professional Tax', 'Provident Fund', 'Leave Deduction'], + 'Customer Group': ['All Customer Groups', 'Default Customer Group'], + 'Customer': '', + 'Cost Center': '', + 'Contact': '', + 'Campaign': '', + 'Budget Distribution': '', + 'Brand': '', + 'Branch': '', + 'Batch': '', + 'Appraisal': '', + 'Account': '', 'BOM': '' } for d in masters.keys(): @@ -115,40 +113,40 @@ def reset_all_series(): def reset_transaction_series(): webnotes.conn.sql("""update tabSeries set current = 0 where name in ('JV', 'INV', 'BILL', 'SO', 'DN', 'PO', 'LEAD', 'ENQUIRY', 'ENQ', 'CI', - 'IN', 'PS', 'IDT', 'QAI', 'QTN', 'STE', 'SQTN', 'SUP', 'TDSP', 'SR', + 'IN', 'PS', 'IDT', 'QAI', 'QTN', 'STE', 'SQTN', 'SUP', 'SR', 'POS', 'LAP', 'LAL', 'EXP')""") print "Series updated" def delete_main_masters(): - main_masters = ['Fiscal Year','Company', 'DefaultValue'] + main_masters = ['Fiscal Year', 'Company', 'DefaultValue'] for d in main_masters: for t in webnotes.conn.sql("select options from tabDocField where parent='%s' and fieldtype='Table'" % d): webnotes.conn.sql("delete from `tab%s`" % (t)) webnotes.conn.sql("delete from `tab%s`" % (d)) print "Deleted " + d - - def reset_global_defaults(): flds = { - 'default_company': '', - 'default_currency': '', - 'current_fiscal_year': '', + 'default_company': None, + 'default_currency': None, + 'current_fiscal_year': None, 'date_format': 'dd-mm-yyyy', - 'sms_sender_name': '', + 'sms_sender_name': None, 'default_item_group': 'Default', 'default_stock_uom': 'Nos', 'default_valuation_method': 'FIFO', 'default_warehouse_type': 'Default Warehouse Type', - 'tolerance': '', - 'acc_frozen_upto': '', - 'bde_auth_role': '', - 'credit_controller': '', + 'tolerance': None, + 'acc_frozen_upto': None, + 'bde_auth_role': None, + 'credit_controller': None, 'default_customer_group': 'Default Customer Group', 'default_territory': 'Default', 'default_price_list': 'Standard', - 'default_supplier_type': 'Default Supplier Type' + 'default_supplier_type': 'Default Supplier Type', + 'hide_currency_symbol': None, + 'default_price_list_currency': None, } from webnotes.model.code import get_obj From 9e4b1e691315b5f9f673d1cb301697449f9ab8b0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 12 Mar 2013 10:44:35 +0530 Subject: [PATCH 35/73] patch fix: published on should be date of creation --- patches/march_2013/p03_rename_blog_to_blog_post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/march_2013/p03_rename_blog_to_blog_post.py b/patches/march_2013/p03_rename_blog_to_blog_post.py index 7520f9cf8b..69902f34be 100644 --- a/patches/march_2013/p03_rename_blog_to_blog_post.py +++ b/patches/march_2013/p03_rename_blog_to_blog_post.py @@ -6,4 +6,4 @@ def execute(): webnotes.reload_doc('website', 'doctype', 'blog_post') webnotes.conn.sql('''update tabBlogger set posts=(select count(*) from `tabBlog Post` where ifnull(blogger,"")=tabBlogger.name)''') - webnotes.conn.sql("""update `tabBlog Post` set published_on=creation""") + webnotes.conn.sql("""update `tabBlog Post` set published_on=date(creation)""") From f7df8b28d268cbceb7dcb9b44f9aae8b07b7871c Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 12 Mar 2013 10:58:11 +0530 Subject: [PATCH 36/73] -m --- patches/february_2013/p07_clear_web_cache.py | 2 +- patches/patch_list.py | 1 + stock/doctype/stock_entry/test_stock_entry.py | 71 +++++++++++++++++++ stock/doctype/warehouse/warehouse.txt | 49 +++++++------ 4 files changed, 99 insertions(+), 24 deletions(-) diff --git a/patches/february_2013/p07_clear_web_cache.py b/patches/february_2013/p07_clear_web_cache.py index 5aca2d6ee6..26329249d0 100644 --- a/patches/february_2013/p07_clear_web_cache.py +++ b/patches/february_2013/p07_clear_web_cache.py @@ -1,6 +1,6 @@ import webnotes def execute(): + webnotes.reload_doc("website", "doctype", "blog_post") from website.utils import clear_cache clear_cache() - \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index bff51a9ae0..7409c0e986 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -18,6 +18,7 @@ from __future__ import unicode_literals patch_list = [ "execute:webnotes.reload_doc('core', 'doctype', 'docfield')", "execute:webnotes.reload_doc('core', 'doctype', 'report')", + "execute:webnotes.reload_doc('core', 'doctype', 'doctype')", "patches.mar_2012.so_rv_mapper_fix", "patches.mar_2012.clean_property_setter", "patches.april_2012.naming_series_patch", diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py index 39ec58ac3a..21d15f7e23 100644 --- a/stock/doctype/stock_entry/test_stock_entry.py +++ b/stock/doctype/stock_entry/test_stock_entry.py @@ -21,6 +21,77 @@ class TestStockEntry(unittest.TestCase): where item_code='_Test Item'""") self.assertTrue(mr_name) + + def test_material_receipt_gl_entry(self): + webnotes.conn.sql("delete from `tabStock Ledger Entry`") + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + mr = webnotes.bean(copy=test_records[0]) + mr.insert() + mr.submit() + + stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company", + "stock_in_hand_account") + + self.check_stock_ledger_entries("Stock Entry", mr.doc.name, + [["_Test Item", "_Test Warehouse", 50.0]]) + + self.check_gl_entries("Stock Entry", mr.doc.name, + sorted([ + [stock_in_hand_account, 5000.0, 0.0], + ["Stock Adjustment - _TC", 0.0, 5000.0] + ]) + ) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + def test_material_issue_gl_entry(self): + webnotes.conn.sql("delete from `tabStock Ledger Entry`") + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + mr = webnotes.bean(copy=test_records[0]) + mr.insert() + mr.submit() + + stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company", + "stock_in_hand_account") + + self.check_stock_ledger_entries("Stock Entry", mr.doc.name, + [["_Test Item", "_Test Warehouse", 50.0]]) + + self.check_gl_entries("Stock Entry", mr.doc.name, + sorted([ + [stock_in_hand_account, 5000.0, 0.0], + ["Stock Adjustment - _TC", 0.0, 5000.0] + ]) + ) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle): + # check stock ledger entries + sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where voucher_type = %s and voucher_no = %s order by item_code, warehouse""", + (voucher_type, voucher_no), as_dict=1) + self.assertTrue(sle) + + for i, sle in enumerate(sle): + self.assertEquals(expected_sle[i][0], sle.item_code) + self.assertEquals(expected_sle[i][1], sle.warehouse) + self.assertEquals(expected_sle[i][2], sle.actual_qty) + + def check_gl_entries(self, voucher_type, voucher_no, expected_gl_entries): + # check gl entries + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type=%s and voucher_no=%s + order by account asc, debit asc""", (voucher_type, voucher_no), as_dict=1) + self.assertTrue(gl_entries) + + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_gl_entries[i][0], gle.account) + self.assertEquals(expected_gl_entries[i][1], gle.debit) + self.assertEquals(expected_gl_entries[i][2], gle.credit) test_records = [ [ diff --git a/stock/doctype/warehouse/warehouse.txt b/stock/doctype/warehouse/warehouse.txt index d0dd73c086..d08b3ccff3 100644 --- a/stock/doctype/warehouse/warehouse.txt +++ b/stock/doctype/warehouse/warehouse.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-10 16:34:30", + "creation": "2013-03-07 18:50:32", "docstatus": 0, - "modified": "2013-02-04 11:35:53", + "modified": "2013-03-11 17:58:45", "modified_by": "Administrator", "owner": "Administrator" }, @@ -21,7 +21,8 @@ "name": "__common__", "parent": "Warehouse", "parentfield": "fields", - "parenttype": "DocType" + "parenttype": "DocType", + "read_only": 0 }, { "doctype": "DocPerm", @@ -190,7 +191,7 @@ "permlevel": 0 }, { - "description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge With\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.", + "description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge Into\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.", "doctype": "DocField", "fieldname": "merge_warehouses_section", "fieldtype": "Section Break", @@ -201,7 +202,7 @@ "doctype": "DocField", "fieldname": "merge_with", "fieldtype": "Link", - "label": "Merge With", + "label": "Merge Into", "options": "Warehouse", "permlevel": 2 }, @@ -221,24 +222,6 @@ "role": "Material Master Manager", "write": 1 }, - { - "amend": 0, - "cancel": 0, - "create": 0, - "doctype": "DocPerm", - "permlevel": 0, - "role": "Material User", - "write": 0 - }, - { - "amend": 0, - "cancel": 0, - "create": 0, - "doctype": "DocPerm", - "permlevel": 2, - "role": "Material User", - "write": 0 - }, { "cancel": 1, "create": 1, @@ -248,6 +231,26 @@ "write": 1 }, { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 0, + "role": "Material Manager", + "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 0, + "role": "Material User", + "write": 0 + }, + { + "amend": 0, + "cancel": 0, "create": 0, "doctype": "DocPerm", "permlevel": 2, From 758131b853b4efc56623d02458e341daa8a74388 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 12 Mar 2013 11:07:45 +0530 Subject: [PATCH 37/73] fixed slideshow --- home/page/attributions/attributions.html | 4 +++ .../style_settings/custom_template.css | 4 +-- website/templates/html/slideshow.html | 6 ++-- website/templates/pages/attributions.html | 36 +++++++++++++++++-- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/home/page/attributions/attributions.html b/home/page/attributions/attributions.html index 07da9fd89d..2d08c79dd0 100644 --- a/home/page/attributions/attributions.html +++ b/home/page/attributions/attributions.html @@ -26,6 +26,10 @@ Apache HTTPD web server The Number One HTTP Server On The Internet. + + Memcached + Free & open source, high-performance, distributed memory object caching system. + Python Programming Language The "batteries included" language that lets you write elegant code, quickly.

Python Libraries: diff --git a/website/doctype/style_settings/custom_template.css b/website/doctype/style_settings/custom_template.css index a67c9f1746..00c02bb2b3 100644 --- a/website/doctype/style_settings/custom_template.css +++ b/website/doctype/style_settings/custom_template.css @@ -12,7 +12,7 @@ body { background-color: #edede7; {% endif %} {% if doc.font or doc.google_web_font_for_text %} - font-family: '{{ doc.google_web_font_for_text or doc.font }}', Verdana, Sans !important; + font-family: '{{ doc.google_web_font_for_text or doc.font }}', 'Helvetica Neue', Arial, Sans !important; {% endif %} {% if doc.font_size %} font-size: {{ doc.font_size }} !important; @@ -31,7 +31,7 @@ div.outer { {% if doc.google_web_font_for_heading or doc.heading_font %} h1, h2, h3, h4, h5 { - font-family: '{{ doc.google_web_font_for_heading or doc.heading_font }}', Arial, 'Helvetica Neue' !important; + font-family: '{{ doc.google_web_font_for_heading or doc.heading_font }}', 'Helvetica Neue', Arial !important; } {% endif %} {% if doc.heading_text_style %} diff --git a/website/templates/html/slideshow.html b/website/templates/html/slideshow.html index 86417245b7..e0e9038d9f 100644 --- a/website/templates/html/slideshow.html +++ b/website/templates/html/slideshow.html @@ -5,10 +5,12 @@ {% for slide in obj.slides %}
+ {% if slide.heading or slide.description %} + {% endif %}
{% endfor %}
diff --git a/website/templates/pages/attributions.html b/website/templates/pages/attributions.html index 2d195ba9cd..9e4b50ddce 100644 --- a/website/templates/pages/attributions.html +++ b/website/templates/pages/attributions.html @@ -12,7 +12,7 @@ {% block content %}
-

This website is made using these Awesome Open Source Projects

+

This website is made using these awesome Open Source projects


@@ -37,6 +37,10 @@ + + + + + + + + @@ -96,13 +104,37 @@ + + + +
Apache HTTPD web server The Number One HTTP Server On The Internet.
MemcachedFree & open source, high-performance, distributed memory object caching system.
Python Programming Language The "batteries included" language that lets you write elegant code, quickly.

Python Libraries: @@ -80,6 +84,10 @@
SlickGrid A lightning fast JavaScript grid/spreadsheet.
FullCalendarFullCalendar is a jQuery plugin that provides a full-sized, drag and drop calendar.
Flot Charting Library Attractive JavaScript plotting for jQuery.JSColor - Color Picker HTML/Javascript Color Picker.
QUnitA JavaScript Unit Testing framework.
Downloadify - Flash Download Widget A tiny javascript + Flash library that enables the creation and download of text files without server interaction.
+ +
+

ERPNext License: GNU/General Public License

+
+

ERPNext - Open Source, web based ERP

+

Copyright © 2012, Web Notes Technologies Pvt Ltd, India

-

Note: A link to this page must be easily accessible.

+

This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version.

+ +

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 + GNU General Public License for more details.

+ +

For complete license see http://www.gnu.org/licenses/

+
+

Note: A link to this page must be easily accessible and all other ERPNext branding must remain as it is.

+
+

For more information please write to us at support@erpnext.com

{% endblock %} \ No newline at end of file From 1aff4c384d54939e39859c46de1d1f5379b2f57c Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 12 Mar 2013 11:22:30 +0530 Subject: [PATCH 38/73] website added banner --- .../website_settings/website_settings.txt | 29 ++++++++++++------- website/templates/html/navbar.html | 4 +-- website/templates/html/outer.html | 3 ++ website/utils.py | 9 ++---- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/website/doctype/website_settings/website_settings.txt b/website/doctype/website_settings/website_settings.txt index 6af0575a36..5bc4f71f68 100644 --- a/website/doctype/website_settings/website_settings.txt +++ b/website/doctype/website_settings/website_settings.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-25 11:35:10", + "creation": "2013-03-07 11:55:11", "docstatus": 0, - "modified": "2013-02-21 10:05:09", + "modified": "2013-03-12 11:17:11", "modified_by": "Administrator", "owner": "Administrator" }, @@ -72,24 +72,31 @@ "label": "Home Page is Products" }, { + "description": "Add a banner to the site. (small banners are usually good)", + "doctype": "DocField", + "fieldname": "banner", + "fieldtype": "Section Break", + "label": "Banner" + }, + { + "description": "Banner is above the Top Menu Bar.", + "doctype": "DocField", + "fieldname": "banner_html", + "fieldtype": "Small Text", + "label": "Banner HTML" + }, + { + "description": "Menu items in the Top Bar. For setting the color of the Top Bar, go to Style Settings", "doctype": "DocField", "fieldname": "top_bar", "fieldtype": "Section Break", "label": "Top Bar" }, - { - "description": "Background shade of the top menu bar", - "doctype": "DocField", - "fieldname": "top_bar_background", - "fieldtype": "Select", - "label": "Top Bar Background", - "options": "Black\nWhite" - }, { "description": "Brand is what appears on the top-right of the toolbar. If it is an image, make sure it\nhas a transparent background and use the <img /> tag. Keep size as 200px x 30px", "doctype": "DocField", "fieldname": "brand_html", - "fieldtype": "Text", + "fieldtype": "Small Text", "label": "Brand HTML" }, { diff --git a/website/templates/html/navbar.html b/website/templates/html/navbar.html index 5a30c6a6f1..8112499c04 100644 --- a/website/templates/html/navbar.html +++ b/website/templates/html/navbar.html @@ -1,7 +1,7 @@ -