Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py
index 47e3195..b31d549 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 fb290d2..1f165f0 100644
--- a/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -38,72 +38,199 @@
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/accounts/general_ledger.py b/accounts/general_ledger.py
index 215c351..8e0f408 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 @@
(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 f0bafdb..f714549 100644
--- a/accounts/page/financial_analytics/financial_analytics.js
+++ b/accounts/page/financial_analytics/financial_analytics.js
@@ -71,9 +71,11 @@
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 8f6b598..4a3f21e 100644
--- a/accounts/page/general_ledger/general_ledger.js
+++ b/accounts/page/general_ledger/general_ledger.js
@@ -108,7 +108,7 @@
// 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 7d8171e..fc082ea 100644
--- a/buying/page/purchase_analytics/purchase_analytics.js
+++ b/buying/page/purchase_analytics/purchase_analytics.js
@@ -120,19 +120,9 @@
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/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
index 47d139f..12ae4a8 100644
--- a/selling/doctype/sales_common/sales_common.py
+++ b/selling/doctype/sales_common/sales_common.py
@@ -341,12 +341,10 @@
# ========================================================================
# 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)
# ===========================================================================
diff --git a/selling/page/sales_analytics/sales_analytics.js b/selling/page/sales_analytics/sales_analytics.js
index 499c6c0..0b35af5 100644
--- a/selling/page/sales_analytics/sales_analytics.js
+++ b/selling/page/sales_analytics/sales_analytics.js
@@ -122,18 +122,8 @@
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/stock/doctype/delivery_note/test_delivery_note.py b/stock/doctype/delivery_note/test_delivery_note.py
index c2bb5d0..acdf8b9 100644
--- a/stock/doctype/delivery_note/test_delivery_note.py
+++ b/stock/doctype/delivery_note/test_delivery_note.py
@@ -109,7 +109,7 @@
"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,
diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py
index 05fc0e0..5dff992 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"""
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()