From b09dc46e68356c1c06c63dca9d2e5cc4aa2a10e0 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 23 Dec 2013 15:49:08 +0530 Subject: [PATCH 01/87] [flat discount] first commit --- .../doctype/sales_invoice/sales_invoice.py | 4 +- .../doctype/sales_invoice/sales_invoice.txt | 9 +- .../sales_invoice/test_sales_invoice.py | 94 +++++++++++++------ .../sales_taxes_and_charges.txt | 13 ++- controllers/accounts_controller.py | 27 ++++-- controllers/buying_controller.py | 5 +- controllers/selling_controller.py | 61 ++++++++---- public/js/transaction.js | 24 +++-- selling/sales_common.js | 58 ++++++++++-- 9 files changed, 218 insertions(+), 77 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index bfba30fa1b..d065dedd70 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -556,12 +556,12 @@ class DocType(SellingController): def make_tax_gl_entries(self, gl_entries): for tax in self.doclist.get({"parentfield": "other_charges"}): - if flt(tax.tax_amount): + if flt(tax.tax_amount_after_flat_discount): gl_entries.append( self.get_gl_dict({ "account": tax.account_head, "against": self.doc.debit_to, - "credit": flt(tax.tax_amount), + "credit": flt(tax.tax_amount_after_flat_discount), "remarks": self.doc.remarks, "cost_center": tax.cost_center }) diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 99bfe5cdf0..66cc0d930a 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-11-18 15:16:50", + "modified": "2013-12-19 11:10:11", "modified_by": "Administrator", "owner": "Administrator" }, @@ -362,6 +362,13 @@ "read_only": 1, "reqd": 1 }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "taxes", diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 9b740d1061..bc6d01ce60 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -16,7 +16,7 @@ class TestSalesInvoice(unittest.TestCase): w.submit() return w - def test_double_submission(self): + def atest_double_submission(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -27,7 +27,7 @@ class TestSalesInvoice(unittest.TestCase): w = webnotes.bean(w2) self.assertRaises(DocstatusTransitionError, w.submit) - def test_timestamp_change(self): + def atest_timestamp_change(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -42,9 +42,8 @@ class TestSalesInvoice(unittest.TestCase): time.sleep(1) self.assertRaises(TimestampMismatchError, w2.save) - def test_sales_invoice_calculation_base_currency(self): + def atest_sales_invoice_calculation_base_currency(self): si = webnotes.bean(copy=test_records[2]) - si.run_method("calculate_taxes_and_totals") si.insert() expected_values = { @@ -87,7 +86,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 1627.05) - def test_sales_invoice_calculation_export_currency(self): + def atest_sales_invoice_calculation_export_currency(self): si = webnotes.bean(copy=test_records[2]) si.doc.currency = "USD" si.doc.conversion_rate = 50 @@ -136,8 +135,53 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 32.54) + + def test_sales_invoice_flat_discount(self): + si = webnotes.bean(copy=test_records[3]) + si.doc.flat_discount = 22.98 + si.insert() + + expected_values = { + "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", + "base_ref_rate", "basic_rate", "amount"], + "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 492.44], + "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 738.68], + } + + # check if children are saved + self.assertEquals(len(si.doclist.get({"parentfield": "entries"})), + len(expected_values)-1) + + # check if item values are calculated + for d in si.doclist.get({"parentfield": "entries"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.doc.net_total, 1231.12) + self.assertEquals(si.doc.net_total_export, 1578.3) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "tax_amount_after_flat_discount", "total"], + "_Test Account Excise Duty - _TC": [140, 137.89, 1369.01], + "_Test Account Education Cess - _TC": [2.8, 2.76, 1371.77], + "_Test Account S&H Education Cess - _TC": [1.4, 1.38, 1373.15], + "_Test Account CST - _TC": [27.88, 27.46, 1400.61], + "_Test Account VAT - _TC": [156.25, 153.89, 1554.5], + "_Test Account Customs Duty - _TC": [125, 123.11, 1677.61], + "_Test Account Shipping Charges - _TC": [100, 100, 1777.61], + "_Test Account Discount - _TC": [-180.33, -177.61, 1600] + } + + for d in si.doclist.get({"parentfield": "other_charges"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) - def test_inclusive_rate_validations(self): + self.assertEquals(si.doc.grand_total, 1600) + self.assertEquals(si.doc.grand_total_export, 1600) + + def atest_inclusive_rate_validations(self): si = webnotes.bean(copy=test_records[2]) for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): tax.idx = i+1 @@ -148,16 +192,15 @@ class TestSalesInvoice(unittest.TestCase): si.doclist[i].included_in_print_rate = 1 # tax type "Actual" cannot be inclusive - self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals") + self.assertRaises(webnotes.ValidationError, si.insert) # taxes above included type 'On Previous Row Total' should also be included si.doclist[3].included_in_print_rate = 0 - self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals") + self.assertRaises(webnotes.ValidationError, si.insert) - def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): + def atest_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) - si.run_method("calculate_taxes_and_totals") si.insert() expected_values = { @@ -200,7 +243,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1622.98) self.assertEquals(si.doc.grand_total_export, 1622.98) - def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): + def atest_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) si.doc.currency = "USD" @@ -211,7 +254,6 @@ class TestSalesInvoice(unittest.TestCase): si.doclist[2].adj_rate = 20 si.doclist[9].rate = 5000 - si.run_method("calculate_taxes_and_totals") si.insert() expected_values = { @@ -254,11 +296,11 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 65205.16) self.assertEquals(si.doc.grand_total_export, 1304.1) - def test_outstanding(self): + def atest_outstanding(self): w = self.make() self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total) - def test_payment(self): + def atest_payment(self): webnotes.conn.sql("""delete from `tabGL Entry`""") w = self.make() @@ -277,7 +319,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Sales Invoice", w.doc.name, "outstanding_amount"), 561.8) - def test_time_log_batch(self): + def atest_time_log_batch(self): tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001") tlb.submit() @@ -300,7 +342,7 @@ class TestSalesInvoice(unittest.TestCase): 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): + def atest_sales_invoice_gl_entry_without_aii(self): self.clear_stock_account_balance() set_perpetual_inventory(0) si = webnotes.bean(copy=test_records[1]) @@ -333,7 +375,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) - def test_pos_gl_entry_with_aii(self): + def atest_pos_gl_entry_with_aii(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -393,7 +435,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): + def atest_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): self.clear_stock_account_balance() set_perpetual_inventory() webnotes.delete_doc("Account", "_Test Warehouse No Account - _TC") @@ -404,7 +446,6 @@ class TestSalesInvoice(unittest.TestCase): pr = webnotes.bean(copy=pr_test_records[0]) pr.doc.naming_series = "_T-Purchase Receipt-" pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC" - pr.run_method("calculate_taxes_and_totals") pr.insert() pr.submit() @@ -449,7 +490,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) set_perpetual_inventory(0) - def test_sales_invoice_gl_entry_with_aii_no_item_code(self): + def atest_sales_invoice_gl_entry_with_aii_no_item_code(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -477,7 +518,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): + def atest_sales_invoice_gl_entry_with_aii_non_stock_item(self): self.clear_stock_account_balance() set_perpetual_inventory() si_copy = webnotes.copy_doclist(test_records[1]) @@ -509,7 +550,6 @@ class TestSalesInvoice(unittest.TestCase): as pr_test_records pr = webnotes.bean(copy=pr_test_records[0]) pr.doc.naming_series = "_T-Purchase Receipt-" - pr.run_method("calculate_taxes_and_totals") pr.insert() pr.submit() @@ -530,7 +570,7 @@ class TestSalesInvoice(unittest.TestCase): ps = webnotes.bean(copy=pos_setting_test_records[0]) ps.insert() - def test_sales_invoice_with_advance(self): + def atest_sales_invoice_with_advance(self): from accounts.doctype.journal_voucher.test_journal_voucher \ import test_records as jv_test_records @@ -565,7 +605,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(not webnotes.conn.sql("""select name from `tabJournal Voucher Detail` where against_invoice=%s""", si.doc.name)) - def test_recurring_invoice(self): + def atest_recurring_invoice(self): from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date today = now_datetime().date() @@ -705,7 +745,7 @@ class TestSalesInvoice(unittest.TestCase): webnotes.conn.sql("delete from tabBin") webnotes.conn.sql("delete from `tabGL Entry`") - def test_serialized(self): + def atest_serialized(self): from stock.doctype.stock_entry.test_stock_entry import make_serialized_item from stock.doctype.serial_no.serial_no import get_serial_nos @@ -727,7 +767,7 @@ class TestSalesInvoice(unittest.TestCase): return si - def test_serialized_cancel(self): + def atest_serialized_cancel(self): from stock.doctype.serial_no.serial_no import get_serial_nos si = self.test_serialized() si.cancel() @@ -739,7 +779,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(webnotes.conn.get_value("Serial No", serial_nos[0], "delivery_document_no")) - def test_serialize_status(self): + def atest_serialize_status(self): from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos from stock.doctype.stock_entry.test_stock_entry import make_serialized_item diff --git a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt index b006c1d85c..3b31623e41 100644 --- a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt +++ b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-24 11:39:32", "docstatus": 0, - "modified": "2013-12-17 12:38:08", + "modified": "2013-12-20 12:31:08", "modified_by": "Administrator", "owner": "Administrator" }, @@ -131,12 +131,21 @@ "options": "Company:company:default_currency", "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "tax_amount_after_flat_discount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Tax Amount After Flat Discount", + "options": "Company:company:default_currency", + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "item_wise_tax_detail", "fieldtype": "Small Text", "hidden": 1, - "label": "Item Wise Tax Detail ", + "label": "Item Wise Tax Detail", "oldfieldname": "item_wise_tax_detail", "oldfieldtype": "Small Text", "read_only": 1 diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 5388ee120a..c76258ac27 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -16,7 +16,10 @@ class AccountsController(TransactionBase): self.set_missing_values(for_validate=True) self.validate_date_with_fiscal_year() if self.meta.get_field("currency"): + self.flat_discount_applied = False self.calculate_taxes_and_totals() + if hasattr(self, "apply_flat_discount"): + self.apply_flat_discount() self.validate_value("grand_total", ">=", 0) self.set_total_in_words() @@ -141,7 +144,7 @@ class AccountsController(TransactionBase): else: validate_conversion_rate(self.doc.currency, self.doc.conversion_rate, self.meta.get_label("conversion_rate"), self.doc.company) - + self.doc.conversion_rate = flt(self.doc.conversion_rate) self.item_doclist = self.doclist.get({"parentfield": self.fname}) self.tax_doclist = self.doclist.get({"parentfield": self.other_fname}) @@ -163,11 +166,16 @@ class AccountsController(TransactionBase): def initialize_taxes(self): for tax in self.tax_doclist: tax.item_wise_tax_detail = {} - for fieldname in ["tax_amount", "total", - "tax_amount_for_current_item", "grand_total_for_current_item", - "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]: - tax.fields[fieldname] = 0.0 - + tax_fields = ["total", "tax_amount_after_flat_discount", + "tax_amount_for_current_item", "grand_total_for_current_item", + "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] + + if not self.flat_discount_applied: + tax_fields.append("tax_amount") + + for fieldname in tax_fields: + tax.fields[fieldname] = 0.0 + self.validate_on_previous_row(tax) self.validate_inclusive_tax(tax) self.round_floats_in(tax) @@ -247,7 +255,10 @@ class AccountsController(TransactionBase): tax.tax_amount_for_current_item = current_tax_amount # accumulate tax amount into tax.tax_amount - tax.tax_amount += current_tax_amount + if not self.flat_discount_applied: + tax.tax_amount += current_tax_amount + + tax.tax_amount_after_flat_discount += current_tax_amount if tax.category: # if just for valuation, do not add the tax amount in total @@ -270,7 +281,7 @@ class AccountsController(TransactionBase): # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item - + def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) current_tax_amount = 0.0 diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index b52d51cf31..5e265e720f 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import webnotes from webnotes import _, msgprint from webnotes.utils import flt, _round - from buying.utils import get_item_details from setup.utils import get_company_currency @@ -162,6 +161,10 @@ class BuyingController(StockController): if not self.meta.get_field("item_tax_amount", parentfield=self.fname): for item in self.item_doclist: del item.fields["item_tax_amount"] + + if not self.meta.get_field("tax_amount_after_flat_discount", parentfield=self.other_fname): + for tax in self.tax_doclist: + del tax.fields["tax_amount_after_flat_discount"] def set_item_tax_amount(self, item, tax, current_tax_amount): """ diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 67c1462662..ede6ca9242 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -121,7 +121,7 @@ class SellingController(StockController): cumulated_tax_fraction += tax.tax_fraction_for_current_item - if cumulated_tax_fraction: + if cumulated_tax_fraction and not self.flat_discount_applied: item.amount = flt((item.export_amount * self.doc.conversion_rate) / (1 + cumulated_tax_fraction), self.precision("amount", item)) @@ -158,22 +158,23 @@ class SellingController(StockController): return current_tax_fraction def calculate_item_values(self): - for item in self.item_doclist: - self.round_floats_in(item) - - if item.adj_rate == 100: - item.export_rate = 0 - elif not item.export_rate: - item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)), - self.precision("export_rate", item)) - - item.export_amount = flt(item.export_rate * item.qty, - self.precision("export_amount", item)) + if not self.flat_discount_applied: + for item in self.item_doclist: + self.round_floats_in(item) + + if item.adj_rate == 100: + item.export_rate = 0 + elif not item.export_rate: + item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)), + self.precision("export_rate", item)) + + item.export_amount = flt(item.export_rate * item.qty, + self.precision("export_amount", item)) + + self._set_in_company_currency(item, "ref_rate", "base_ref_rate") + self._set_in_company_currency(item, "export_rate", "basic_rate") + self._set_in_company_currency(item, "export_amount", "amount") - self._set_in_company_currency(item, "ref_rate", "base_ref_rate") - self._set_in_company_currency(item, "export_rate", "basic_rate") - self._set_in_company_currency(item, "export_amount", "amount") - def calculate_net_total(self): self.doc.net_total = self.doc.net_total_export = 0.0 @@ -184,6 +185,7 @@ class SellingController(StockController): self.round_floats_in(self.doc, ["net_total", "net_total_export"]) def calculate_totals(self): + self.total_tax_excluding_actual = 0.0 self.doc.grand_total = flt(self.tax_doclist and \ self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total")) self.doc.grand_total_export = flt(self.doc.grand_total / self.doc.conversion_rate, @@ -191,12 +193,33 @@ class SellingController(StockController): self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total, self.precision("other_charges_total")) - self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export, - self.precision("other_charges_total_export")) + self.doc.other_charges_total_export = flt(self.doc.grand_total_export - + self.doc.net_total_export + flt(self.doc.flat_discount), self.precision("other_charges_total_export")) self.doc.rounded_total = _round(self.doc.grand_total) self.doc.rounded_total_export = _round(self.doc.grand_total_export) - + + if self.doc.flat_discount: + # calculate total tax for flat discount excluding actual + for tax in self.tax_doclist: + if tax.charge_type != "Actual": + self.total_tax_excluding_actual += tax.tax_amount + + self.total_amount_for_flat_discount = flt(self.doc.net_total + + self.total_tax_excluding_actual, self.precision("grand_total")) + + def apply_flat_discount(self): + distributed_amount = 0.0 + + if self.doc.flat_discount and self.total_amount_for_flat_discount: + # calculate item amount after flat discount + for item in self.item_doclist: + distributed_amount = self.doc.flat_discount * item.amount / self.total_amount_for_flat_discount + item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) + + self.flat_discount_applied = True + self.calculate_taxes_and_totals() + def calculate_outstanding_amount(self): # NOTE: # write_off_amount is only for POS Invoice diff --git a/public/js/transaction.js b/public/js/transaction.js index 4c4a810ed2..f06fc6b735 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -146,7 +146,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, validate: function() { + this.flat_discount_applied = false; this.calculate_taxes_and_totals(); + this.apply_flat_discount && this.apply_flat_discount(); }, set_default_values: function() { @@ -528,12 +530,18 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ initialize_taxes: function() { var me = this; + $.each(this.frm.tax_doclist, function(i, tax) { tax.item_wise_tax_detail = {}; - $.each(["tax_amount", "total", - "tax_amount_for_current_item", "grand_total_for_current_item", - "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"], - function(i, fieldname) { tax[fieldname] = 0.0 }); + tax_fields = ["total", "tax_amount_for_current_item", "grand_total_for_current_item", + "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] + + if (me.flat_discount_applied) + tax_fields.push("tax_amount_after_flat_discount"); + else + tax_fields.push("tax_amount"); + + $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); me.validate_on_previous_row(tax); me.validate_inclusive_tax(tax); @@ -567,7 +575,10 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ tax.tax_amount_for_current_item = current_tax_amount; // accumulate tax amount into tax.tax_amount - tax.tax_amount += current_tax_amount; + if (me.flat_discount_applied) + tax.tax_amount_after_flat_discount += current_tax_amount; + else + tax.tax_amount += current_tax_amount; // for buying if(tax.category) { @@ -617,9 +628,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ } else if(tax.charge_type == "On Previous Row Total") { current_tax_amount = (tax_rate / 100.0) * this.frm.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item; - } - + current_tax_amount = flt(current_tax_amount, precision("tax_amount", tax)); // store tax breakup for each item diff --git a/selling/sales_common.js b/selling/sales_common.js index dddc2b568d..d8fdb706b0 100644 --- a/selling/sales_common.js +++ b/selling/sales_common.js @@ -225,6 +225,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.calculate_taxes_and_totals(); }, + + flat_discount: function() { + this.flat_discount_applied = false; + this.calculate_taxes_and_totals(); + this.apply_flat_discount(); + }, commission_rate: function() { this.calculate_commission(); @@ -310,15 +316,17 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ calculate_item_values: function() { var me = this; - $.each(this.frm.item_doclist, function(i, item) { - wn.model.round_floats_in(item); - item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item)); - - me._set_in_company_currency(item, "ref_rate", "base_ref_rate"); - me._set_in_company_currency(item, "export_rate", "basic_rate"); - me._set_in_company_currency(item, "export_amount", "amount"); - }); + if (!this.flat_discount_applied) { + $.each(this.frm.item_doclist, function(i, item) { + wn.model.round_floats_in(item); + item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item)); + + me._set_in_company_currency(item, "ref_rate", "base_ref_rate"); + me._set_in_company_currency(item, "export_rate", "basic_rate"); + me._set_in_company_currency(item, "export_amount", "amount"); + }); + } }, determine_exclusive_rate: function() { @@ -341,7 +349,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ cumulated_tax_fraction += tax.tax_fraction_for_current_item; }); - if(cumulated_tax_fraction) { + if(cumulated_tax_fraction && !me.flat_discount_applied) { item.amount = flt( (item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), precision("amount", item)); @@ -396,7 +404,10 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ }, calculate_totals: function() { + var me = this; var tax_count = this.frm.tax_doclist.length; + this.total_tax_excluding_actual = 0.0; + this.frm.doc.grand_total = flt( tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total, precision("grand_total")); @@ -406,11 +417,38 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("other_charges_total")); this.frm.doc.other_charges_total_export = flt( - this.frm.doc.grand_total_export - this.frm.doc.net_total_export, + this.frm.doc.grand_total_export - this.frm.doc.net_total_export + this.frm.doc.flat_discount, precision("other_charges_total_export")); this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total); this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export); + + // calculate total amount for flat discount + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type != "Actual") { + me.total_tax_excluding_actual += flt(tax.tax_amount, precision("tax_amount", tax)); + } + }); + + this.total_amount_for_flat_discount = flt(this.frm.doc.net_total + + this.total_tax_excluding_actual, precision("grand_total")); + }, + + apply_flat_discount: function() { + var me = this; + var distributed_amount = 0.0; + + if (this.frm.doc.flat_discount && this.total_amount_for_flat_discount) { + // calculate item amount after flat discount + $.each(this.frm.item_doclist, function(i, item) { + distributed_amount = flt(me.frm.doc.flat_discount * item.amount / me.total_amount_for_flat_discount, + precision("amount", item)); + item.amount -= distributed_amount; + }); + + this.flat_discount_applied = true; + this.calculate_taxes_and_totals(); + } }, calculate_outstanding_amount: function() { From 63aa5fd67351e3478819d316f89f44aa0a4e73f4 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 24 Dec 2013 20:30:03 +0530 Subject: [PATCH 02/87] [flat discount] implemented flat discount on server side --- .../sales_invoice/test_sales_invoice.py | 86 +++++++++++-------- controllers/accounts_controller.py | 50 +++++++---- controllers/selling_controller.py | 42 +++++---- 3 files changed, 108 insertions(+), 70 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index bc6d01ce60..46a3f26d48 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -16,7 +16,7 @@ class TestSalesInvoice(unittest.TestCase): w.submit() return w - def atest_double_submission(self): + def test_double_submission(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -27,7 +27,7 @@ class TestSalesInvoice(unittest.TestCase): w = webnotes.bean(w2) self.assertRaises(DocstatusTransitionError, w.submit) - def atest_timestamp_change(self): + def test_timestamp_change(self): w = webnotes.bean(copy=test_records[0]) w.doc.docstatus = '0' w.insert() @@ -42,7 +42,7 @@ class TestSalesInvoice(unittest.TestCase): time.sleep(1) self.assertRaises(TimestampMismatchError, w2.save) - def atest_sales_invoice_calculation_base_currency(self): + def test_sales_invoice_calculation_base_currency(self): si = webnotes.bean(copy=test_records[2]) si.insert() @@ -86,7 +86,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 1627.05) - def atest_sales_invoice_calculation_export_currency(self): + def test_sales_invoice_calculation_export_currency(self): si = webnotes.bean(copy=test_records[2]) si.doc.currency = "USD" si.doc.conversion_rate = 50 @@ -138,14 +138,25 @@ class TestSalesInvoice(unittest.TestCase): def test_sales_invoice_flat_discount(self): si = webnotes.bean(copy=test_records[3]) - si.doc.flat_discount = 22.98 + si.doc.flat_discount = 104.95 + si.doclist.append({ + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account Service Tax - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Service Tax", + "rate": 10, + "row_id": 8, + "idx": 9 + }) si.insert() expected_values = { "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", "base_ref_rate", "basic_rate", "amount"], - "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 492.44], - "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 738.68], + "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 465.37], + "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 698.08], } # check if children are saved @@ -158,30 +169,31 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) # check net total - self.assertEquals(si.doc.net_total, 1231.12) + self.assertEquals(si.doc.net_total, 1163.45) self.assertEquals(si.doc.net_total_export, 1578.3) # check tax calculation expected_values = { "keys": ["tax_amount", "tax_amount_after_flat_discount", "total"], - "_Test Account Excise Duty - _TC": [140, 137.89, 1369.01], - "_Test Account Education Cess - _TC": [2.8, 2.76, 1371.77], - "_Test Account S&H Education Cess - _TC": [1.4, 1.38, 1373.15], - "_Test Account CST - _TC": [27.88, 27.46, 1400.61], - "_Test Account VAT - _TC": [156.25, 153.89, 1554.5], - "_Test Account Customs Duty - _TC": [125, 123.11, 1677.61], - "_Test Account Shipping Charges - _TC": [100, 100, 1777.61], - "_Test Account Discount - _TC": [-180.33, -177.61, 1600] + "_Test Account Excise Duty - _TC": [140, 130.31, 1293.76], + "_Test Account Education Cess - _TC": [2.8, 2.61, 1296.37], + "_Test Account S&H Education Cess - _TC": [1.4, 1.31, 1297.68], + "_Test Account CST - _TC": [27.88, 25.96, 1323.64], + "_Test Account VAT - _TC": [156.25, 145.43, 1469.07], + "_Test Account Customs Duty - _TC": [125, 116.35, 1585.42], + "_Test Account Shipping Charges - _TC": [100, 100, 1685.42], + "_Test Account Discount - _TC": [-180.33, -168.54, 1516.88], + "_Test Account Service Tax - _TC": [-18.03, -16.88, 1500] } for d in si.doclist.get({"parentfield": "other_charges"}): for i, k in enumerate(expected_values["keys"]): - self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) - self.assertEquals(si.doc.grand_total, 1600) - self.assertEquals(si.doc.grand_total_export, 1600) + self.assertEquals(si.doc.grand_total, 1500) + self.assertEquals(si.doc.grand_total_export, 1500) - def atest_inclusive_rate_validations(self): + def test_inclusive_rate_validations(self): si = webnotes.bean(copy=test_records[2]) for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): tax.idx = i+1 @@ -198,7 +210,7 @@ class TestSalesInvoice(unittest.TestCase): si.doclist[3].included_in_print_rate = 0 self.assertRaises(webnotes.ValidationError, si.insert) - def atest_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): + def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) si.insert() @@ -238,12 +250,12 @@ class TestSalesInvoice(unittest.TestCase): for d in si.doclist.get({"parentfield": "other_charges"}): for i, k in enumerate(expected_values["keys"]): - self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) self.assertEquals(si.doc.grand_total, 1622.98) self.assertEquals(si.doc.grand_total_export, 1622.98) - def atest_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): + def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): # prepare si = webnotes.bean(copy=test_records[3]) si.doc.currency = "USD" @@ -291,16 +303,16 @@ class TestSalesInvoice(unittest.TestCase): for d in si.doclist.get({"parentfield": "other_charges"}): for i, k in enumerate(expected_values["keys"]): - self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) self.assertEquals(si.doc.grand_total, 65205.16) self.assertEquals(si.doc.grand_total_export, 1304.1) - def atest_outstanding(self): + def test_outstanding(self): w = self.make() self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total) - def atest_payment(self): + def test_payment(self): webnotes.conn.sql("""delete from `tabGL Entry`""") w = self.make() @@ -319,7 +331,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Sales Invoice", w.doc.name, "outstanding_amount"), 561.8) - def atest_time_log_batch(self): + def test_time_log_batch(self): tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001") tlb.submit() @@ -342,7 +354,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing") - def atest_sales_invoice_gl_entry_without_aii(self): + def test_sales_invoice_gl_entry_without_aii(self): self.clear_stock_account_balance() set_perpetual_inventory(0) si = webnotes.bean(copy=test_records[1]) @@ -375,7 +387,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) - def atest_pos_gl_entry_with_aii(self): + def test_pos_gl_entry_with_aii(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -435,7 +447,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def atest_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): + def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): self.clear_stock_account_balance() set_perpetual_inventory() webnotes.delete_doc("Account", "_Test Warehouse No Account - _TC") @@ -490,7 +502,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(gle) set_perpetual_inventory(0) - def atest_sales_invoice_gl_entry_with_aii_no_item_code(self): + def test_sales_invoice_gl_entry_with_aii_no_item_code(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -518,7 +530,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) - def atest_sales_invoice_gl_entry_with_aii_non_stock_item(self): + def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): self.clear_stock_account_balance() set_perpetual_inventory() si_copy = webnotes.copy_doclist(test_records[1]) @@ -570,7 +582,7 @@ class TestSalesInvoice(unittest.TestCase): ps = webnotes.bean(copy=pos_setting_test_records[0]) ps.insert() - def atest_sales_invoice_with_advance(self): + def test_sales_invoice_with_advance(self): from accounts.doctype.journal_voucher.test_journal_voucher \ import test_records as jv_test_records @@ -605,7 +617,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(not webnotes.conn.sql("""select name from `tabJournal Voucher Detail` where against_invoice=%s""", si.doc.name)) - def atest_recurring_invoice(self): + def test_recurring_invoice(self): from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date today = now_datetime().date() @@ -745,7 +757,7 @@ class TestSalesInvoice(unittest.TestCase): webnotes.conn.sql("delete from tabBin") webnotes.conn.sql("delete from `tabGL Entry`") - def atest_serialized(self): + def test_serialized(self): from stock.doctype.stock_entry.test_stock_entry import make_serialized_item from stock.doctype.serial_no.serial_no import get_serial_nos @@ -767,7 +779,7 @@ class TestSalesInvoice(unittest.TestCase): return si - def atest_serialized_cancel(self): + def test_serialized_cancel(self): from stock.doctype.serial_no.serial_no import get_serial_nos si = self.test_serialized() si.cancel() @@ -779,7 +791,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertFalse(webnotes.conn.get_value("Serial No", serial_nos[0], "delivery_document_no")) - def atest_serialize_status(self): + def test_serialize_status(self): from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos from stock.doctype.stock_entry.test_stock_entry import make_serialized_item diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index c76258ac27..41d4859357 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -148,6 +148,10 @@ class AccountsController(TransactionBase): self.doc.conversion_rate = flt(self.doc.conversion_rate) self.item_doclist = self.doclist.get({"parentfield": self.fname}) self.tax_doclist = self.doclist.get({"parentfield": self.other_fname}) + + # for buying + if not hasattr(self, "flat_discount_applied"): + self.flat_discount_applied = False self.calculate_item_values() self.initialize_taxes() @@ -232,24 +236,26 @@ class AccountsController(TransactionBase): _on_previous_row_error("1 - %d" % (tax.row_id,)) def calculate_taxes(self): - for item in self.item_doclist: + # maintain actual tax rate based on idx + actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist + if tax.charge_type == "Actual"]) + + for n, item in enumerate(self.item_doclist): item_tax_map = self._load_item_tax_rate(item.item_tax_rate) for i, tax in enumerate(self.tax_doclist): # tax_amount represents the amount of tax for the current step current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map) + + # Adjust divisional loss to the last item + if tax.charge_type == "Actual": + actual_tax_dict[tax.idx] -= current_tax_amount; + if n == len(self.item_doclist) - 1: + current_tax_amount += actual_tax_dict[tax.idx] if hasattr(self, "set_item_tax_amount"): self.set_item_tax_amount(item, tax, current_tax_amount) - # case when net total is 0 but there is an actual type charge - # in this case add the actual amount to tax.tax_amount - # and tax.grand_total_for_current_item for the first such iteration - if tax.charge_type=="Actual" and \ - not (current_tax_amount or self.doc.net_total or tax.tax_amount): - zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax)) - current_tax_amount += zero_net_total_adjustment - # store tax_amount for current item as it will be used for # charge type = 'On Previous Row Amount' tax.tax_amount_for_current_item = current_tax_amount @@ -271,17 +277,31 @@ class AccountsController(TransactionBase): # note: grand_total_for_current_item contains the contribution of # item's amount, previously applied tax and the current tax on that item if i==0: - tax.grand_total_for_current_item = flt(item.amount + - current_tax_amount, self.precision("total", tax)) - + tax.grand_total_for_current_item = flt(item.amount + current_tax_amount, + self.precision("total", tax)) else: tax.grand_total_for_current_item = \ - flt(self.tax_doclist[i-1].grand_total_for_current_item + + flt(self.tax_doclist[i-1].grand_total_for_current_item + current_tax_amount, self.precision("total", tax)) + # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item + # set precision in the last item iteration + if n == len(self.item_doclist) - 1: + tax.total = flt(tax.total, self.precision("total", tax)) + tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + self.precision("tax_amount", tax)) + + # adjust discount loss in last tax iteration + if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied: + flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + + flat_discount_loss, self.precision("tax_amount", tax)) + tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) + def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) current_tax_amount = 0.0 @@ -300,9 +320,9 @@ class AccountsController(TransactionBase): elif tax.charge_type == "On Previous Row Total": current_tax_amount = (tax_rate / 100.0) * \ self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item - + current_tax_amount = flt(current_tax_amount, self.precision("tax_amount", tax)) - + # store tax breakup for each item key = item.item_code or item.item_name if tax.item_wise_tax_detail.get(key): diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index ede6ca9242..2571c3c83e 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -185,7 +185,6 @@ class SellingController(StockController): self.round_floats_in(self.doc, ["net_total", "net_total_export"]) def calculate_totals(self): - self.total_tax_excluding_actual = 0.0 self.doc.grand_total = flt(self.tax_doclist and \ self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total")) self.doc.grand_total_export = flt(self.doc.grand_total / self.doc.conversion_rate, @@ -199,26 +198,33 @@ class SellingController(StockController): self.doc.rounded_total = _round(self.doc.grand_total) self.doc.rounded_total_export = _round(self.doc.grand_total_export) - if self.doc.flat_discount: - # calculate total tax for flat discount excluding actual - for tax in self.tax_doclist: - if tax.charge_type != "Actual": - self.total_tax_excluding_actual += tax.tax_amount - - self.total_amount_for_flat_discount = flt(self.doc.net_total + - self.total_tax_excluding_actual, self.precision("grand_total")) - def apply_flat_discount(self): - distributed_amount = 0.0 + if self.doc.flat_discount: + total_amount_for_flat_discount = self.get_flat_discountable_amount() - if self.doc.flat_discount and self.total_amount_for_flat_discount: - # calculate item amount after flat discount - for item in self.item_doclist: - distributed_amount = self.doc.flat_discount * item.amount / self.total_amount_for_flat_discount - item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) + if total_amount_for_flat_discount: + # calculate item amount after flat discount + for item in self.item_doclist: + distributed_amount = self.doc.flat_discount * item.amount / total_amount_for_flat_discount + item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) - self.flat_discount_applied = True - self.calculate_taxes_and_totals() + self.flat_discount_applied = True + self.calculate_taxes_and_totals() + + def get_flat_discountable_amount(self): + actual_taxes_dict = {} + + for tax in self.tax_doclist: + if tax.charge_type == "Actual": + actual_taxes_dict.setdefault(tax.idx, tax.tax_amount) + elif tax.row_id in actual_taxes_dict: + actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * \ + flt(tax.rate) / 100 + actual_taxes_dict.setdefault(tax.idx, actual_tax_amount) + + total_amount_for_flat_discount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()), + self.precision("grand_total")) + return total_amount_for_flat_discount def calculate_outstanding_amount(self): # NOTE: From c53dbc7cdfec972872abd7febe60220acf75f0c3 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 25 Dec 2013 19:46:20 +0530 Subject: [PATCH 03/87] [flat discount] implemented flat discount on client side --- .../sales_invoice/test_sales_invoice.py | 53 ++++++++++++++- .../purchase_common/purchase_common.js | 8 +++ controllers/accounts_controller.py | 31 +++++---- public/js/transaction.js | 67 +++++++++++++------ selling/sales_common.js | 53 +++++++++------ stock/doctype/item/item.js | 3 +- stock/doctype/item/item.py | 4 +- 7 files changed, 162 insertions(+), 57 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 46a3f26d48..86308905b5 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -192,7 +192,57 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1500) self.assertEquals(si.doc.grand_total_export, 1500) - + + def test_flat_discount_gl_entry(self): + si = webnotes.bean(copy=test_records[3]) + si.doc.flat_discount = 104.95 + si.doclist.append({ + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account Service Tax - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Service Tax", + "rate": 10, + "row_id": 8, + "idx": 9 + }) + 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, 1500, 0.0], + [test_records[3][1]["income_account"], 0.0, 1163.45], + [test_records[3][3]["account_head"], 0.0, 130.31], + [test_records[3][4]["account_head"], 0.0, 2.61], + [test_records[3][5]["account_head"], 0.0, 1.31], + [test_records[3][6]["account_head"], 0.0, 25.96], + [test_records[3][7]["account_head"], 0.0, 145.43], + [test_records[3][8]["account_head"], 0.0, 116.35], + [test_records[3][9]["account_head"], 0.0, 100], + [test_records[3][10]["account_head"], 168.54, 0.0], + ["_Test Account Service Tax - _TC", 16.88, 0.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) + + # cancel + si.cancel() + + gle = webnotes.conn.sql("""select * from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name) + + self.assertFalse(gle) + def test_inclusive_rate_validations(self): si = webnotes.bean(copy=test_records[2]) for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): @@ -418,7 +468,6 @@ class TestSalesInvoice(unittest.TestCase): 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) - # print gl_entries stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"}) diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 9661f6edaf..92d127b267 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -360,6 +360,14 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }); } } + + if(this.frm.tax_doclist.length) { + if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_flat_discount", this.frm.doctype)) { + $.each(this.frm.tax_doclist, function(i, tax) { + delete tax["tax_amount_after_flat_discount"]; + }); + } + } }, calculate_outstanding_amount: function() { diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 41d4859357..bcb50da44c 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -227,11 +227,11 @@ class AccountsController(TransactionBase): "charge_type": tax.charge_type, }, raise_exception=True) elif tax.charge_type == "On Previous Row Amount" and \ - not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate): + not cint(self.tax_doclist[cint(tax.row_id) - 1].included_in_print_rate): # referred row should also be inclusive _on_previous_row_error(tax.row_id) elif tax.charge_type == "On Previous Row Total" and \ - not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:tax.row_id - 1]]): + not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:cint(tax.row_id) - 1]]): # all rows about the reffered tax should be inclusive _on_previous_row_error("1 - %d" % (tax.row_id,)) @@ -249,7 +249,7 @@ class AccountsController(TransactionBase): # Adjust divisional loss to the last item if tax.charge_type == "Actual": - actual_tax_dict[tax.idx] -= current_tax_amount; + actual_tax_dict[tax.idx] -= current_tax_amount if n == len(self.item_doclist) - 1: current_tax_amount += actual_tax_dict[tax.idx] @@ -283,24 +283,29 @@ class AccountsController(TransactionBase): tax.grand_total_for_current_item = \ flt(self.tax_doclist[i-1].grand_total_for_current_item + current_tax_amount, self.precision("total", tax)) - # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item # set precision in the last item iteration if n == len(self.item_doclist) - 1: - tax.total = flt(tax.total, self.precision("total", tax)) - tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, - self.precision("tax_amount", tax)) + self.round_off_totals(tax) - # adjust discount loss in last tax iteration + # adjust flat discount loss in last tax iteration if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied: - flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + - flat_discount_loss, self.precision("tax_amount", tax)) - tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) + self.adjust_flat_discount_loss(tax) + + def round_off_totals(self, tax): + tax.total = flt(tax.total, self.precision("total", tax)) + tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + self.precision("tax_amount", tax)) + + def adjust_flat_discount_loss(self, tax): + flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + + flat_discount_loss, self.precision("tax_amount", tax)) + tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) diff --git a/public/js/transaction.js b/public/js/transaction.js index f06fc6b735..542a1c1411 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -516,7 +516,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ this.validate_conversion_rate(); this.frm.item_doclist = this.get_item_doclist(); this.frm.tax_doclist = this.get_tax_doclist(); - + this.calculate_item_values(); this.initialize_taxes(); this.determine_exclusive_rate && this.determine_exclusive_rate(); @@ -533,12 +533,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ $.each(this.frm.tax_doclist, function(i, tax) { tax.item_wise_tax_detail = {}; - tax_fields = ["total", "tax_amount_for_current_item", "grand_total_for_current_item", + tax_fields = ["total", "tax_amount_after_flat_discount", + "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] - if (me.flat_discount_applied) - tax_fields.push("tax_amount_after_flat_discount"); - else + if (!me.flat_discount_applied) tax_fields.push("tax_amount"); $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); @@ -551,34 +550,41 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ calculate_taxes: function() { var me = this; + var actual_tax_dict = {}; + // maintain actual tax rate based on idx + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] = flt(tax.rate); + } + }); + $.each(this.frm.item_doclist, function(n, item) { var item_tax_map = me._load_item_tax_rate(item.item_tax_rate); - + $.each(me.frm.tax_doclist, function(i, tax) { // tax_amount represents the amount of tax for the current step var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map); - me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount); - - // case when net total is 0 but there is an actual type charge - // in this case add the actual amount to tax.tax_amount - // and tax.grand_total_for_current_item for the first such iteration - if(tax.charge_type == "Actual" && - !(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) { - var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax)); - current_tax_amount += zero_net_total_adjustment; + // Adjust divisional loss to the last item + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] -= current_tax_amount; + if (n == me.frm.item_doclist.length - 1) { + current_tax_amount += actual_tax_dict[tax.idx] } - + } + + me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount); + // store tax_amount for current item as it will be used for // charge type = 'On Previous Row Amount' tax.tax_amount_for_current_item = current_tax_amount; // accumulate tax amount into tax.tax_amount - if (me.flat_discount_applied) - tax.tax_amount_after_flat_discount += current_tax_amount; - else + if (!me.flat_discount_applied) tax.tax_amount += current_tax_amount; + + tax.tax_amount_after_flat_discount += current_tax_amount; // for buying if(tax.category) { @@ -603,9 +609,32 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ // in tax.total, accumulate grand total for each item tax.total += tax.grand_total_for_current_item; + + // set precision in the last item iteration + if (n == me.frm.item_doclist.length - 1) { + me.round_off_totals(tax); + + // adjust flat discount loss in last tax iteration + if ((i == me.frm.tax_doclist.length - 1) && me.flat_discount_applied) + me.adjust_flat_discount_loss(tax); + } }); }); }, + + round_off_totals: function(tax) { + tax.total = flt(tax.total, precision("total", tax)); + tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)); + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + precision("tax_amount", tax)); + }, + + adjust_flat_discount_loss: function(tax) { + var flat_discount_loss = this.frm.doc.grand_total - this.frm.doc.flat_discount - tax.total; + tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + + flat_discount_loss, precision("tax_amount", tax)); + tax.total = flt(tax.total + flat_discount_loss, precision("total", tax)); + }, get_current_tax_amount: function(item, tax, item_tax_map) { var tax_rate = this._get_tax_rate(tax, item_tax_map); diff --git a/selling/sales_common.js b/selling/sales_common.js index d8fdb706b0..91ec01dfcf 100644 --- a/selling/sales_common.js +++ b/selling/sales_common.js @@ -353,7 +353,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ item.amount = flt( (item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), precision("amount", item)); - + item.basic_rate = flt(item.amount / item.qty, precision("basic_rate", item)); if(item.adj_rate == 100) { @@ -393,20 +393,19 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ calculate_net_total: function() { var me = this; - this.frm.doc.net_total = this.frm.doc.net_total_export = 0.0; + $.each(this.frm.item_doclist, function(i, item) { me.frm.doc.net_total += item.amount; me.frm.doc.net_total_export += item.export_amount; }); - + wn.model.round_floats_in(this.frm.doc, ["net_total", "net_total_export"]); }, calculate_totals: function() { var me = this; var tax_count = this.frm.tax_doclist.length; - this.total_tax_excluding_actual = 0.0; this.frm.doc.grand_total = flt( tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total, @@ -416,40 +415,54 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("other_charges_total")); - this.frm.doc.other_charges_total_export = flt( - this.frm.doc.grand_total_export - this.frm.doc.net_total_export + this.frm.doc.flat_discount, + this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export - + this.frm.doc.net_total_export + this.frm.doc.flat_discount, precision("other_charges_total_export")); this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total); this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export); - - // calculate total amount for flat discount - $.each(this.frm.tax_doclist, function(i, tax) { - if (tax.charge_type != "Actual") { - me.total_tax_excluding_actual += flt(tax.tax_amount, precision("tax_amount", tax)); - } - }); - - this.total_amount_for_flat_discount = flt(this.frm.doc.net_total + - this.total_tax_excluding_actual, precision("grand_total")); }, apply_flat_discount: function() { var me = this; var distributed_amount = 0.0; - if (this.frm.doc.flat_discount && this.total_amount_for_flat_discount) { + if (this.frm.doc.flat_discount) { + var total_amount_for_flat_discount = this.get_flat_discountable_amount(); // calculate item amount after flat discount $.each(this.frm.item_doclist, function(i, item) { - distributed_amount = flt(me.frm.doc.flat_discount * item.amount / me.total_amount_for_flat_discount, - precision("amount", item)); - item.amount -= distributed_amount; + distributed_amount = me.frm.doc.flat_discount * item.amount / total_amount_for_flat_discount; + item.amount = flt(item.amount - distributed_amount, precision("amount", item)); }); this.flat_discount_applied = true; this.calculate_taxes_and_totals(); } }, + + get_flat_discountable_amount: function() { + var me = this; + var total_actual_tax = 0.0; + var actual_taxes_dict = {}; + + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type == "Actual") + actual_taxes_dict[tax.idx] = tax.tax_amount; + else if (actual_taxes_dict[tax.row_id] !== null) { + actual_tax_amount = flt(actual_taxes_dict[tax.row_id]) * flt(tax.rate) / 100; + actual_taxes_dict[tax.idx] = actual_tax_amount; + } + }); + + $.each(actual_taxes_dict, function(key, value) { + if (value) + total_actual_tax += value; + }); + + total_amount_for_flat_discount = flt(this.frm.doc.grand_total - total_actual_tax, + precision("grand_total")); + return total_amount_for_flat_discount; + }, calculate_outstanding_amount: function() { // NOTE: diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index c9aa75e7b7..6a1a7ef1c2 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -97,7 +97,8 @@ cur_frm.fields_dict['default_sales_cost_center'].get_query = function(doc) { cur_frm.fields_dict['item_tax'].grid.get_field("tax_type").get_query = function(doc, cdt, cdn) { return{ filters:[ - ['Account', 'account_type', 'in', 'Tax, Chargeable'], + ['Account', 'account_type', 'in', + 'Tax, Chargeable, Income Account, Expense Account'], ['Account', 'docstatus', '!=', 2] ] } diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index b5884b4111..0c4d5dd596 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -154,8 +154,8 @@ class DocType(DocListController, WebsiteGenerator): if d.tax_type: account_type = webnotes.conn.get_value("Account", d.tax_type, "account_type") - if account_type not in ['Tax', 'Chargeable']: - msgprint("'%s' is not Tax / Chargeable Account" % d.tax_type, raise_exception=1) + if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']: + msgprint("'%s' is not Tax / Chargeable / Income / Expense Account" % d.tax_type, raise_exception=1) else: if d.tax_type in check_list: msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1) From aebb844da974fac347bb1b76f8bf393fe7d70910 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 26 Dec 2013 18:05:41 +0530 Subject: [PATCH 04/87] [flat discount] added flat discount in print format and all selling doctypes --- .../Print Format/POS Invoice/POS Invoice.txt | 4 +-- .../Sales Invoice Classic.txt | 4 +-- .../Sales Invoice Modern.txt | 4 +-- .../Sales Invoice Spartan.txt | 4 +-- .../doctype/sales_invoice/sales_invoice.js | 6 ++-- .../doctype/sales_invoice/sales_invoice.txt | 17 ++++----- .../sales_taxes_and_charges_master.js | 36 ++++++++++++------- .../report/sales_register/sales_register.py | 5 +-- .../Quotation Classic/Quotation Classic.txt | 4 +-- .../Quotation Modern/Quotation Modern.txt | 4 +-- .../Quotation Spartan/Quotation Spartan.txt | 4 +-- .../Sales Order Classic.txt | 4 +-- .../Sales Order Modern/Sales Order Modern.txt | 4 +-- .../Sales Order Spartan.txt | 4 +-- selling/doctype/quotation/quotation.txt | 10 ++++-- selling/doctype/sales_order/sales_order.txt | 9 ++++- .../Delivery Note Classic.txt | 4 +-- .../Delivery Note Modern.txt | 4 +-- .../Delivery Note Spartan.txt | 4 +-- stock/doctype/delivery_note/delivery_note.txt | 13 +++++-- 20 files changed, 90 insertions(+), 58 deletions(-) diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index aab8e18491..d2cfa6d18a 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-09-13 17:17:47", + "modified": "2013-12-26 14:19:13", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt b/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt index fc99597766..4e8b12b943 100644 --- a/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt +++ b/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-08-07 20:14:53", + "modified": "2013-12-26 17:33:08", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt b/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt index 07946f7fcc..6808c009e6 100644 --- a/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt +++ b/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-08-07 20:12:16", + "modified": "2013-12-26 17:33:05", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt b/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt index 57c02fe2ec..45905fc2e1 100644 --- a/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt +++ b/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-08-07 19:50:51", + "modified": "2013-12-26 17:34:00", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index 7784005578..b3d784b383 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -25,7 +25,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte } // toggle to pos view if is_pos is 1 in user_defaults - if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos)) { + if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || this.frm.doc.is_pos)) { if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) { this.frm.set_value("is_pos", 1); this.is_pos(function() { @@ -144,8 +144,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte me.set_default_values(); me.set_dynamic_labels(); me.calculate_taxes_and_totals(); - - if(callback_fn) callback_fn() + + if(callback_fn) callback_fn(); } } }); diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 66cc0d930a..82a1eb5172 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-12-19 11:10:11", + "modified": "2013-12-26 17:50:21", "modified_by": "Administrator", "owner": "Administrator" }, @@ -362,13 +362,6 @@ "read_only": 1, "reqd": 1 }, - { - "doctype": "DocField", - "fieldname": "flat_discount", - "fieldtype": "Currency", - "label": "Flat Discount", - "options": "Company:company:default_currency" - }, { "doctype": "DocField", "fieldname": "taxes", @@ -459,6 +452,14 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency", + "print_hide": 0 + }, { "doctype": "DocField", "fieldname": "totals", diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index e2e5047028..0c5daf3667 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -19,6 +19,10 @@ cur_frm.pformat.net_total_export = function(doc) { return ''; } +cur_frm.pformat.flat_discount = function(doc) { + return ''; +} + cur_frm.pformat.grand_total_export = function(doc) { return ''; } @@ -33,10 +37,10 @@ cur_frm.pformat.in_words_export = function(doc) { cur_frm.pformat.other_charges= function(doc){ //function to make row of table - var make_row = function(title,val,bold){ + var make_row = function(title, val, bold){ var bstart = ''; var bend = ''; - return ''+(bold?bstart:'')+title+(bold?bend:'')+'' - +''+format_currency(val, doc.currency)+'' + return '' + (bold?bstart:'') + title + (bold?bend:'') + '' + +'' + format_currency(val, doc.currency) + '' +'' } @@ -52,7 +56,7 @@ cur_frm.pformat.other_charges= function(doc){ out =''; if (!doc.print_without_amount) { - var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges'); + var cl = getchildren('Sales Taxes and Charges', doc.name, 'other_charges'); // outer table var out='
'; @@ -60,6 +64,7 @@ cur_frm.pformat.other_charges= function(doc){ // main table out +=''; + if(!print_hide('net_total_export')) { out += make_row('Net Total', doc.net_total_export, 1); } @@ -68,26 +73,31 @@ cur_frm.pformat.other_charges= function(doc){ if(cl.length){ for(var i=0;i' + out += '' } - out +='
' + doc.in_words_export + '
'; + out += ''; } return out; } @@ -99,7 +109,7 @@ cur_frm.cscript.charge_type = function(doc, cdt, cdn) { d.charge_type = ''; } validated = false; - refresh_field('charge_type',d.name,'other_charges'); + refresh_field('charge_type', d.name, 'other_charges'); cur_frm.cscript.row_id(doc, cdt, cdn); cur_frm.cscript.rate(doc, cdt, cdn); cur_frm.cscript.tax_amount(doc, cdt, cdn); @@ -122,7 +132,7 @@ cur_frm.cscript.row_id = function(doc, cdt, cdn) { } } validated = false; - refresh_field('row_id',d.name,'other_charges'); + refresh_field('row_id', d.name, 'other_charges'); } /*---------------------- Get rate if account_head has account_type as TAX or CHARGEABLE-------------------------------------*/ @@ -152,7 +162,7 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) { d.rate = ''; } validated = false; - refresh_field('rate',d.name,'other_charges'); + refresh_field('rate', d.name, 'other_charges'); } cur_frm.cscript.tax_amount = function(doc, cdt, cdn) { @@ -166,5 +176,5 @@ cur_frm.cscript.tax_amount = function(doc, cdt, cdn) { d.tax_amount = ''; } validated = false; - refresh_field('tax_amount',d.name,'other_charges'); + refresh_field('tax_amount', d.name, 'other_charges'); }; \ No newline at end of file diff --git a/accounts/report/sales_register/sales_register.py b/accounts/report/sales_register/sales_register.py index 49b914e4a3..98ef93662d 100644 --- a/accounts/report/sales_register/sales_register.py +++ b/accounts/report/sales_register/sales_register.py @@ -79,7 +79,7 @@ def get_columns(invoice_list): tax_accounts = webnotes.conn.sql_list("""select distinct account_head from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' - and docstatus = 1 and ifnull(tax_amount, 0) != 0 + and docstatus = 1 and ifnull(tax_amount_after_flat_discount, 0) != 0 and parent in (%s) order by account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) @@ -126,7 +126,8 @@ def get_invoice_income_map(invoice_list): return invoice_income_map def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts): - tax_details = webnotes.conn.sql("""select parent, account_head, sum(tax_amount) as tax_amount + tax_details = webnotes.conn.sql("""select parent, account_head, + sum(tax_amount_after_flat_discount) as tax_amount from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) diff --git a/selling/Print Format/Quotation Classic/Quotation Classic.txt b/selling/Print Format/Quotation Classic/Quotation Classic.txt index e7588c4522..dc845290fe 100644 --- a/selling/Print Format/Quotation Classic/Quotation Classic.txt +++ b/selling/Print Format/Quotation Classic/Quotation Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:55:11", + "modified": "2013-12-26 17:45:37", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Quotation Modern/Quotation Modern.txt b/selling/Print Format/Quotation Modern/Quotation Modern.txt index 20d380dcbf..8b4b0d8f65 100644 --- a/selling/Print Format/Quotation Modern/Quotation Modern.txt +++ b/selling/Print Format/Quotation Modern/Quotation Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 20:12:11", + "modified": "2013-12-26 17:45:15", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Quotation Spartan/Quotation Spartan.txt b/selling/Print Format/Quotation Spartan/Quotation Spartan.txt index c5b4cb92b3..c4a1362ad3 100644 --- a/selling/Print Format/Quotation Spartan/Quotation Spartan.txt +++ b/selling/Print Format/Quotation Spartan/Quotation Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:53:01", + "modified": "2013-12-26 17:45:50", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Sales Order Classic/Sales Order Classic.txt b/selling/Print Format/Sales Order Classic/Sales Order Classic.txt index 7f2748ac0c..1d36ee6a77 100644 --- a/selling/Print Format/Sales Order Classic/Sales Order Classic.txt +++ b/selling/Print Format/Sales Order Classic/Sales Order Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:45:49", + "modified": "2013-12-26 17:35:51", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Sales Order Modern/Sales Order Modern.txt b/selling/Print Format/Sales Order Modern/Sales Order Modern.txt index e4102b2359..157c8eb29c 100644 --- a/selling/Print Format/Sales Order Modern/Sales Order Modern.txt +++ b/selling/Print Format/Sales Order Modern/Sales Order Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 20:12:23", + "modified": "2013-12-26 17:34:24", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt b/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt index 105b65b21b..8dce87eca4 100644 --- a/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt +++ b/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-08-07 19:45:59", + "modified": "2013-12-26 17:35:29", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/selling/doctype/quotation/quotation.txt b/selling/doctype/quotation/quotation.txt index 93346d3029..ce8a0d502b 100644 --- a/selling/doctype/quotation/quotation.txt +++ b/selling/doctype/quotation/quotation.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:08", "docstatus": 0, - "modified": "2013-12-14 17:25:46", + "modified": "2013-12-26 17:54:55", "modified_by": "Administrator", "owner": "Administrator" }, @@ -458,6 +458,13 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "totals", @@ -863,7 +870,6 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", - "match": "customer", "role": "Customer", "submit": 0, "write": 0 diff --git a/selling/doctype/sales_order/sales_order.txt b/selling/doctype/sales_order/sales_order.txt index 7a1af77947..34309cc1a5 100644 --- a/selling/doctype/sales_order/sales_order.txt +++ b/selling/doctype/sales_order/sales_order.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-18 12:39:59", "docstatus": 0, - "modified": "2013-11-03 14:20:16", + "modified": "2013-12-26 17:55:43", "modified_by": "Administrator", "owner": "Administrator" }, @@ -477,6 +477,13 @@ "read_only": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "totals", diff --git a/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt b/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt index 163dffaa87..d16b67fea6 100644 --- a/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt +++ b/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:31:11", "docstatus": 0, - "modified": "2013-08-07 19:44:55", + "modified": "2013-12-26 17:36:51", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt b/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt index f4323a9e1f..9965634355 100644 --- a/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt +++ b/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:31:11", "docstatus": 0, - "modified": "2013-08-07 20:12:29", + "modified": "2013-12-26 17:36:26", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt b/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt index 03fbef521e..2623d76183 100644 --- a/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt +++ b/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt @@ -2,14 +2,14 @@ { "creation": "2013-04-19 13:31:11", "docstatus": 0, - "modified": "2013-08-07 19:44:37", + "modified": "2013-12-26 17:37:14", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/stock/doctype/delivery_note/delivery_note.txt b/stock/doctype/delivery_note/delivery_note.txt index 480d45d014..9784b5a8fc 100644 --- a/stock/doctype/delivery_note/delivery_note.txt +++ b/stock/doctype/delivery_note/delivery_note.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:09", "docstatus": 0, - "modified": "2013-12-14 17:26:12", + "modified": "2013-12-26 18:01:33", "modified_by": "Administrator", "owner": "Administrator" }, @@ -465,7 +465,7 @@ "fieldname": "other_charges_total_export", "fieldtype": "Currency", "label": "Taxes and Charges Total", - "options": "company", + "options": "Company:company:default_currency", "print_hide": 1, "read_only": 1 }, @@ -487,6 +487,13 @@ "read_only": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "flat_discount", + "fieldtype": "Currency", + "label": "Flat Discount", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "totals", @@ -1058,7 +1065,7 @@ }, { "doctype": "DocPerm", - "match": "customer", + "match": "customer_name", "role": "Customer" } ] \ No newline at end of file From 13fa595282788ff67c6bfcabe53942582a03daf7 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 26 Dec 2013 18:14:44 +0530 Subject: [PATCH 05/87] [flat discount] pos print format fixed --- accounts/Print Format/POS Invoice/POS Invoice.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index d2cfa6d18a..0907c4a865 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-12-26 14:19:13", + "modified": "2013-12-26 18:13:48", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", From 2b1d8854d5aa8c9cf85a34d344a1d283097a7797 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 26 Dec 2013 20:31:42 +0530 Subject: [PATCH 06/87] [flat discount] added flat discount in pos --- accounts/doctype/sales_invoice/pos.js | 82 ++++++++++++++++----------- patches/patch_list.py | 29 ++++++---- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index adbdca1b63..81f6ae9124 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -30,12 +30,14 @@ erpnext.POS = Class.extend({ \
\
\ - \ - \ - \ - \ - \ -
Net Total
\ +
\ + \ + \ + \ + \ + \ +
Net Total
\ +
\ \ +
\ + \ + \ + \ + \ + \ +
Flat Discount\ + \ +
\ +
\
\ \ \ @@ -82,6 +95,10 @@ erpnext.POS = Class.extend({ me.refresh(); }); + this.wrapper.find('input.flat-discount').on("change", function() { + wn.model.set_value(me.frm.doctype, me.frm.docname, "flat_discount", this.value); + }); + this.call_function("delete-items", function() {me.remove_selected_item();}); this.call_function("make-payment", function() {me.make_payment();}); }, @@ -112,9 +129,9 @@ erpnext.POS = Class.extend({ }, make: function() { this.make_party(); - this.make_item_group(); - this.make_search(); this.make_barcode(); + this.make_search(); + this.make_item_group(); this.make_item_list(); }, make_party: function() { @@ -137,23 +154,23 @@ erpnext.POS = Class.extend({ me.party.toLowerCase(), this.value); }); }, - make_item_group: function() { + make_barcode: function() { var me = this; - this.item_group = wn.ui.form.make_control({ + this.barcode = wn.ui.form.make_control({ df: { - "fieldtype": "Link", - "options": "Item Group", - "label": "Item Group", - "fieldname": "pos_item_group", - "placeholder": "Item Group" + "fieldtype": "Data", + "label": "Barcode", + "fieldname": "pos_barcode", + "placeholder": "Barcode / Serial No" }, - parent: this.wrapper.find(".item-group-area"), + parent: this.wrapper.find(".barcode-area"), only_input: true, }); - this.item_group.make_input(); - this.item_group.$input.on("change", function() { - if(!me.item_group.autocomplete_open) - me.make_item_list(); + this.barcode.make_input(); + this.barcode.$input.on("keypress", function() { + if(me.barcode_timeout) + clearTimeout(me.barcode_timeout); + me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000); }); }, make_search: function() { @@ -176,23 +193,23 @@ erpnext.POS = Class.extend({ me.item_timeout = setTimeout(function() { me.make_item_list(); }, 1000); }); }, - make_barcode: function() { + make_item_group: function() { var me = this; - this.barcode = wn.ui.form.make_control({ + this.item_group = wn.ui.form.make_control({ df: { - "fieldtype": "Data", - "label": "Barcode", - "fieldname": "pos_barcode", - "placeholder": "Barcode / Serial No" + "fieldtype": "Link", + "options": "Item Group", + "label": "Item Group", + "fieldname": "pos_item_group", + "placeholder": "Item Group" }, - parent: this.wrapper.find(".barcode-area"), + parent: this.wrapper.find(".item-group-area"), only_input: true, }); - this.barcode.make_input(); - this.barcode.$input.on("keypress", function() { - if(me.barcode_timeout) - clearTimeout(me.barcode_timeout); - me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000); + this.item_group.make_input(); + this.item_group.$input.on("change", function() { + if(!me.item_group.autocomplete_open) + me.make_item_list(); }); }, make_item_list: function() { @@ -321,6 +338,7 @@ erpnext.POS = Class.extend({ refresh: function() { var me = this; this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]); + this.wrapper.find('input.flat-discount').val(this.frm.doc.flat_discount); this.barcode.set_input(""); this.show_items_in_item_cart(); diff --git a/patches/patch_list.py b/patches/patch_list.py index 608ba77168..b567eb1c19 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -173,18 +173,18 @@ patch_list = [ "patches.july_2013.p05_custom_doctypes_in_list_view", "patches.july_2013.p06_same_sales_rate", "patches.july_2013.p07_repost_billed_amt_in_sales_cycle", - "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-07-22", - "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-07-22", - "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-07-22", - "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-07-22", - "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-07-22", - "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-07-22", - "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-07-22", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-12-26", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-12-26", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-12-26", "patches.july_2013.p08_custom_print_format_net_total_export", "patches.july_2013.p09_remove_website_pyc", "patches.july_2013.p10_change_partner_user_to_website_user", @@ -263,4 +263,9 @@ patch_list = [ "patches.1311.p08_email_digest_recipients", "execute:webnotes.delete_doc('DocType', 'Warehouse Type')", "patches.1312.p02_update_item_details_in_item_price", + "execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2013-12-26", + "execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2013-12-26", + "execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2013-12-26", + "execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2013-12-26", ] \ No newline at end of file From 31ccf9a80bd7fa61e3debe40904995995cd370c0 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 27 Dec 2013 14:21:39 +0530 Subject: [PATCH 07/87] [flat discount] fixed test cases for stock entry --- accounts/doctype/sales_invoice/pos.js | 3 ++- buying/doctype/purchase_order/test_purchase_order.py | 1 - stock/doctype/stock_entry/stock_entry.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index 81f6ae9124..9e11fa80d2 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -53,7 +53,8 @@ erpnext.POS = Class.extend({
\
\ \ - \ + \ + \ \
Flat DiscountFlat Discount\ \ diff --git a/buying/doctype/purchase_order/test_purchase_order.py b/buying/doctype/purchase_order/test_purchase_order.py index f6c435c6fb..23d5ea4dca 100644 --- a/buying/doctype/purchase_order/test_purchase_order.py +++ b/buying/doctype/purchase_order/test_purchase_order.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt - from __future__ import unicode_literals import unittest import webnotes diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 2e7e2a4066..8eddbd4560 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -290,7 +290,7 @@ class DocType(StockController): if not returnable_qty: webnotes.throw("{item}: {item_code} {returned}".format( item=_("Item"), item_code=item.item_code, - returned=_("already returned though some other documents"))) + returned=_("already returned though some other documents")), StockOverReturnError) elif item.transfer_qty > returnable_qty: webnotes.throw("{item}: {item_code}, {returned}: {qty}".format( item=_("Item"), item_code=item.item_code, From d51f805b783f02804375e20f2b905dfa4ce478ca Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 27 Dec 2013 17:33:55 +0530 Subject: [PATCH 08/87] Rewritten General Ledger report with grouping functions --- .../report/general_ledger/general_ledger.js | 54 +++-- .../report/general_ledger/general_ledger.py | 199 ++++++++++++------ 2 files changed, 164 insertions(+), 89 deletions(-) diff --git a/accounts/report/general_ledger/general_ledger.js b/accounts/report/general_ledger/general_ledger.js index 7985277115..f2e60b6447 100644 --- a/accounts/report/general_ledger/general_ledger.js +++ b/accounts/report/general_ledger/general_ledger.js @@ -11,26 +11,6 @@ wn.query_reports["General Ledger"] = { "default": wn.defaults.get_user_default("company"), "reqd": 1 }, - { - "fieldname":"account", - "label": wn._("Account"), - "fieldtype": "Link", - "options": "Account" - }, - { - "fieldname":"voucher_no", - "label": wn._("Voucher No"), - "fieldtype": "Data", - }, - { - "fieldname":"group_by", - "label": wn._("Group by"), - "fieldtype": "Select", - "options": "\nGroup by Account\nGroup by Voucher" - }, - { - "fieldtype": "Break", - }, { "fieldname":"from_date", "label": wn._("From Date"), @@ -46,6 +26,40 @@ wn.query_reports["General Ledger"] = { "default": wn.datetime.get_today(), "reqd": 1, "width": "60px" + }, + { + "fieldtype": "Break", + }, + { + "fieldname":"account", + "label": wn._("Account"), + "fieldtype": "Link", + "options": "Account", + "get_query": function() { + var company = wn.query_report.filters_by_name.company.get_value(); + return { + "query": "accounts.utils.get_account_list", + "filters": { + "company": company, + } + } + } + }, + { + "fieldname":"voucher_no", + "label": wn._("Voucher No"), + "fieldtype": "Data", + }, + { + "fieldname":"group_by_voucher", + "label": wn._("Group by Voucher"), + "fieldtype": "Check", + "default": 1 + }, + { + "fieldname":"group_by_account", + "label": wn._("Group by Account"), + "fieldtype": "Check", } ] } \ No newline at end of file diff --git a/accounts/report/general_ledger/general_ledger.py b/accounts/report/general_ledger/general_ledger.py index b88d5bc296..2efc8241c0 100644 --- a/accounts/report/general_ledger/general_ledger.py +++ b/accounts/report/general_ledger/general_ledger.py @@ -3,109 +3,170 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import flt, add_days +from webnotes.utils import cstr, flt from webnotes import _ -from accounts.utils import get_balance_on def execute(filters=None): - account_details = webnotes.conn.get_value("Account", filters["account"], - ["debit_or_credit", "group_or_ledger"], as_dict=True) if filters.get("account") else None + account_details = {} + for acc in webnotes.conn.sql("""select name, debit_or_credit, group_or_ledger + from tabAccount""", as_dict=1): + account_details.setdefault(acc.name, acc) + validate_filters(filters, account_details) columns = get_columns() - data = [] - if filters.get("group_by"): - data += get_grouped_gle(filters) - else: - data += get_gl_entries(filters) - if data: - data.append(get_total_row(data)) + + res = get_result(filters, account_details) - if account_details: - data = [get_opening_balance_row(filters, account_details.debit_or_credit)] + data + \ - [get_closing_balance_row(filters, account_details.debit_or_credit)] - - return columns, data + return columns, res def validate_filters(filters, account_details): - if account_details and account_details.group_or_ledger == "Ledger" \ - and filters.get("group_by") == "Group by Account": + if filters.get("account") and filters.get("group_by_account") \ + and account_details[filters.account].group_or_ledger == "Ledger": webnotes.throw(_("Can not filter based on Account, if grouped by Account")) - if filters.get("voucher_no") and filters.get("group_by") == "Group by Voucher": + if filters.get("voucher_no") and filters.get("group_by_voucher"): webnotes.throw(_("Can not filter based on Voucher No, if grouped by Voucher")) + + if filters.from_date > filters.to_date: + webnotes.throw(_("From Date must be before To Date")) def get_columns(): return ["Posting Date:Date:100", "Account:Link/Account:200", "Debit:Float:100", "Credit:Float:100", "Voucher Type::120", "Voucher No::160", "Link::20", - "Cost Center:Link/Cost Center:100", "Remarks::200"] + "Against Account::120", "Cost Center:Link/Cost Center:100", "Remarks::200"] -def get_opening_balance_row(filters, debit_or_credit): - opening_balance = get_balance_on(filters["account"], add_days(filters["from_date"], -1)) - return get_balance_row(opening_balance, debit_or_credit, "Opening Balance") - -def get_closing_balance_row(filters, debit_or_credit): - closing_balance = get_balance_on(filters["account"], filters["to_date"]) - return get_balance_row(closing_balance, debit_or_credit, "Closing Balance") - -def get_balance_row(balance, debit_or_credit, balance_label): - if debit_or_credit == "Debit": - return ["", balance_label, balance, 0.0, "", "", ""] - else: - return ["", balance_label, 0.0, balance, "", "", ""] +def get_result(filters, account_details): + gl_entries = get_gl_entries(filters) + + data = get_data_with_opening_closing(filters, account_details, gl_entries) + result = get_result_as_list(data) + + return result + def get_gl_entries(filters): - gl_entries = webnotes.conn.sql("""select - posting_date, account, debit, credit, voucher_type, voucher_no, cost_center, remarks - from `tabGL Entry` - where company=%(company)s - and posting_date between %(from_date)s and %(to_date)s - {conditions} - order by posting_date, account"""\ - .format(conditions=get_conditions(filters)), filters, as_list=1) + group_by_condition = "group by voucher_type, voucher_no, account" \ + if filters.get("group_by_voucher") else "group by name" - for d in gl_entries: - icon = """""" \ - % ("/".join(["#Form", d[4], d[5]]),) - d.insert(6, icon) + gl_entries = webnotes.conn.sql("""select posting_date, account, + sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit, + voucher_type, voucher_no, cost_center, remarks, is_advance, against + from `tabGL Entry` + where company=%(company)s {conditions} + {group_by_condition} + order by posting_date, account"""\ + .format(conditions=get_conditions(filters), group_by_condition=group_by_condition), + filters, as_dict=1) return gl_entries - + def get_conditions(filters): conditions = [] if filters.get("account"): lft, rgt = webnotes.conn.get_value("Account", filters["account"], ["lft", "rgt"]) conditions.append("""account in (select name from tabAccount where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt)) + else: + conditions.append("posting_date between %(from_date)s and %(to_date)s") + if filters.get("voucher_no"): conditions.append("voucher_no=%(voucher_no)s") return "and {}".format(" and ".join(conditions)) if conditions else "" - -def get_grouped_gle(filters): - gle_map = {} - gle = get_gl_entries(filters) - for d in gle: - gle_map.setdefault(d[1 if filters["group_by"]=="Group by Account" else 5], []).append(d) - + +def get_data_with_opening_closing(filters, account_details, gl_entries): data = [] - for entries in gle_map.values(): - subtotal_debit = subtotal_credit = 0.0 - for entry in entries: - data.append(entry) - subtotal_debit += flt(entry[2]) - subtotal_credit += flt(entry[3]) - - data.append(["", "Total", subtotal_debit, subtotal_credit, "", "", ""]) + gle_map = initialize_gle_map(gl_entries) + + opening, total_debit, total_credit, gle_map = get_accountwise_gle(filters, gl_entries, gle_map) + + # Opening for filtered account + if filters.get("account"): + data += [get_balance_row("Opening", account_details[filters.account].debit_or_credit, + opening), {}] + + for acc, acc_dict in gle_map.items(): + if acc_dict.entries: + # Opening for individual ledger, if grouped by account + if filters.get("group_by_account"): + data.append(get_balance_row("Opening", account_details[acc].debit_or_credit, + acc_dict.opening)) + + data += acc_dict.entries + + # Totals and closing for individual ledger, if grouped by account + if filters.get("group_by_account"): + data += [{"account": "Totals", "debit": acc_dict.total_debit, + "credit": acc_dict.total_credit}, + get_balance_row("Closing (Opening + Totals)", + account_details[acc].debit_or_credit, (acc_dict.opening + + acc_dict.total_debit - acc_dict.total_credit)), {}] + + # Total debit and credit between from and to date + if total_debit or total_credit: + data.append({"account": "Totals", "debit": total_debit, "credit": total_credit}) + + # Closing for filtered account + if filters.get("account"): + data.append(get_balance_row("Closing (Opening + Totals)", + account_details[filters.account].debit_or_credit, + (opening + total_debit - total_credit))) - if data: - data.append(get_total_row(gle)) return data + +def initialize_gle_map(gl_entries): + gle_map = webnotes._dict() + for gle in gl_entries: + gle_map.setdefault(gle.account, webnotes._dict({ + "opening": 0, + "entries": [], + "total_debit": 0, + "total_credit": 0, + "closing": 0 + })) + return gle_map + +def get_accountwise_gle(filters, gl_entries, gle_map): + opening, total_debit, total_credit = 0, 0, 0 -def get_total_row(gle): - total_debit = total_credit = 0.0 - for d in gle: - total_debit += flt(d[2]) - total_credit += flt(d[3]) + for gle in gl_entries: + amount = flt(gle.debit) - flt(gle.credit) + if filters.get("account") and (gle.posting_date < filters.from_date + or cstr(gle.is_advance) == "Yes"): + gle_map[gle.account].opening += amount + opening += amount + elif gle.posting_date < filters.to_date: + gle_map[gle.account].entries.append(gle) + gle_map[gle.account].total_debit += flt(gle.debit) + gle_map[gle.account].total_credit += flt(gle.credit) + + total_debit += flt(gle.debit) + total_credit += flt(gle.credit) + + return opening, total_debit, total_credit, gle_map + +def get_balance_row(label, debit_or_credit, balance): + return { + "account": label, + "debit": balance if debit_or_credit=="Debit" else 0, + "credit": -1*balance if debit_or_credit=="Credit" else 0, + } + +def get_result_as_list(data): + result = [] + for d in data: + result.append([d.get("posting_date"), d.get("account"), d.get("debit"), + d.get("credit"), d.get("voucher_type"), d.get("voucher_no"), + get_voucher_link(d.get("voucher_type"), d.get("voucher_no")), + d.get("against"), d.get("cost_center"), d.get("remarks")]) + + return result + +def get_voucher_link(voucher_type, voucher_no): + icon = "" + if voucher_type and voucher_no: + icon = """ + """ % ("/".join(["#Form", voucher_type, voucher_no])) - return ["", "Total Debit/Credit", total_debit, total_credit, "", "", ""] \ No newline at end of file + return icon \ No newline at end of file From e761fe89e22b131fc084f19b0ad6b01c797189c3 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 27 Dec 2013 17:35:39 +0530 Subject: [PATCH 09/87] Stock Entry catch exceptions for testcase --- accounts/doctype/sales_invoice/test_sales_invoice.py | 1 - stock/doctype/stock_entry/stock_entry.py | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 9b740d1061..5a573f9441 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -364,7 +364,6 @@ class TestSalesInvoice(unittest.TestCase): 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) - # print gl_entries stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"}) diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 2e7e2a4066..7dec8785c4 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -290,11 +290,12 @@ class DocType(StockController): if not returnable_qty: webnotes.throw("{item}: {item_code} {returned}".format( item=_("Item"), item_code=item.item_code, - returned=_("already returned though some other documents"))) + returned=_("already returned though some other documents")), + StockOverReturnError) elif item.transfer_qty > returnable_qty: webnotes.throw("{item}: {item_code}, {returned}: {qty}".format( item=_("Item"), item_code=item.item_code, - returned=_("Max Returnable Qty"), qty=returnable_qty)) + returned=_("Max Returnable Qty"), qty=returnable_qty), StockOverReturnError) def get_already_returned_item_qty(self, ref_fieldname): return dict(webnotes.conn.sql("""select item_code, sum(transfer_qty) as qty From a4f99428d78cc22b616a980f57003d751c816e68 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 27 Dec 2013 17:36:17 +0530 Subject: [PATCH 10/87] Fixes in time log batch --- projects/doctype/time_log_batch/time_log_batch.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/projects/doctype/time_log_batch/time_log_batch.py b/projects/doctype/time_log_batch/time_log_batch.py index ccb0a25624..593dc222f1 100644 --- a/projects/doctype/time_log_batch/time_log_batch.py +++ b/projects/doctype/time_log_batch/time_log_batch.py @@ -28,7 +28,7 @@ class DocType: }) def validate_time_log_is_submitted(self, tl): - if tl.status != "Submitted": + if tl.status != "Submitted" and self.doc.docstatus == 0: webnotes.msgprint(_("Time Log must have status 'Submitted'") + \ " :" + tl.name + " (" + _(tl.status) + ")", raise_exception=True) @@ -57,7 +57,4 @@ class DocType: tl = webnotes.bean("Time Log", d.time_log) tl.doc.time_log_batch = time_log_batch tl.doc.sales_invoice = self.doc.sales_invoice - tl.update_after_submit() - - - \ No newline at end of file + tl.update_after_submit() \ No newline at end of file From ab9d755e4d612fdd3d300f879c20834f3dd21686 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Mon, 30 Dec 2013 18:18:01 +0600 Subject: [PATCH 11/87] bumped to version 3.4.0 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index b57ba61ba1..de048e5b53 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.3.8", + "app_version": "3.4.0", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.3.2" + "requires_framework_version": "==3.4.0" } \ No newline at end of file From ba7221c3325acd48c1f1534921d67d11003ba718 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Mon, 30 Dec 2013 19:28:03 +0600 Subject: [PATCH 12/87] bumped to version 3.4.1 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index de048e5b53..2309618f9d 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.0", + "app_version": "3.4.1", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.4.0" + "requires_framework_version": "==3.4.1" } \ No newline at end of file From 9cd9836e1813c6aa2bc5d7f0607472826ffb3a2a Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Mon, 30 Dec 2013 20:04:38 +0600 Subject: [PATCH 13/87] bumped to version 3.4.2 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 2309618f9d..80f1952f1a 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.1", + "app_version": "3.4.2", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.4.1" + "requires_framework_version": "==3.4.2" } \ No newline at end of file From 2a3d7e660fbb4d7490e017cd34f12ca707f4f106 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 30 Dec 2013 20:28:14 +0530 Subject: [PATCH 14/87] Fixes in general ledger report --- accounts/report/general_ledger/general_ledger.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/report/general_ledger/general_ledger.js b/accounts/report/general_ledger/general_ledger.js index f2e60b6447..96682f9647 100644 --- a/accounts/report/general_ledger/general_ledger.js +++ b/accounts/report/general_ledger/general_ledger.js @@ -38,7 +38,7 @@ wn.query_reports["General Ledger"] = { "get_query": function() { var company = wn.query_report.filters_by_name.company.get_value(); return { - "query": "accounts.utils.get_account_list", + "doctype": "Account", "filters": { "company": company, } From 424b4a4b36d7b650365bc752fc7729ff725ff968 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 31 Dec 2013 10:24:28 +0530 Subject: [PATCH 15/87] Supplier bill info in accounts payable report --- .../accounts_payable/accounts_payable.py | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/accounts/report/accounts_payable/accounts_payable.py b/accounts/report/accounts_payable/accounts_payable.py index e5489d100f..f9266dc9ea 100644 --- a/accounts/report/accounts_payable/accounts_payable.py +++ b/accounts/report/accounts_payable/accounts_payable.py @@ -19,8 +19,8 @@ def execute(filters=None): for gle in get_gl_entries(filters, before_report_date=False)] account_supplier_type_map = get_account_supplier_type_map() - pi_map = get_pi_map() - + voucher_detail_map = get_voucher_details() + # Age of the invoice on this date age_on = getdate(filters.get("report_date")) > getdate(nowdate()) \ and nowdate() or filters.get("report_date") @@ -29,14 +29,8 @@ def execute(filters=None): for gle in entries: if cstr(gle.against_voucher) == gle.voucher_no or not gle.against_voucher \ or [gle.against_voucher_type, gle.against_voucher] in entries_after_report_date: - if gle.voucher_type == "Purchase Invoice": - pi_info = pi_map.get(gle.voucher_no) - due_date = pi_info.get("due_date") - bill_no = pi_info.get("bill_no") - bill_date = pi_info.get("bill_date") - else: - due_date = bill_no = bill_date = "" - + voucher_details = voucher_detail_map.get(gle.voucher_type, {}).get(gle.voucher_no, {}) + invoiced_amount = gle.credit > 0 and gle.credit or 0 outstanding_amount = get_outstanding_amount(gle, filters.get("report_date") or nowdate()) @@ -44,13 +38,15 @@ def execute(filters=None): if abs(flt(outstanding_amount)) > 0.01: paid_amount = invoiced_amount - outstanding_amount row = [gle.posting_date, gle.account, account_supplier.get(gle.account, ""), - gle.voucher_type, gle.voucher_no, - gle.remarks, account_supplier_type_map.get(gle.account), due_date, bill_no, - bill_date, invoiced_amount, paid_amount, outstanding_amount] + gle.voucher_type, gle.voucher_no, gle.remarks, + account_supplier_type_map.get(gle.account), + voucher_details.get("due_date", ""), voucher_details.get("bill_no", ""), + voucher_details.get("bill_date", ""), invoiced_amount, + paid_amount, outstanding_amount] # Ageing if filters.get("ageing_based_on") == "Due Date": - ageing_based_on_date = due_date + ageing_based_on_date = voucher_details.get("due_date", "") else: ageing_based_on_date = gle.posting_date @@ -112,14 +108,15 @@ def get_account_supplier_type_map(): return account_supplier_type_map -def get_pi_map(): - """ get due_date from sales invoice """ - pi_map = {} - for t in webnotes.conn.sql("""select name, due_date, bill_no, bill_date - from `tabPurchase Invoice`""", as_dict=1): - pi_map[t.name] = t +def get_voucher_details(): + voucher_details = {} + for dt in ["Purchase Invoice", "Journal Voucher"]: + voucher_details.setdefault(dt, webnotes._dict()) + for t in webnotes.conn.sql("""select name, due_date, bill_no, bill_date + from `tab%s`""" % dt, as_dict=1): + voucher_details[dt].setdefault(t.name, t) - return pi_map + return voucher_details def get_outstanding_amount(gle, report_date): payment_amount = webnotes.conn.sql(""" From ffe8af3f2f14c2d16c07c81d41b84131c16c651c Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 31 Dec 2013 14:42:36 +0600 Subject: [PATCH 16/87] bumped to version 3.4.3 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 80f1952f1a..c09c2afac9 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.2", + "app_version": "3.4.3", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { From 432b86344ee664ebed22f560f0ce139241cb5858 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 31 Dec 2013 15:07:58 +0530 Subject: [PATCH 17/87] Validate account with reference voucher if against voucher mentioned --- .../doctype/journal_voucher/journal_voucher.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py index 4d00dfd472..c9ca0c2e37 100644 --- a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py +++ b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py @@ -42,7 +42,6 @@ class DocType(AccountsController): def on_submit(self): if self.doc.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']: self.check_credit_days() - self.check_account_against_entries() self.make_gl_entries() self.check_credit_limit() @@ -232,14 +231,20 @@ class DocType(AccountsController): for d in self.doclist.get({"parentfield": "entries"}): if d.against_invoice and webnotes.conn.get_value("Sales Invoice", d.against_invoice, "debit_to") != d.account: - webnotes.throw(_("Credited account (Customer) is not matching with Sales Invoice")) + webnotes.throw(_("Row #") + cstr(d.idx) + ": " + + _("Account is not matching with Debit To account of Sales Invoice")) if d.against_voucher and webnotes.conn.get_value("Purchase Invoice", - d.against_voucher, "credit_to") != d.account: - webnotes.throw(_("Debited account (Supplier) is not matching with Purchase Invoice")) + d.against_voucher, "credit_to") != d.account: + webnotes.throw(_("Row #") + cstr(d.idx) + ": " + + _("Account is not matching with Credit To account of Purchase Invoice")) def make_gl_entries(self, cancel=0, adv_adj=0): from erpnext.accounts.general_ledger import make_gl_entries + + if not cancel: + self.check_account_against_entries() + gl_map = [] for d in self.doclist.get({"parentfield": "entries"}): if d.debit or d.credit: From d3f04d754a8aa0e87d81bf721635bd79dc5d3242 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 31 Dec 2013 16:04:48 +0530 Subject: [PATCH 18/87] General ledger path fixed --- .../report/{accounts_payable => }/general_ledger/__init__.py | 0 .../{accounts_payable => }/general_ledger/general_ledger.js | 0 .../{accounts_payable => }/general_ledger/general_ledger.py | 0 .../{accounts_payable => }/general_ledger/general_ledger.txt | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename erpnext/accounts/report/{accounts_payable => }/general_ledger/__init__.py (100%) rename erpnext/accounts/report/{accounts_payable => }/general_ledger/general_ledger.js (100%) rename erpnext/accounts/report/{accounts_payable => }/general_ledger/general_ledger.py (100%) rename erpnext/accounts/report/{accounts_payable => }/general_ledger/general_ledger.txt (100%) diff --git a/erpnext/accounts/report/accounts_payable/general_ledger/__init__.py b/erpnext/accounts/report/general_ledger/__init__.py similarity index 100% rename from erpnext/accounts/report/accounts_payable/general_ledger/__init__.py rename to erpnext/accounts/report/general_ledger/__init__.py diff --git a/erpnext/accounts/report/accounts_payable/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js similarity index 100% rename from erpnext/accounts/report/accounts_payable/general_ledger/general_ledger.js rename to erpnext/accounts/report/general_ledger/general_ledger.js diff --git a/erpnext/accounts/report/accounts_payable/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py similarity index 100% rename from erpnext/accounts/report/accounts_payable/general_ledger/general_ledger.py rename to erpnext/accounts/report/general_ledger/general_ledger.py diff --git a/erpnext/accounts/report/accounts_payable/general_ledger/general_ledger.txt b/erpnext/accounts/report/general_ledger/general_ledger.txt similarity index 100% rename from erpnext/accounts/report/accounts_payable/general_ledger/general_ledger.txt rename to erpnext/accounts/report/general_ledger/general_ledger.txt From a2e0a9b05f4a4d8ef7dbe8f0c4b9e6d4c2f79a70 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 1 Jan 2014 10:45:42 +0530 Subject: [PATCH 19/87] Fliend rearrangemet in tables --- .../doctype/pos_setting/pos_setting.js | 2 +- .../sales_invoice_advance.txt | 41 ++-- .../sales_invoice_item/sales_invoice_item.txt | 130 +++++++----- .../sales_taxes_and_charges.txt | 63 +++--- erpnext/hr/doctype/employee/employee.js | 2 +- erpnext/public/js/queries.js | 2 +- erpnext/selling/doctype/lead/lead.js | 4 +- .../doctype/quotation_item/quotation_item.txt | 197 +++++++++-------- .../sales_order_item/sales_order_item.txt | 199 ++++++++++-------- .../selling/doctype/sales_team/sales_team.txt | 27 ++- .../authorization_rule/authorization_rule.js | 4 +- .../delivery_note_item/delivery_note_item.txt | 185 +++++++++------- .../doctype/packing_slip/packing_slip.js | 2 +- .../stock/doctype/stock_entry/stock_entry.js | 6 +- 14 files changed, 493 insertions(+), 371 deletions(-) diff --git a/erpnext/accounts/doctype/pos_setting/pos_setting.js b/erpnext/accounts/doctype/pos_setting/pos_setting.js index 8c5f254a52..a1ebb59602 100755 --- a/erpnext/accounts/doctype/pos_setting/pos_setting.js +++ b/erpnext/accounts/doctype/pos_setting/pos_setting.js @@ -74,5 +74,5 @@ cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) cur_frm.fields_dict.user.get_query = function(doc,cdt,cdn) { - return{ query:"core.doctype.profile.profile.profile_query"} + return{ query:"webnotes.core.doctype.profile.profile.profile_query"} } diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.txt b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.txt index ad1a9eb8fb..9ae37cfab3 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.txt +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-22 01:27:41", "docstatus": 0, - "modified": "2013-12-20 19:21:40", + "modified": "2013-12-31 18:29:19", "modified_by": "Administrator", "owner": "Administrator" }, @@ -15,7 +15,6 @@ { "doctype": "DocField", "name": "__common__", - "no_copy": 1, "parent": "Sales Invoice Advance", "parentfield": "fields", "parenttype": "DocType", @@ -31,6 +30,7 @@ "fieldtype": "Link", "in_list_view": 1, "label": "Journal Voucher", + "no_copy": 1, "oldfieldname": "journal_voucher", "oldfieldtype": "Link", "options": "Journal Voucher", @@ -38,26 +38,13 @@ "read_only": 1, "width": "250px" }, - { - "doctype": "DocField", - "fieldname": "jv_detail_no", - "fieldtype": "Data", - "hidden": 1, - "in_list_view": 0, - "label": "Journal Voucher Detail No", - "oldfieldname": "jv_detail_no", - "oldfieldtype": "Data", - "print_hide": 1, - "print_width": "120px", - "read_only": 1, - "width": "120px" - }, { "doctype": "DocField", "fieldname": "advance_amount", "fieldtype": "Currency", "in_list_view": 1, "label": "Advance amount", + "no_copy": 1, "oldfieldname": "advance_amount", "oldfieldtype": "Currency", "options": "Company:company:default_currency", @@ -71,22 +58,44 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Allocated amount", + "no_copy": 1, "oldfieldname": "allocated_amount", "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_width": "120px", "width": "120px" }, + { + "doctype": "DocField", + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "remarks", "fieldtype": "Small Text", "in_list_view": 1, "label": "Remarks", + "no_copy": 1, "oldfieldname": "remarks", "oldfieldtype": "Small Text", "print_width": "150px", "read_only": 1, "width": "150px" + }, + { + "doctype": "DocField", + "fieldname": "jv_detail_no", + "fieldtype": "Data", + "hidden": 1, + "in_list_view": 0, + "label": "Journal Voucher Detail No", + "no_copy": 1, + "oldfieldname": "jv_detail_no", + "oldfieldtype": "Data", + "print_hide": 1, + "print_width": "120px", + "read_only": 1, + "width": "120px" } ] \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.txt b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.txt index 339115d25e..4d7ae0ca82 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.txt +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-04 11:02:19", "docstatus": 0, - "modified": "2013-12-20 19:21:40", + "modified": "2013-12-31 18:27:41", "modified_by": "Administrator", "owner": "Administrator" }, @@ -49,16 +49,6 @@ "reqd": 0, "search_index": 1 }, - { - "doctype": "DocField", - "fieldname": "customer_item_code", - "fieldtype": "Data", - "hidden": 1, - "in_list_view": 0, - "label": "Customer's Item Code", - "print_hide": 1, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "item_name", @@ -73,6 +63,21 @@ "reqd": 1, "search_index": 0 }, + { + "doctype": "DocField", + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "customer_item_code", + "fieldtype": "Data", + "hidden": 1, + "in_list_view": 0, + "label": "Customer's Item Code", + "print_hide": 1, + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "description", @@ -104,15 +109,6 @@ "read_only": 0, "reqd": 0 }, - { - "doctype": "DocField", - "fieldname": "stock_uom", - "fieldtype": "Link", - "in_list_view": 0, - "label": "UOM", - "options": "UOM", - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "ref_rate", @@ -137,6 +133,37 @@ "print_hide": 1, "read_only": 0 }, + { + "doctype": "DocField", + "fieldname": "col_break2", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "stock_uom", + "fieldtype": "Link", + "in_list_view": 0, + "label": "UOM", + "options": "UOM", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "base_ref_rate", + "fieldtype": "Currency", + "in_list_view": 0, + "label": "Price List Rate (Company Currency)", + "oldfieldname": "base_ref_rate", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "section_break1", + "fieldtype": "Section Break" + }, { "doctype": "DocField", "fieldname": "export_rate", @@ -163,15 +190,8 @@ }, { "doctype": "DocField", - "fieldname": "base_ref_rate", - "fieldtype": "Currency", - "in_list_view": 0, - "label": "Price List Rate (Company Currency)", - "oldfieldname": "base_ref_rate", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "read_only": 1 + "fieldname": "col_break3", + "fieldtype": "Column Break" }, { "doctype": "DocField", @@ -237,6 +257,11 @@ "read_only": 0, "width": "120px" }, + { + "doctype": "DocField", + "fieldname": "col_break4", + "fieldtype": "Column Break" + }, { "default": ":Company", "doctype": "DocField", @@ -322,6 +347,22 @@ "print_hide": 1, "read_only": 0 }, + { + "doctype": "DocField", + "fieldname": "item_tax_rate", + "fieldtype": "Small Text", + "hidden": 1, + "label": "Item Tax Rate", + "oldfieldname": "item_tax_rate", + "oldfieldtype": "Small Text", + "print_hide": 1, + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "col_break5", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "actual_qty", @@ -334,13 +375,11 @@ }, { "doctype": "DocField", - "fieldname": "delivered_qty", - "fieldtype": "Float", - "label": "Delivered Qty", - "oldfieldname": "delivered_qty", - "oldfieldtype": "Currency", - "print_hide": 1, - "read_only": 1 + "fieldname": "time_log_batch", + "fieldtype": "Link", + "label": "Time Log Batch", + "options": "Time Log Batch", + "read_only": 0 }, { "doctype": "DocField", @@ -400,20 +439,11 @@ }, { "doctype": "DocField", - "fieldname": "time_log_batch", - "fieldtype": "Link", - "label": "Time Log Batch", - "options": "Time Log Batch", - "read_only": 0 - }, - { - "doctype": "DocField", - "fieldname": "item_tax_rate", - "fieldtype": "Small Text", - "hidden": 1, - "label": "Item Tax Rate", - "oldfieldname": "item_tax_rate", - "oldfieldtype": "Small Text", + "fieldname": "delivered_qty", + "fieldtype": "Float", + "label": "Delivered Qty", + "oldfieldname": "delivered_qty", + "oldfieldtype": "Currency", "print_hide": 1, "read_only": 1 }, diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt index ab4da2aa4f..49df5f7291 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-24 11:39:32", "docstatus": 0, - "modified": "2013-12-20 19:21:45", + "modified": "2013-12-31 17:51:47", "modified_by": "Administrator", "owner": "Administrator" }, @@ -46,6 +46,24 @@ "oldfieldname": "row_id", "oldfieldtype": "Data" }, + { + "doctype": "DocField", + "fieldname": "description", + "fieldtype": "Small Text", + "in_list_view": 1, + "label": "Description", + "oldfieldname": "description", + "oldfieldtype": "Small Text", + "print_width": "300px", + "reqd": 1, + "width": "300px" + }, + { + "doctype": "DocField", + "fieldname": "col_break_1", + "fieldtype": "Column Break", + "width": "50%" + }, { "doctype": "DocField", "fieldname": "account_head", @@ -69,36 +87,6 @@ "oldfieldtype": "Link", "options": "Cost Center" }, - { - "doctype": "DocField", - "fieldname": "description", - "fieldtype": "Small Text", - "in_list_view": 1, - "label": "Description", - "oldfieldname": "description", - "oldfieldtype": "Small Text", - "print_width": "300px", - "reqd": 1, - "width": "300px" - }, - { - "allow_on_submit": 0, - "description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount", - "doctype": "DocField", - "fieldname": "included_in_print_rate", - "fieldtype": "Check", - "label": "Is this Tax included in Basic Rate?", - "no_copy": 0, - "print_hide": 1, - "print_width": "150px", - "report_hide": 1, - "width": "150px" - }, - { - "doctype": "DocField", - "fieldname": "section_break_6", - "fieldtype": "Section Break" - }, { "doctype": "DocField", "fieldname": "rate", @@ -131,6 +119,19 @@ "options": "Company:company:default_currency", "read_only": 1 }, + { + "allow_on_submit": 0, + "description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount", + "doctype": "DocField", + "fieldname": "included_in_print_rate", + "fieldtype": "Check", + "label": "Is this Tax included in Basic Rate?", + "no_copy": 0, + "print_hide": 1, + "print_width": "150px", + "report_hide": 1, + "width": "150px" + }, { "doctype": "DocField", "fieldname": "item_wise_tax_detail", diff --git a/erpnext/hr/doctype/employee/employee.js b/erpnext/hr/doctype/employee/employee.js index 1df6175fae..23d50670fb 100644 --- a/erpnext/hr/doctype/employee/employee.js +++ b/erpnext/hr/doctype/employee/employee.js @@ -5,7 +5,7 @@ wn.provide("erpnext.hr"); erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({ setup: function() { this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) { - return { query:"core.doctype.profile.profile.profile_query"} } + return { query:"webnotes.core.doctype.profile.profile.profile_query"} } this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) { return{ query: "erpnext.controllers.queries.employee_query"} } }, diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js index 621e340ff7..dbaa27d2de 100644 --- a/erpnext/public/js/queries.js +++ b/erpnext/public/js/queries.js @@ -5,7 +5,7 @@ wn.provide("erpnext.queries"); $.extend(erpnext.queries, { profile: function() { - return { query: "core.doctype.profile.profile.profile_query" }; + return { query: "webnotes.core.doctype.profile.profile.profile_query" }; }, lead: function() { diff --git a/erpnext/selling/doctype/lead/lead.js b/erpnext/selling/doctype/lead/lead.js index 4ab1067089..41f679e34a 100644 --- a/erpnext/selling/doctype/lead/lead.js +++ b/erpnext/selling/doctype/lead/lead.js @@ -14,12 +14,12 @@ erpnext.LeadController = wn.ui.form.Controller.extend({ onload: function() { if(cur_frm.fields_dict.lead_owner.df.options.match(/^Profile/)) { cur_frm.fields_dict.lead_owner.get_query = function(doc,cdt,cdn) { - return { query:"core.doctype.profile.profile.profile_query" } } + return { query:"webnotes.core.doctype.profile.profile.profile_query" } } } if(cur_frm.fields_dict.contact_by.df.options.match(/^Profile/)) { cur_frm.fields_dict.contact_by.get_query = function(doc,cdt,cdn) { - return { query:"core.doctype.profile.profile.profile_query" } } + return { query:"webnotes.core.doctype.profile.profile.profile_query" } } } if(in_list(user_roles,'System Manager')) { diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.txt b/erpnext/selling/doctype/quotation_item/quotation_item.txt index e669937d09..531f005bd5 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.txt +++ b/erpnext/selling/doctype/quotation_item/quotation_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-07 11:42:57", "docstatus": 0, - "modified": "2013-12-20 19:23:41", + "modified": "2013-12-31 18:12:09", "modified_by": "Administrator", "owner": "Administrator" }, @@ -69,6 +69,11 @@ "search_index": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "description", @@ -106,21 +111,6 @@ "search_index": 0, "width": "100px" }, - { - "doctype": "DocField", - "fieldname": "stock_uom", - "fieldtype": "Link", - "in_list_view": 0, - "label": "UOM", - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "options": "UOM", - "print_hide": 0, - "print_width": "100px", - "read_only": 1, - "reqd": 0, - "width": "100px" - }, { "doctype": "DocField", "fieldname": "ref_rate", @@ -149,6 +139,45 @@ "read_only": 0, "width": "100px" }, + { + "doctype": "DocField", + "fieldname": "col_break2", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "stock_uom", + "fieldtype": "Link", + "in_list_view": 0, + "label": "UOM", + "oldfieldname": "stock_uom", + "oldfieldtype": "Data", + "options": "UOM", + "print_hide": 0, + "print_width": "100px", + "read_only": 1, + "reqd": 0, + "width": "100px" + }, + { + "doctype": "DocField", + "fieldname": "base_ref_rate", + "fieldtype": "Currency", + "in_list_view": 0, + "label": "Price List Rate (Company Currency)", + "oldfieldname": "base_ref_rate", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "print_width": "100px", + "read_only": 1, + "width": "100px" + }, + { + "doctype": "DocField", + "fieldname": "Section_break1", + "fieldtype": "Section Break" + }, { "doctype": "DocField", "fieldname": "export_rate", @@ -185,17 +214,8 @@ }, { "doctype": "DocField", - "fieldname": "base_ref_rate", - "fieldtype": "Currency", - "in_list_view": 0, - "label": "Price List Rate (Company Currency)", - "oldfieldname": "base_ref_rate", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "print_width": "100px", - "read_only": 1, - "width": "100px" + "fieldname": "col_break3", + "fieldtype": "Column Break" }, { "doctype": "DocField", @@ -238,6 +258,70 @@ "in_list_view": 0, "label": "Reference" }, + { + "doctype": "DocField", + "fieldname": "prevdoc_doctype", + "fieldtype": "Data", + "hidden": 1, + "in_list_view": 0, + "label": "Against Doctype", + "no_copy": 1, + "oldfieldname": "prevdoc_doctype", + "oldfieldtype": "Data", + "print_hide": 1, + "print_width": "150px", + "read_only": 1, + "report_hide": 0, + "width": "150px" + }, + { + "doctype": "DocField", + "fieldname": "prevdoc_docname", + "fieldtype": "Data", + "in_list_view": 0, + "label": "Against Docname", + "no_copy": 1, + "oldfieldname": "prevdoc_docname", + "oldfieldtype": "Data", + "print_hide": 1, + "print_width": "150px", + "read_only": 1, + "report_hide": 0, + "width": "150px" + }, + { + "doctype": "DocField", + "fieldname": "item_tax_rate", + "fieldtype": "Small Text", + "hidden": 1, + "in_list_view": 0, + "label": "Item Tax Rate", + "oldfieldname": "item_tax_rate", + "oldfieldtype": "Small Text", + "print_hide": 1, + "read_only": 1, + "report_hide": 1 + }, + { + "doctype": "DocField", + "fieldname": "col_break4", + "fieldtype": "Column Break" + }, + { + "allow_on_submit": 1, + "doctype": "DocField", + "fieldname": "page_break", + "fieldtype": "Check", + "hidden": 0, + "in_list_view": 0, + "label": "Page Break", + "no_copy": 1, + "oldfieldname": "page_break", + "oldfieldtype": "Check", + "print_hide": 1, + "read_only": 0, + "report_hide": 1 + }, { "description": "Add / Edit", "doctype": "DocField", @@ -270,64 +354,5 @@ "read_only": 1, "search_index": 1, "width": "150px" - }, - { - "doctype": "DocField", - "fieldname": "item_tax_rate", - "fieldtype": "Small Text", - "hidden": 1, - "in_list_view": 0, - "label": "Item Tax Rate", - "oldfieldname": "item_tax_rate", - "oldfieldtype": "Small Text", - "print_hide": 1, - "read_only": 1, - "report_hide": 1 - }, - { - "doctype": "DocField", - "fieldname": "prevdoc_docname", - "fieldtype": "Data", - "in_list_view": 0, - "label": "Against Docname", - "no_copy": 1, - "oldfieldname": "prevdoc_docname", - "oldfieldtype": "Data", - "print_hide": 1, - "print_width": "150px", - "read_only": 1, - "report_hide": 0, - "width": "150px" - }, - { - "doctype": "DocField", - "fieldname": "prevdoc_doctype", - "fieldtype": "Data", - "hidden": 1, - "in_list_view": 0, - "label": "Against Doctype", - "no_copy": 1, - "oldfieldname": "prevdoc_doctype", - "oldfieldtype": "Data", - "print_hide": 1, - "print_width": "150px", - "read_only": 1, - "report_hide": 0, - "width": "150px" - }, - { - "allow_on_submit": 1, - "doctype": "DocField", - "fieldname": "page_break", - "fieldtype": "Check", - "hidden": 0, - "in_list_view": 0, - "label": "Page Break", - "no_copy": 1, - "oldfieldname": "page_break", - "oldfieldtype": "Check", - "print_hide": 1, - "read_only": 0, - "report_hide": 1 } ] \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.txt b/erpnext/selling/doctype/sales_order_item/sales_order_item.txt index eb656a600a..38fb01cc27 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.txt +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-07 11:42:58", "docstatus": 0, - "modified": "2013-12-20 19:21:43", + "modified": "2013-12-31 18:07:50", "modified_by": "Administrator", "owner": "Administrator" }, @@ -65,6 +65,11 @@ "reqd": 1, "width": "150" }, + { + "doctype": "DocField", + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "description", @@ -100,21 +105,6 @@ "reqd": 1, "width": "100px" }, - { - "doctype": "DocField", - "fieldname": "stock_uom", - "fieldtype": "Link", - "hidden": 0, - "in_list_view": 0, - "label": "UOM", - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "options": "UOM", - "print_width": "70px", - "read_only": 1, - "reqd": 0, - "width": "70px" - }, { "doctype": "DocField", "fieldname": "ref_rate", @@ -143,6 +133,45 @@ "read_only": 0, "width": "70px" }, + { + "doctype": "DocField", + "fieldname": "col_break2", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "stock_uom", + "fieldtype": "Link", + "hidden": 0, + "in_list_view": 0, + "label": "UOM", + "oldfieldname": "stock_uom", + "oldfieldtype": "Data", + "options": "UOM", + "print_width": "70px", + "read_only": 1, + "reqd": 0, + "width": "70px" + }, + { + "doctype": "DocField", + "fieldname": "base_ref_rate", + "fieldtype": "Currency", + "in_list_view": 0, + "label": "Price List Rate (Company Currency)", + "oldfieldname": "base_ref_rate", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "print_width": "100px", + "read_only": 1, + "width": "100px" + }, + { + "doctype": "DocField", + "fieldname": "section_break_simple1", + "fieldtype": "Section Break" + }, { "doctype": "DocField", "fieldname": "export_rate", @@ -174,17 +203,8 @@ }, { "doctype": "DocField", - "fieldname": "base_ref_rate", - "fieldtype": "Currency", - "in_list_view": 0, - "label": "Price List Rate (Company Currency)", - "oldfieldname": "base_ref_rate", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "print_width": "100px", - "read_only": 1, - "width": "100px" + "fieldname": "col_break3", + "fieldtype": "Column Break" }, { "doctype": "DocField", @@ -240,6 +260,71 @@ "reqd": 0, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "prevdoc_docname", + "fieldtype": "Link", + "hidden": 0, + "in_filter": 1, + "in_list_view": 0, + "label": "Quotation", + "no_copy": 1, + "oldfieldname": "prevdoc_docname", + "oldfieldtype": "Link", + "options": "Quotation", + "print_hide": 1, + "read_only": 1, + "search_index": 1 + }, + { + "doctype": "DocField", + "fieldname": "brand", + "fieldtype": "Link", + "hidden": 1, + "in_filter": 1, + "in_list_view": 0, + "label": "Brand Name", + "oldfieldname": "brand", + "oldfieldtype": "Link", + "options": "Brand", + "print_hide": 1, + "read_only": 1, + "search_index": 1 + }, + { + "description": "Add / Edit", + "doctype": "DocField", + "fieldname": "item_group", + "fieldtype": "Link", + "hidden": 1, + "in_filter": 1, + "in_list_view": 0, + "label": "Item Group", + "oldfieldname": "item_group", + "oldfieldtype": "Link", + "options": "Item Group", + "print_hide": 1, + "read_only": 1, + "search_index": 1 + }, + { + "allow_on_submit": 1, + "doctype": "DocField", + "fieldname": "page_break", + "fieldtype": "Check", + "in_list_view": 0, + "label": "Page Break", + "oldfieldname": "page_break", + "oldfieldtype": "Check", + "print_hide": 1, + "read_only": 0, + "report_hide": 1 + }, + { + "doctype": "DocField", + "fieldname": "col_break4", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "projected_qty", @@ -328,66 +413,6 @@ "report_hide": 1, "width": "50px" }, - { - "doctype": "DocField", - "fieldname": "brand", - "fieldtype": "Link", - "hidden": 1, - "in_filter": 1, - "in_list_view": 0, - "label": "Brand Name", - "oldfieldname": "brand", - "oldfieldtype": "Link", - "options": "Brand", - "print_hide": 1, - "read_only": 1, - "search_index": 1 - }, - { - "description": "Add / Edit", - "doctype": "DocField", - "fieldname": "item_group", - "fieldtype": "Link", - "hidden": 1, - "in_filter": 1, - "in_list_view": 0, - "label": "Item Group", - "oldfieldname": "item_group", - "oldfieldtype": "Link", - "options": "Item Group", - "print_hide": 1, - "read_only": 1, - "search_index": 1 - }, - { - "doctype": "DocField", - "fieldname": "prevdoc_docname", - "fieldtype": "Link", - "hidden": 0, - "in_filter": 1, - "in_list_view": 0, - "label": "Quotation", - "no_copy": 1, - "oldfieldname": "prevdoc_docname", - "oldfieldtype": "Link", - "options": "Quotation", - "print_hide": 1, - "read_only": 1, - "search_index": 1 - }, - { - "allow_on_submit": 1, - "doctype": "DocField", - "fieldname": "page_break", - "fieldtype": "Check", - "in_list_view": 0, - "label": "Page Break", - "oldfieldname": "page_break", - "oldfieldtype": "Check", - "print_hide": 1, - "read_only": 0, - "report_hide": 1 - }, { "doctype": "DocField", "fieldname": "item_tax_rate", diff --git a/erpnext/selling/doctype/sales_team/sales_team.txt b/erpnext/selling/doctype/sales_team/sales_team.txt index 9b584296e8..d012cb41c1 100644 --- a/erpnext/selling/doctype/sales_team/sales_team.txt +++ b/erpnext/selling/doctype/sales_team/sales_team.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-19 13:30:51", "docstatus": 0, - "modified": "2013-12-20 19:21:46", + "modified": "2013-12-31 19:00:14", "modified_by": "Administrator", "owner": "Administrator" }, @@ -63,6 +63,11 @@ "print_width": "100px", "width": "100px" }, + { + "doctype": "DocField", + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "allocated_percentage", @@ -89,6 +94,16 @@ "reqd": 0, "width": "120px" }, + { + "doctype": "DocField", + "fieldname": "incentives", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Incentives", + "oldfieldname": "incentives", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency" + }, { "doctype": "DocField", "fieldname": "parenttype", @@ -101,15 +116,5 @@ "oldfieldtype": "Data", "print_hide": 1, "search_index": 1 - }, - { - "doctype": "DocField", - "fieldname": "incentives", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Incentives", - "oldfieldname": "incentives", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency" } ] \ No newline at end of file diff --git a/erpnext/setup/doctype/authorization_rule/authorization_rule.js b/erpnext/setup/doctype/authorization_rule/authorization_rule.js index bd42618c53..66b14a85ba 100644 --- a/erpnext/setup/doctype/authorization_rule/authorization_rule.js +++ b/erpnext/setup/doctype/authorization_rule/authorization_rule.js @@ -69,10 +69,10 @@ cur_frm.cscript.transaction = function(doc,cdt,cdn){ cur_frm.fields_dict.system_user.get_query = function(doc,cdt,cdn) { - return{ query:"core.doctype.profile.profile.profile_query" } } + return{ query:"webnotes.core.doctype.profile.profile.profile_query" } } cur_frm.fields_dict.approving_user.get_query = function(doc,cdt,cdn) { - return{ query:"core.doctype.profile.profile.profile_query" } } + return{ query:"webnotes.core.doctype.profile.profile.profile_query" } } cur_frm.fields_dict['approving_role'].get_query = cur_frm.fields_dict['system_role'].get_query; diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.txt b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.txt index 96c01f6001..7caa89d1af 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.txt +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-22 13:15:44", "docstatus": 0, - "modified": "2013-12-20 19:23:08", + "modified": "2013-12-31 18:23:03", "modified_by": "Administrator", "owner": "Administrator" }, @@ -50,16 +50,6 @@ "search_index": 1, "width": "150px" }, - { - "doctype": "DocField", - "fieldname": "customer_item_code", - "fieldtype": "Data", - "hidden": 1, - "in_list_view": 0, - "label": "Customer's Item Code", - "print_hide": 1, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "item_name", @@ -74,6 +64,21 @@ "reqd": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "col_break1", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "customer_item_code", + "fieldtype": "Data", + "hidden": 1, + "in_list_view": 0, + "label": "Customer's Item Code", + "print_hide": 1, + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "description", @@ -107,21 +112,6 @@ "reqd": 1, "width": "100px" }, - { - "doctype": "DocField", - "fieldname": "stock_uom", - "fieldtype": "Link", - "in_list_view": 0, - "label": "UOM", - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "options": "UOM", - "print_hide": 0, - "print_width": "50px", - "read_only": 1, - "reqd": 1, - "width": "50px" - }, { "doctype": "DocField", "fieldname": "ref_rate", @@ -151,6 +141,45 @@ "read_only": 0, "width": "100px" }, + { + "doctype": "DocField", + "fieldname": "col_break2", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "stock_uom", + "fieldtype": "Link", + "in_list_view": 0, + "label": "UOM", + "oldfieldname": "stock_uom", + "oldfieldtype": "Data", + "options": "UOM", + "print_hide": 0, + "print_width": "50px", + "read_only": 1, + "reqd": 1, + "width": "50px" + }, + { + "doctype": "DocField", + "fieldname": "base_ref_rate", + "fieldtype": "Currency", + "in_list_view": 0, + "label": "Price List Rate (Company Currency)", + "oldfieldname": "base_ref_rate", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "print_width": "100px", + "read_only": 1, + "width": "100px" + }, + { + "doctype": "DocField", + "fieldname": "section_break_1", + "fieldtype": "Section Break" + }, { "doctype": "DocField", "fieldname": "export_rate", @@ -183,17 +212,8 @@ }, { "doctype": "DocField", - "fieldname": "base_ref_rate", - "fieldtype": "Currency", - "in_list_view": 0, - "label": "Price List Rate (Company Currency)", - "oldfieldname": "base_ref_rate", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "print_width": "100px", - "read_only": 1, - "width": "100px" + "fieldname": "col_break3", + "fieldtype": "Column Break" }, { "doctype": "DocField", @@ -271,31 +291,6 @@ "print_hide": 1, "read_only": 0 }, - { - "doctype": "DocField", - "fieldname": "expense_account", - "fieldtype": "Link", - "hidden": 0, - "label": "Expense Account", - "no_copy": 1, - "options": "Account", - "print_hide": 1, - "read_only": 0, - "width": "120px" - }, - { - "default": ":Company", - "doctype": "DocField", - "fieldname": "cost_center", - "fieldtype": "Link", - "hidden": 0, - "label": "Cost Center", - "no_copy": 1, - "options": "Cost Center", - "print_hide": 1, - "read_only": 0, - "width": "120px" - }, { "description": "Add / Edit", "doctype": "DocField", @@ -323,6 +318,22 @@ "read_only": 1, "width": "150px" }, + { + "doctype": "DocField", + "fieldname": "item_tax_rate", + "fieldtype": "Small Text", + "hidden": 1, + "label": "Item Tax Rate", + "oldfieldname": "item_tax_rate", + "oldfieldtype": "Small Text", + "print_hide": 1, + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "col_break4", + "fieldtype": "Column Break" + }, { "doctype": "DocField", "fieldname": "actual_qty", @@ -338,30 +349,44 @@ }, { "doctype": "DocField", - "fieldname": "installed_qty", - "fieldtype": "Float", - "label": "Installed Qty", + "fieldname": "expense_account", + "fieldtype": "Link", + "hidden": 0, + "label": "Expense Account", "no_copy": 1, - "oldfieldname": "installed_qty", - "oldfieldtype": "Currency", + "options": "Account", "print_hide": 1, - "print_width": "150px", - "read_only": 1, - "width": "150px" + "read_only": 0, + "width": "120px" + }, + { + "default": ":Company", + "doctype": "DocField", + "fieldname": "cost_center", + "fieldtype": "Link", + "hidden": 0, + "label": "Cost Center", + "no_copy": 1, + "options": "Cost Center", + "print_hide": 1, + "read_only": 0, + "width": "120px" }, { "doctype": "DocField", "fieldname": "against_sales_order", "fieldtype": "Link", "label": "Against Sales Order", - "options": "Sales Order" + "options": "Sales Order", + "read_only": 1 }, { "doctype": "DocField", "fieldname": "against_sales_invoice", "fieldtype": "Link", "label": "Against Sales Invoice", - "options": "Sales Invoice" + "options": "Sales Invoice", + "read_only": 1 }, { "doctype": "DocField", @@ -381,14 +406,16 @@ }, { "doctype": "DocField", - "fieldname": "item_tax_rate", - "fieldtype": "Small Text", - "hidden": 1, - "label": "Item Tax Rate", - "oldfieldname": "item_tax_rate", - "oldfieldtype": "Small Text", + "fieldname": "installed_qty", + "fieldtype": "Float", + "label": "Installed Qty", + "no_copy": 1, + "oldfieldname": "installed_qty", + "oldfieldtype": "Currency", "print_hide": 1, - "read_only": 1 + "print_width": "150px", + "read_only": 1, + "width": "150px" }, { "doctype": "DocField", diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.js b/erpnext/stock/doctype/packing_slip/packing_slip.js index a0e82e7399..992b00de87 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.js +++ b/erpnext/stock/doctype/packing_slip/packing_slip.js @@ -11,7 +11,7 @@ cur_frm.fields_dict['delivery_note'].get_query = function(doc, cdt, cdn) { cur_frm.fields_dict['item_details'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) { return { - query: "stock.doctype.packing_slip.packing_slip.item_details", + query: "erpnext.stock.doctype.packing_slip.packing_slip.item_details", filters:{ 'delivery_note': doc.delivery_note} } } diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index ec46685059..6bd9564845 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -12,7 +12,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ var me = this; this.frm.fields_dict.delivery_note_no.get_query = function() { - return { query: "stock.doctype.stock_entry.stock_entry.query_sales_return_doc" }; + return { query: "erpnext.stock.doctype.stock_entry.stock_entry.query_sales_return_doc" }; }; this.frm.fields_dict.sales_invoice_no.get_query = @@ -28,7 +28,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ if(in_list(["Sales Return", "Purchase Return"], me.frm.doc.purpose) && me.get_doctype_docname()) { return { - query: "stock.doctype.stock_entry.stock_entry.query_return_item", + query: "erpnext.stock.doctype.stock_entry.stock_entry.query_return_item", filters: { purpose: me.frm.doc.purpose, delivery_note_no: me.frm.doc.delivery_note_no, @@ -309,7 +309,7 @@ cur_frm.fields_dict['mtn_details'].grid.get_field('batch_no').get_query = functi var d = locals[cdt][cdn]; if(d.item_code) { return{ - query: "stock.doctype.stock_entry.stock_entry.get_batch_no", + query: "erpnext.stock.doctype.stock_entry.stock_entry.get_batch_no", filters:{ 'item_code': d.item_code, 's_warehouse': d.s_warehouse, From a1ffacaf0bb3e9b76f22e96708d69f9c14ea6c42 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 2 Jan 2014 16:30:16 +0530 Subject: [PATCH 20/87] Valuation related charges should only go to stock items --- controllers/accounts_controller.py | 3 --- controllers/buying_controller.py | 38 +++++++++++++++++------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 5388ee120a..11480c9ebe 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -231,9 +231,6 @@ class AccountsController(TransactionBase): # tax_amount represents the amount of tax for the current step current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map) - if hasattr(self, "set_item_tax_amount"): - self.set_item_tax_amount(item, tax, current_tax_amount) - # case when net total is 0 but there is an actual type charge # in this case add the actual amount to tax.tax_amount # and tax.grand_total_for_current_item for the first such iteration diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 35b9d25279..4aa08d6c55 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -163,30 +163,36 @@ class BuyingController(StockController): if not self.meta.get_field("item_tax_amount", parentfield=self.fname): for item in self.item_doclist: del item.fields["item_tax_amount"] - - def set_item_tax_amount(self, item, tax, current_tax_amount): + + # update valuation rate + def update_valuation_rate(self, parentfield): """ item_tax_amount is the total tax amount applied on that item stored for valuation TODO: rename item_tax_amount to valuation_tax_amount """ - if tax.category in ["Valuation", "Valuation and Total"] and \ - self.meta.get_field("item_tax_amount", parentfield=self.fname): - item.item_tax_amount += flt(current_tax_amount, self.precision("item_tax_amount", item)) - - # update valuation rate - def update_valuation_rate(self, parentfield): - for item in self.doclist.get({"parentfield": parentfield}): - item.conversion_factor = item.conversion_factor or flt(webnotes.conn.get_value( - "UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom}, - "conversion_factor")) or 1 + stock_items = self.get_stock_items() + + stock_items_amount = sum([flt(d.amount) for d in + self.doclist.get({"parentfield": parentfield}) + if d.item_code and d.item_code in stock_items]) - if item.item_code and item.qty: + total_valuation_amount = sum([flt(d.tax_amount) for d in + self.doclist.get({"parentfield": "purchase_tax_details"}) + if d.category in ["Valuation", "Valuation and Total"]]) + + + for item in self.doclist.get({"parentfield": parentfield}): + if item.item_code and item.qty and item.item_code in stock_items: + item.item_tax_amount = flt(flt(item.amount) * total_valuation_amount \ + / stock_items_amount, self.precision("item_tax_amount", item)) + self.round_floats_in(item) - - # if no item code, which is sometimes the case in purchase invoice, - # then it is not possible to track valuation against it + + item.conversion_factor = item.conversion_factor or flt(webnotes.conn.get_value( + "UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom}, + "conversion_factor")) or 1 qty_in_stock_uom = flt(item.qty * item.conversion_factor) item.valuation_rate = ((item.amount + item.item_tax_amount + item.rm_supp_cost) / qty_in_stock_uom) From df07c964f74e5527d2ab1a0aaffb2cdd96807619 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 2 Jan 2014 17:42:01 +0600 Subject: [PATCH 21/87] bumped to version 3.4.4 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index c09c2afac9..e8955b178c 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.3", + "app_version": "3.4.4", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.4.2" + "requires_framework_version": "==3.4.3" } \ No newline at end of file From 28acaeb3456e31351e3dd32c0ba6d886c70a7442 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 11:16:16 +0530 Subject: [PATCH 22/87] Fixes in valuation rate calculation in purchase receipt --- controllers/buying_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 4aa08d6c55..f014f72ee5 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -184,7 +184,7 @@ class BuyingController(StockController): for item in self.doclist.get({"parentfield": parentfield}): - if item.item_code and item.qty and item.item_code in stock_items: + if item.item_code and item.qty and stock_items_amount and item.item_code in stock_items: item.item_tax_amount = flt(flt(item.amount) * total_valuation_amount \ / stock_items_amount, self.precision("item_tax_amount", item)) From a4db83a934eb4fefd356ae6f55d88f97e3d45af9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 12:13:18 +0530 Subject: [PATCH 23/87] Fixes in valuation rate calculation in purchase receipt --- .../purchase_invoice/purchase_invoice.py | 12 ------------ accounts/utils.py | 2 ++ controllers/buying_controller.py | 17 +++++++++++------ 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 404627af25..0b8ad46dd0 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -350,7 +350,6 @@ class DocType(BuyingController): # item gl entries stock_item_and_auto_accounting_for_stock = False stock_items = self.get_stock_items() - # rounding_diff = 0.0 for item in self.doclist.get({"parentfield": "entries"}): if auto_accounting_for_stock and item.item_code in stock_items: if flt(item.valuation_rate): @@ -361,11 +360,6 @@ class DocType(BuyingController): valuation_amt = item.amount + item.item_tax_amount + item.rm_supp_cost - # rounding_diff += (flt(item.amount, self.precision("amount", item)) + - # flt(item.item_tax_amount, self.precision("item_tax_amount", item)) + - # flt(item.rm_supp_cost, self.precision("rm_supp_cost", item)) - - # valuation_amt) - gl_entries.append( self.get_gl_dict({ "account": item.expense_head, @@ -392,12 +386,6 @@ class DocType(BuyingController): # this will balance out valuation amount included in cost of goods sold expenses_included_in_valuation = \ self.get_company_default("expenses_included_in_valuation") - - # if rounding_diff: - # import operator - # cost_center_with_max_value = max(valuation_tax.iteritems(), - # key=operator.itemgetter(1))[0] - # valuation_tax[cost_center_with_max_value] -= flt(rounding_diff) for cost_center, amount in valuation_tax.items(): gl_entries.append( diff --git a/accounts/utils.py b/accounts/utils.py index 8971c80f99..a5fb390e9f 100644 --- a/accounts/utils.py +++ b/accounts/utils.py @@ -31,6 +31,8 @@ def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1): if not fy: error_msg = """%s %s not in any Fiscal Year""" % (label, formatdate(date)) + error_msg = """{msg}: {date}""".format(msg=_("Fiscal Year does not exist for date"), + date=formatdate(date)) if verbose: webnotes.msgprint(error_msg) raise FiscalYearError, error_msg diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index f014f72ee5..3c6981d6cb 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -174,9 +174,11 @@ class BuyingController(StockController): """ stock_items = self.get_stock_items() - stock_items_amount = sum([flt(d.amount) for d in - self.doclist.get({"parentfield": parentfield}) - if d.item_code and d.item_code in stock_items]) + stock_items_qty, stock_items_amount = 0, 0 + for d in self.doclist.get({"parentfield": parentfield}): + if d.item_code and d.item_code in stock_items: + stock_items_qty += flt(d.qty) + stock_items_amount += flt(d.amount) total_valuation_amount = sum([flt(d.tax_amount) for d in self.doclist.get({"parentfield": "purchase_tax_details"}) @@ -184,9 +186,12 @@ class BuyingController(StockController): for item in self.doclist.get({"parentfield": parentfield}): - if item.item_code and item.qty and stock_items_amount and item.item_code in stock_items: - item.item_tax_amount = flt(flt(item.amount) * total_valuation_amount \ - / stock_items_amount, self.precision("item_tax_amount", item)) + if item.item_code and item.qty and item.item_code in stock_items: + item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \ + else flt(item.qty) / stock_items_qty + + item.item_tax_amount = flt(item_proportion * total_valuation_amount, + self.precision("item_tax_amount", item)) self.round_floats_in(item) From 6472bdace2b67e023563c2ca00b41cdfb2c9683e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 12:30:24 +0530 Subject: [PATCH 24/87] Fixes in general ledger report --- accounts/doctype/journal_voucher/journal_voucher.js | 3 ++- accounts/doctype/purchase_invoice/purchase_invoice.js | 3 ++- accounts/doctype/sales_invoice/sales_invoice.js | 3 ++- accounts/report/general_ledger/general_ledger.py | 2 +- public/js/controllers/stock_controller.js | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js index 6b94ba170a..e5cea8cc79 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.js +++ b/accounts/doctype/journal_voucher/journal_voucher.js @@ -120,7 +120,8 @@ cur_frm.cscript.refresh = function(doc) { "voucher_no": doc.name, "from_date": doc.posting_date, "to_date": doc.posting_date, - "company": doc.company + "company": doc.company, + group_by_voucher: 0 }; wn.set_route("query-report", "General Ledger"); }, "icon-table"); diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.js b/accounts/doctype/purchase_invoice/purchase_invoice.js index 0bdc70e13d..1055bdd25d 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -35,7 +35,8 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ "voucher_no": doc.name, "from_date": doc.posting_date, "to_date": doc.posting_date, - "company": doc.company + "company": doc.company, + group_by_voucher: 0 }; wn.set_route("query-report", "General Ledger"); }, "icon-table"); diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index a390fb4ed7..3bdef5bb56 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -54,7 +54,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte "voucher_no": doc.name, "from_date": doc.posting_date, "to_date": doc.posting_date, - "company": doc.company + "company": doc.company, + group_by_voucher: 0 }; wn.set_route("query-report", "General Ledger"); }, "icon-table"); diff --git a/accounts/report/general_ledger/general_ledger.py b/accounts/report/general_ledger/general_ledger.py index 2efc8241c0..855b7d1c7a 100644 --- a/accounts/report/general_ledger/general_ledger.py +++ b/accounts/report/general_ledger/general_ledger.py @@ -136,7 +136,7 @@ def get_accountwise_gle(filters, gl_entries, gle_map): or cstr(gle.is_advance) == "Yes"): gle_map[gle.account].opening += amount opening += amount - elif gle.posting_date < filters.to_date: + elif gle.posting_date <= filters.to_date: gle_map[gle.account].entries.append(gle) gle_map[gle.account].total_debit += flt(gle.debit) gle_map[gle.account].total_credit += flt(gle.credit) diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js index d2fb904419..6a4261c22a 100644 --- a/public/js/controllers/stock_controller.js +++ b/public/js/controllers/stock_controller.js @@ -28,7 +28,8 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({ voucher_no: me.frm.doc.name, from_date: me.frm.doc.posting_date, to_date: me.frm.doc.posting_date, - company: me.frm.doc.company + company: me.frm.doc.company, + group_by_voucher: false }; wn.set_route("query-report", "General Ledger"); }, "icon-table"); From b0a9581e59c6d7c8c1148afefb26c528bd464c2d Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 3 Jan 2014 12:44:00 +0530 Subject: [PATCH 25/87] fixed accounts receivable for customer name --- .../accounts_receivable.py | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 945bae434a..1c76f9baf1 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -18,16 +18,23 @@ class AccountsReceivableReport(object): return self.get_columns(), self.get_data() def get_columns(self): - return [ + columns = [ "Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110", "Voucher No::120", "::30", "Due Date:Date:80", "Invoiced Amount:Currency:100", "Payment Received:Currency:100", "Outstanding Amount:Currency:100", "Age:Int:50", "0-30:Currency:100", - "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100", - "Customer:Link/Customer:200", "Territory:Link/Territory:80", "Remarks::200" + "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100" ] + naming_by = self.get_selling_settings() + if naming_by[0].value == "Naming Series": + columns += ["Customer:Link/Customer:200"] + + columns += ["Customer Name::110", "Territory:Link/Territory:80", "Remarks::200"] + + return columns + def get_data(self): data = [] future_vouchers = self.get_entries_after(self.filters.report_date) @@ -42,10 +49,15 @@ class AccountsReceivableReport(object): gle.voucher_type, gle.voucher_no, due_date, invoiced_amount, payment_received, outstanding_amount] - entry_date = due_date if self.filters.ageing_based_on=="Due Date" \ + entry_date = due_date if self.filters.ageing_based_on == "Due Date" \ else gle.posting_date row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) - row += [self.get_customer(gle.account), self.get_territory(gle.account), gle.remarks] + + naming_by = self.get_selling_settings() + if naming_by[0].value == "Naming Series": + row += [self.get_customer(gle.account)] + + row += [self.get_customer_name(gle.account), self.get_territory(gle.account), gle.remarks] data.append(row) for i in range(0,len(data)): @@ -53,7 +65,11 @@ class AccountsReceivableReport(object): % ("/".join(["#Form", data[i][2], data[i][3]]),)) return data - + + def get_selling_settings(self): + return webnotes.conn.sql("""select value from `tabSingles` where + doctype='Selling Settings' and field='cust_master_name'""", as_dict=1) + def get_entries_after(self, report_date): # returns a distinct list return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries() @@ -77,18 +93,21 @@ class AccountsReceivableReport(object): return flt(gle.debit) - flt(gle.credit) - payment_received def get_customer(self, account): + return self.get_account_map().get(account).get("customer") or "" + + def get_customer_name(self, account): return self.get_account_map().get(account).get("customer_name") or "" - + def get_territory(self, account): return self.get_account_map().get(account).get("territory") or "" def get_account_map(self): if not hasattr(self, "account_map"): self.account_map = dict(((r.name, r) for r in webnotes.conn.sql("""select - account.name, customer.name as customer_name, customer.territory - from `tabAccount` account, `tabCustomer` customer - where account.master_type="Customer" - and customer.name=account.master_name""", as_dict=True))) + acc.name, cust.name as customer, cust.customer_name, cust.territory + from `tabAccount` acc, `tabCustomer` cust + where acc.master_type="Customer" + and cust.name=acc.master_name""", as_dict=True))) return self.account_map @@ -164,4 +183,4 @@ def get_ageing_data(age_as_on, entry_date, outstanding_amount): if index is None: index = 3 outstanding_range[index] = outstanding_amount - return [age] + outstanding_range + return [age] + outstanding_range \ No newline at end of file From b4eba77f7b00d92a25335d6cfc2adf454763601d Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 3 Jan 2014 12:58:04 +0530 Subject: [PATCH 26/87] fixed accounts receivable --- .../accounts_receivable/accounts_receivable.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 1c76f9baf1..0407039e41 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -26,9 +26,8 @@ class AccountsReceivableReport(object): "Outstanding Amount:Currency:100", "Age:Int:50", "0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100" ] - - naming_by = self.get_selling_settings() - if naming_by[0].value == "Naming Series": + + if self.get_customer_naming() == "Naming Series": columns += ["Customer:Link/Customer:200"] columns += ["Customer Name::110", "Territory:Link/Territory:80", "Remarks::200"] @@ -53,8 +52,7 @@ class AccountsReceivableReport(object): else gle.posting_date row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) - naming_by = self.get_selling_settings() - if naming_by[0].value == "Naming Series": + if self.get_customer_naming() == "Naming Series": row += [self.get_customer(gle.account)] row += [self.get_customer_name(gle.account), self.get_territory(gle.account), gle.remarks] @@ -66,9 +64,8 @@ class AccountsReceivableReport(object): return data - def get_selling_settings(self): - return webnotes.conn.sql("""select value from `tabSingles` where - doctype='Selling Settings' and field='cust_master_name'""", as_dict=1) + def get_customer_naming(self): + return webnotes.conn.get_value("Selling Settings", None, "cust_master_name") def get_entries_after(self, report_date): # returns a distinct list From 8a0b7cece13a46b1f62f1dc7a70002f24a3f6731 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 3 Jan 2014 13:21:38 +0530 Subject: [PATCH 27/87] accounts receivable fixed --- .../accounts_receivable.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 0407039e41..781db2aaf3 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -15,26 +15,28 @@ class AccountsReceivableReport(object): else self.filters.report_date def run(self): - return self.get_columns(), self.get_data() + customer_naming_by = webnotes.conn.get_value("Selling Settings", None, "cust_master_name") + return self.get_columns(customer_naming_by), self.get_data(customer_naming_by) - def get_columns(self): + def get_columns(self, customer_naming_by): columns = [ "Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110", "Voucher No::120", "::30", "Due Date:Date:80", "Invoiced Amount:Currency:100", "Payment Received:Currency:100", "Outstanding Amount:Currency:100", "Age:Int:50", "0-30:Currency:100", - "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100" + "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100", + "Customer:Link/Customer:200" ] - if self.get_customer_naming() == "Naming Series": - columns += ["Customer:Link/Customer:200"] + if customer_naming_by == "Naming Series": + columns += ["Customer Name::110"] - columns += ["Customer Name::110", "Territory:Link/Territory:80", "Remarks::200"] + columns += ["Territory:Link/Territory:80", "Remarks::200"] return columns - def get_data(self): + def get_data(self, customer_naming_by): data = [] future_vouchers = self.get_entries_after(self.filters.report_date) for gle in self.get_entries_till(self.filters.report_date): @@ -50,23 +52,21 @@ class AccountsReceivableReport(object): outstanding_amount] entry_date = due_date if self.filters.ageing_based_on == "Due Date" \ else gle.posting_date - row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) + row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) + \ + [self.get_customer(gle.account)] - if self.get_customer_naming() == "Naming Series": - row += [self.get_customer(gle.account)] + if customer_naming_by == "Naming Series": + row += [self.get_customer_name(gle.account)] - row += [self.get_customer_name(gle.account), self.get_territory(gle.account), gle.remarks] + row += [self.get_territory(gle.account), gle.remarks] data.append(row) - for i in range(0,len(data)): + for i in range(0, len(data)): data[i].insert(4, """""" \ % ("/".join(["#Form", data[i][2], data[i][3]]),)) return data - def get_customer_naming(self): - return webnotes.conn.get_value("Selling Settings", None, "cust_master_name") - def get_entries_after(self, report_date): # returns a distinct list return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries() @@ -163,7 +163,7 @@ class AccountsReceivableReport(object): def execute(filters=None): return AccountsReceivableReport(filters).run() - + def get_ageing_data(age_as_on, entry_date, outstanding_amount): # [0-30, 30-60, 60-90, 90-above] outstanding_range = [0.0, 0.0, 0.0, 0.0] From 866103bf666cd6bec9e96e478f8bf701207fb614 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Fri, 3 Jan 2014 13:57:06 +0600 Subject: [PATCH 28/87] bumped to version 3.4.5 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index e8955b178c..89c1332005 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.4", + "app_version": "3.4.5", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { From 33f6b9d6e8079df15c32773008f7c68fadbb4715 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 15:12:16 +0530 Subject: [PATCH 29/87] Unlinked message listing all linked entries while cancelling an accounting trandsaction --- accounts/utils.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/accounts/utils.py b/accounts/utils.py index a5fb390e9f..fdd57b35c2 100644 --- a/accounts/utils.py +++ b/accounts/utils.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import nowdate, nowtime, cstr, flt, now, getdate, add_months +from webnotes.utils import nowdate, cstr, flt, now, getdate, add_months from webnotes.model.doc import addchild from webnotes import msgprint, _ from webnotes.utils import formatdate @@ -64,7 +64,6 @@ def get_balance_on(account=None, date=None): try: year_start_date = get_fiscal_year(date, verbose=0)[1] except FiscalYearError, e: - from webnotes.utils import getdate if getdate(date) > getdate(nowdate()): # if fiscal year not found and the date is greater than today # get fiscal year for today's date and its corresponding year start date @@ -222,17 +221,26 @@ def get_cost_center_list(doctype, txt, searchfield, start, page_len, filters): tuple(filter_values + ["%%%s%%" % txt, start, page_len])) def remove_against_link_from_jv(ref_type, ref_no, against_field): - webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null, - modified=%s, modified_by=%s - where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"), - (now(), webnotes.session.user, ref_no)) + linked_jv = webnotes.conn.sql_list("""select parent from `tabJournal Voucher Detail` + where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no)) + + if linked_jv: + webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null, + modified=%s, modified_by=%s + where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"), + (now(), webnotes.session.user, ref_no)) - webnotes.conn.sql("""update `tabGL Entry` - set against_voucher_type=null, against_voucher=null, - modified=%s, modified_by=%s - where against_voucher_type=%s and against_voucher=%s - and voucher_no != ifnull(against_voucher, '')""", - (now(), webnotes.session.user, ref_type, ref_no)) + webnotes.conn.sql("""update `tabGL Entry` + set against_voucher_type=null, against_voucher=null, + modified=%s, modified_by=%s + where against_voucher_type=%s and against_voucher=%s + and voucher_no != ifnull(against_voucher, '')""", + (now(), webnotes.session.user, ref_type, ref_no)) + + webnotes.msgprint("{msg} {linked_jv}".format(msg = _("""Following linked Journal Vouchers \ + made against this transaction has been unlinked. You can link them again with other \ + transactions via Payment Reconciliation Tool."""), linked_jv="\n".join(linked_jv))) + @webnotes.whitelist() def get_company_default(company, fieldname): @@ -370,4 +378,4 @@ def get_account_for(account_for_doctype, account_for): account_for_field = "account_type" return webnotes.conn.get_value("Account", {account_for_field: account_for_doctype, - "master_name": account_for}) + "master_name": account_for}) \ No newline at end of file From 7f0406f281a5d38f442244fd7373a9daf29975e4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 17:43:19 +0530 Subject: [PATCH 30/87] Chekc over billing validation considering tolerance --- controllers/accounts_controller.py | 35 ++++++++++++++++++------- controllers/status_updater.py | 41 ++++++++++++++++-------------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 11480c9ebe..1a399219e4 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -381,24 +381,41 @@ class AccountsController(TransactionBase): }) def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): + from controllers.status_updater import get_tolerance_for + item_tolerance = {} + global_tolerance = None + for item in self.doclist.get({"parentfield": "entries"}): if item.fields.get(item_ref_dn): already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s` where %s=%s and docstatus=1""" % (based_on, self.tname, item_ref_dn, '%s'), item.fields[item_ref_dn])[0][0] - max_allowed_amt = flt(webnotes.conn.get_value(ref_dt + " Item", - item.fields[item_ref_dn], based_on), self.precision(based_on, item)) - total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]), self.precision(based_on, item)) + + ref_amt = flt(webnotes.conn.get_value(ref_dt + " Item", + item.fields[item_ref_dn], based_on), self.precision(based_on, item)) + + tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code, + item_tolerance, global_tolerance) - if max_allowed_amt and total_billed_amt - max_allowed_amt > 0.02: - webnotes.msgprint(_("Row ")+ cstr(item.idx) + ": " + cstr(item.item_code) + - _(" will be over-billed against mentioned ") + cstr(ref_dt) + - _(". Max allowed " + cstr(based_on) + ": " + cstr(max_allowed_amt)), - raise_exception=1) - + max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) + + if total_billed_amt - max_allowed_amt > 0.01: + reduce_by = total_billed_amt - max_allowed_amt + + webnotes.throw(_("Row #") + cstr(item.idx) + ": " + + _(" Max amount allowed for Item ") + cstr(item.item_code) + + _(" against ") + ref_dt + " " + + cstr(item.fields[ref_dt.lower().replace(" ", "_")]) + _(" is ") + + cstr(max_allowed_amt) + ". \n" + + _("""If you want to increase your overflow tolerance, please increase \ + tolerance % in Global Defaults or Item master. + Or, you must reduce the amount by """) + cstr(reduce_by) + "\n" + + _("""Also, please check if the order item has already been billed \ + in the Sales Order""")) + def get_company_default(self, fieldname): from accounts.utils import get_company_default return get_company_default(self.doc.company, fieldname) diff --git a/controllers/status_updater.py b/controllers/status_updater.py index b2745268f7..a285c4798d 100644 --- a/controllers/status_updater.py +++ b/controllers/status_updater.py @@ -151,7 +151,9 @@ class StatusUpdater(DocListController): """ # check if overflow is within tolerance - tolerance = self.get_tolerance_for(item['item_code']) + tolerance, self.tolerance, self.global_tolerance = get_tolerance_for(item['item_code'], + self.tolerance, self.global_tolerance) + overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) / item[args['target_ref_field']]) * 100 @@ -170,23 +172,6 @@ class StatusUpdater(DocListController): Also, please check if the order item has already been billed in the Sales Order""" % item, raise_exception=1) - - def get_tolerance_for(self, item_code): - """ - Returns the tolerance for the item, if not set, returns global tolerance - """ - if self.tolerance.get(item_code): return self.tolerance[item_code] - - tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0) - - if not tolerance: - if self.global_tolerance == None: - self.global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None, - 'tolerance')) - tolerance = self.global_tolerance - - self.tolerance[item_code] = tolerance - return tolerance def update_qty(self, change_modified=True): @@ -245,4 +230,22 @@ class StatusUpdater(DocListController): set %(status_field)s = if(ifnull(%(target_parent_field)s,0)<0.001, 'Not %(keyword)s', if(%(target_parent_field)s>=99.99, 'Fully %(keyword)s', 'Partly %(keyword)s')) - where name='%(name)s'""" % args) \ No newline at end of file + where name='%(name)s'""" % args) + +def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None): + """ + Returns the tolerance for the item, if not set, returns global tolerance + """ + if item_tolerance.get(item_code): + return item_tolerance[item_code], item_tolerance, global_tolerance + + tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0) + + if not tolerance: + if global_tolerance == None: + global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None, + 'tolerance')) + tolerance = global_tolerance + + item_tolerance[item_code] = tolerance + return tolerance, item_tolerance, global_tolerance \ No newline at end of file From b476c989a40da3d025155311fcbc945468a860d6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 17:43:52 +0530 Subject: [PATCH 31/87] Fixes test cases for date and year mismatch --- accounts/doctype/sales_invoice/test_sales_invoice.py | 9 +++++---- buying/doctype/purchase_order/test_purchase_order.py | 7 ++++--- .../doctype/production_order/test_production_order.py | 3 ++- selling/doctype/quotation/test_quotation.py | 1 + selling/doctype/sales_order/test_sales_order.py | 1 + stock/doctype/material_request/test_material_request.py | 1 + 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 5a573f9441..e98dfdc2a0 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -565,16 +565,17 @@ class TestSalesInvoice(unittest.TestCase): where against_invoice=%s""", si.doc.name)) def test_recurring_invoice(self): - from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date - today = now_datetime().date() - + from webnotes.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate + from accounts.utils import get_fiscal_year + today = nowdate() base_si = webnotes.bean(copy=test_records[0]) base_si.doc.fields.update({ "convert_into_recurring_invoice": 1, "recurring_type": "Monthly", "notification_email_address": "test@example.com, test1@example.com, test2@example.com", - "repeat_on_day_of_month": today.day, + "repeat_on_day_of_month": getdate(today).day, "posting_date": today, + "fiscal_year": get_fiscal_year(today)[0], "invoice_period_from_date": get_first_day(today), "invoice_period_to_date": get_last_day(today) }) diff --git a/buying/doctype/purchase_order/test_purchase_order.py b/buying/doctype/purchase_order/test_purchase_order.py index f6c435c6fb..e1933982c4 100644 --- a/buying/doctype/purchase_order/test_purchase_order.py +++ b/buying/doctype/purchase_order/test_purchase_order.py @@ -22,7 +22,7 @@ class TestPurchaseOrder(unittest.TestCase): pr = make_purchase_receipt(po.doc.name) pr[0]["supplier_warehouse"] = "_Test Warehouse 1 - _TC" - + pr[0]["posting_date"] = "2013-05-12" self.assertEquals(pr[0]["doctype"], "Purchase Receipt") self.assertEquals(len(pr), len(test_records[0])) @@ -52,7 +52,7 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(pr[0]["doctype"], "Purchase Receipt") self.assertEquals(len(pr), len(test_records[0])) - + pr[0]["posting_date"] = "2013-05-12" pr[0].naming_series = "_T-Purchase Receipt-" pr[1].qty = 4.0 pr_bean = webnotes.bean(pr) @@ -66,6 +66,7 @@ class TestPurchaseOrder(unittest.TestCase): pr1 = make_purchase_receipt(po.doc.name) pr1[0].naming_series = "_T-Purchase Receipt-" + pr1[0]["posting_date"] = "2013-05-12" pr1[1].qty = 8 pr1_bean = webnotes.bean(pr1) pr1_bean.insert() @@ -88,7 +89,7 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(pi[0]["doctype"], "Purchase Invoice") self.assertEquals(len(pi), len(test_records[0])) - + pi[0]["posting_date"] = "2013-05-12" pi[0].bill_no = "NA" webnotes.bean(pi).insert() diff --git a/manufacturing/doctype/production_order/test_production_order.py b/manufacturing/doctype/production_order/test_production_order.py index 52697292c8..ca28708cc1 100644 --- a/manufacturing/doctype/production_order/test_production_order.py +++ b/manufacturing/doctype/production_order/test_production_order.py @@ -34,6 +34,7 @@ class TestProductionOrder(unittest.TestCase): stock_entry = webnotes.bean(stock_entry) stock_entry.doc.fg_completed_qty = 4 + stock_entry.doc.posting_date = "2013-05-12" stock_entry.run_method("get_items") stock_entry.submit() @@ -50,7 +51,7 @@ class TestProductionOrder(unittest.TestCase): stock_entry = make_stock_entry(pro_order, "Manufacture/Repack") stock_entry = webnotes.bean(stock_entry) - + stock_entry.doc.posting_date = "2013-05-12" stock_entry.doc.fg_completed_qty = 15 stock_entry.run_method("get_items") stock_entry.insert() diff --git a/selling/doctype/quotation/test_quotation.py b/selling/doctype/quotation/test_quotation.py index 8f0e644cb9..327d72f2e0 100644 --- a/selling/doctype/quotation/test_quotation.py +++ b/selling/doctype/quotation/test_quotation.py @@ -28,6 +28,7 @@ class TestQuotation(unittest.TestCase): sales_order[0]["delivery_date"] = "2014-01-01" sales_order[0]["naming_series"] = "_T-Quotation-" + sales_order[0]["transaction_date"] = "2013-05-12" webnotes.bean(sales_order).insert() diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py index 1549b24c89..a6fe8fb5bb 100644 --- a/selling/doctype/sales_order/test_sales_order.py +++ b/selling/doctype/sales_order/test_sales_order.py @@ -53,6 +53,7 @@ class TestSalesOrder(unittest.TestCase): self.assertEquals(len([d for d in si if d["doctype"]=="Sales Invoice Item"]), 1) si = webnotes.bean(si) + si.doc.posting_date = "2013-10-10" si.insert() si.submit() diff --git a/stock/doctype/material_request/test_material_request.py b/stock/doctype/material_request/test_material_request.py index c19bfd3928..81ae27d8c2 100644 --- a/stock/doctype/material_request/test_material_request.py +++ b/stock/doctype/material_request/test_material_request.py @@ -125,6 +125,7 @@ class TestMaterialRequest(unittest.TestCase): from stock.doctype.material_request.material_request import make_purchase_order po_doclist = make_purchase_order(mr.doc.name) po_doclist[0].supplier = "_Test Supplier" + po_doclist[0].transaction_date = "2013-07-07" po_doclist[1].qty = 27.0 po_doclist[2].qty = 1.5 po_doclist[1].schedule_date = "2013-07-09" From 57738a0ff3e0880d40515b5be46a4b89aaab6962 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 3 Jan 2014 18:15:07 +0530 Subject: [PATCH 32/87] flat discount replaced to discount amount --- .../Print Format/POS Invoice/POS Invoice.txt | 2 +- .../Sales Invoice Classic.txt | 2 +- .../Sales Invoice Modern.txt | 2 +- .../Sales Invoice Spartan.txt | 2 +- erpnext/accounts/doctype/sales_invoice/pos.js | 12 +++--- .../doctype/sales_invoice/sales_invoice.py | 4 +- .../doctype/sales_invoice/sales_invoice.txt | 6 +-- .../sales_invoice/test_sales_invoice.py | 10 ++--- .../sales_taxes_and_charges.txt | 6 +-- .../sales_taxes_and_charges_master.js | 8 ++-- .../report/sales_register/sales_register.py | 4 +- .../purchase_common/purchase_common.js | 4 +- erpnext/controllers/accounts_controller.py | 42 +++++++++---------- erpnext/controllers/buying_controller.py | 6 +-- erpnext/controllers/selling_controller.py | 28 ++++++------- erpnext/patches.txt | 20 ++++++++- erpnext/public/js/transaction.js | 37 +++++++++------- .../Quotation Classic/Quotation Classic.txt | 2 +- .../Quotation Modern/Quotation Modern.txt | 2 +- .../Quotation Spartan/Quotation Spartan.txt | 2 +- .../Sales Order Classic.txt | 2 +- .../Sales Order Modern/Sales Order Modern.txt | 2 +- .../Sales Order Spartan.txt | 2 +- .../selling/doctype/quotation/quotation.txt | 6 +-- .../doctype/sales_order/sales_order.txt | 6 +-- erpnext/selling/sales_common.js | 38 ++++++++--------- .../Delivery Note Classic.txt | 2 +- .../Delivery Note Modern.txt | 2 +- .../Delivery Note Spartan.txt | 2 +- .../doctype/delivery_note/delivery_note.txt | 6 +-- 30 files changed, 144 insertions(+), 125 deletions(-) diff --git a/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt b/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt index 0907c4a865..980195642f 100644 --- a/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/erpnext/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt b/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt index 4e8b12b943..09fcb91476 100644 --- a/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt +++ b/erpnext/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt b/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt index 6808c009e6..a85a11abc8 100644 --- a/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt +++ b/erpnext/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt b/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt index 45905fc2e1..e0850e1e9a 100644 --- a/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt +++ b/erpnext/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/accounts/doctype/sales_invoice/pos.js b/erpnext/accounts/doctype/sales_invoice/pos.js index 1da6f735f6..1b14f05dc1 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.js +++ b/erpnext/accounts/doctype/sales_invoice/pos.js @@ -50,13 +50,13 @@ erpnext.POS = Class.extend({
\
\ -
\ +
\ \ \ - \ + \ \ \ \ @@ -96,8 +96,8 @@ erpnext.POS = Class.extend({ me.refresh(); }); - this.wrapper.find('input.flat-discount').on("change", function() { - wn.model.set_value(me.frm.doctype, me.frm.docname, "flat_discount", this.value); + this.wrapper.find('input.discount-amount').on("change", function() { + wn.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", this.value); }); this.call_function("delete-items", function() {me.remove_selected_item();}); @@ -339,7 +339,7 @@ erpnext.POS = Class.extend({ refresh: function() { var me = this; this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]); - this.wrapper.find('input.flat-discount').val(this.frm.doc.flat_discount); + this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount); this.barcode.set_input(""); this.show_items_in_item_cart(); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 55c2ecaa59..4a059441fe 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -556,12 +556,12 @@ class DocType(SellingController): def make_tax_gl_entries(self, gl_entries): for tax in self.doclist.get({"parentfield": "other_charges"}): - if flt(tax.tax_amount_after_flat_discount): + if flt(tax.tax_amount_after_discount_amount): gl_entries.append( self.get_gl_dict({ "account": tax.account_head, "against": self.doc.debit_to, - "credit": flt(tax.tax_amount_after_flat_discount), + "credit": flt(tax.tax_amount_after_discount_amount), "remarks": self.doc.remarks, "cost_center": tax.cost_center }) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt b/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt index 0fcb79d86b..66f7d32c3d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-12-26 17:50:21", + "modified": "2014-01-03 14:52:16", "modified_by": "Administrator", "owner": "Administrator" }, @@ -457,9 +457,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency", "print_hide": 0 }, diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4b49eb4715..709507abc1 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -136,9 +136,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1627.05) self.assertEquals(si.doc.grand_total_export, 32.54) - def test_sales_invoice_flat_discount(self): + def test_sales_invoice_discount_amount(self): si = webnotes.bean(copy=test_records[3]) - si.doc.flat_discount = 104.95 + si.doc.discount_amount = 104.95 si.doclist.append({ "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", @@ -174,7 +174,7 @@ class TestSalesInvoice(unittest.TestCase): # check tax calculation expected_values = { - "keys": ["tax_amount", "tax_amount_after_flat_discount", "total"], + "keys": ["tax_amount", "tax_amount_after_discount_amount", "total"], "_Test Account Excise Duty - _TC": [140, 130.31, 1293.76], "_Test Account Education Cess - _TC": [2.8, 2.61, 1296.37], "_Test Account S&H Education Cess - _TC": [1.4, 1.31, 1297.68], @@ -193,9 +193,9 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(si.doc.grand_total, 1500) self.assertEquals(si.doc.grand_total_export, 1500) - def test_flat_discount_gl_entry(self): + def test_discount_amount_gl_entry(self): si = webnotes.bean(copy=test_records[3]) - si.doc.flat_discount = 104.95 + si.doc.discount_amount = 104.95 si.doclist.append({ "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt index 1b3b6f8939..f3c41a649f 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-24 11:39:32", "docstatus": 0, - "modified": "2013-12-20 19:21:45", + "modified": "2014-01-03 15:04:25", "modified_by": "Administrator", "owner": "Administrator" }, @@ -133,10 +133,10 @@ }, { "doctype": "DocField", - "fieldname": "tax_amount_after_flat_discount", + "fieldname": "tax_amount_after_discount_amount", "fieldtype": "Currency", "hidden": 1, - "label": "Tax Amount After Flat Discount", + "label": "Tax Amount After Discount Amount", "options": "Company:company:default_currency", "read_only": 1 }, diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index 2ac6be7a25..0e9b3db6c0 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -19,7 +19,7 @@ cur_frm.pformat.net_total_export = function(doc) { return ''; } -cur_frm.pformat.flat_discount = function(doc) { +cur_frm.pformat.discount_amount = function(doc) { return ''; } @@ -77,9 +77,9 @@ cur_frm.pformat.other_charges= function(doc){ } } - // flat discount - if(!print_hide('flat_discount') && doc.flat_discount) { - out += make_row('Flat Discount', doc.flat_discount, 0); + // Discount Amount + if(!print_hide('discount_amount') && doc.discount_amount) { + out += make_row('Discount Amount', convert_rate(doc.discount_amount), 0); } // grand total diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 98ef93662d..8fab6a9d97 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -79,7 +79,7 @@ def get_columns(invoice_list): tax_accounts = webnotes.conn.sql_list("""select distinct account_head from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' - and docstatus = 1 and ifnull(tax_amount_after_flat_discount, 0) != 0 + and docstatus = 1 and ifnull(tax_amount_after_discount_amount, 0) != 0 and parent in (%s) order by account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) @@ -127,7 +127,7 @@ def get_invoice_income_map(invoice_list): def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts): tax_details = webnotes.conn.sql("""select parent, account_head, - sum(tax_amount_after_flat_discount) as tax_amount + sum(tax_amount_after_discount_amount) as tax_amount from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 29e4781d29..f528f6cf1b 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -362,9 +362,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ } if(this.frm.tax_doclist.length) { - if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_flat_discount", this.frm.doctype)) { + if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_discount_amount", this.frm.doctype)) { $.each(this.frm.tax_doclist, function(i, tax) { - delete tax["tax_amount_after_flat_discount"]; + delete tax["tax_amount_after_discount_amount"]; }); } } diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 9b8dc2963d..e7393eb735 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -16,10 +16,7 @@ class AccountsController(TransactionBase): self.set_missing_values(for_validate=True) self.validate_date_with_fiscal_year() if self.meta.get_field("currency"): - self.flat_discount_applied = False self.calculate_taxes_and_totals() - if hasattr(self, "apply_flat_discount"): - self.apply_flat_discount() self.validate_value("grand_total", ">=", 0) self.set_total_in_words() @@ -136,6 +133,12 @@ class AccountsController(TransactionBase): self.doclist.append(tax) def calculate_taxes_and_totals(self): + self.discount_amount_applied = False + self._calculate_taxes_and_totals() + if self.meta.get_field(self.doc.doctype, "discount_amount"): + self.apply_discount_amount() + + def _calculate_taxes_and_totals(self): # validate conversion rate company_currency = get_company_currency(self.doc.company) if not self.doc.currency or self.doc.currency == company_currency: @@ -148,10 +151,6 @@ class AccountsController(TransactionBase): self.doc.conversion_rate = flt(self.doc.conversion_rate) self.item_doclist = self.doclist.get({"parentfield": self.fname}) self.tax_doclist = self.doclist.get({"parentfield": self.other_fname}) - - # for buying - if not hasattr(self, "flat_discount_applied"): - self.flat_discount_applied = False self.calculate_item_values() self.initialize_taxes() @@ -164,17 +163,14 @@ class AccountsController(TransactionBase): self.calculate_totals() self._cleanup() - # TODO - # print format: show net_total_export instead of net_total - def initialize_taxes(self): for tax in self.tax_doclist: tax.item_wise_tax_detail = {} - tax_fields = ["total", "tax_amount_after_flat_discount", + tax_fields = ["total", "tax_amount_after_discount_amount", "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] - if not self.flat_discount_applied: + if not self.discount_amount_applied: tax_fields.append("tax_amount") for fieldname in tax_fields: @@ -261,10 +257,10 @@ class AccountsController(TransactionBase): tax.tax_amount_for_current_item = current_tax_amount # accumulate tax amount into tax.tax_amount - if not self.flat_discount_applied: + if not self.discount_amount_applied: tax.tax_amount += current_tax_amount - tax.tax_amount_after_flat_discount += current_tax_amount + tax.tax_amount_after_discount_amount += current_tax_amount if tax.category: # if just for valuation, do not add the tax amount in total @@ -291,21 +287,21 @@ class AccountsController(TransactionBase): if n == len(self.item_doclist) - 1: self.round_off_totals(tax) - # adjust flat discount loss in last tax iteration - if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied: - self.adjust_flat_discount_loss(tax) + # adjust Discount Amount loss in last tax iteration + if i == (len(self.tax_doclist) - 1) and self.discount_amount_applied: + self.adjust_discount_amount_loss(tax) def round_off_totals(self, tax): tax.total = flt(tax.total, self.precision("total", tax)) tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount, self.precision("tax_amount", tax)) - def adjust_flat_discount_loss(self, tax): - flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + - flat_discount_loss, self.precision("tax_amount", tax)) - tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax)) + def adjust_discount_amount_loss(self, tax): + discount_amount_loss = self.doc.grand_total - flt(self.doc.discount_amount) - tax.total + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount + + discount_amount_loss, self.precision("tax_amount", tax)) + tax.total = flt(tax.total + discount_amount_loss, self.precision("total", tax)) def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index be07670450..f630f5ae83 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -147,7 +147,7 @@ class BuyingController(StockController): def _cleanup(self): super(BuyingController, self)._cleanup() - # except in purchase invoice, rate field is purchase_rate + # except in purchase invoice, rate field is purchase_rate # reset fieldname of rate if self.doc.doctype != "Purchase Invoice": df = self.meta.get_field("rate", parentfield=self.fname) @@ -161,9 +161,9 @@ class BuyingController(StockController): for item in self.item_doclist: del item.fields["item_tax_amount"] - if not self.meta.get_field("tax_amount_after_flat_discount", parentfield=self.other_fname): + if not self.meta.get_field("tax_amount_after_discount_amount", parentfield=self.other_fname): for tax in self.tax_doclist: - del tax.fields["tax_amount_after_flat_discount"] + del tax.fields["tax_amount_after_discount_amount"] def set_item_tax_amount(self, item, tax, current_tax_amount): """ diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 9e0fa1b2aa..04bcfaeb04 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -121,7 +121,7 @@ class SellingController(StockController): cumulated_tax_fraction += tax.tax_fraction_for_current_item - if cumulated_tax_fraction and not self.flat_discount_applied: + if cumulated_tax_fraction and not self.discount_amount_applied: item.amount = flt((item.export_amount * self.doc.conversion_rate) / (1 + cumulated_tax_fraction), self.precision("amount", item)) @@ -158,7 +158,7 @@ class SellingController(StockController): return current_tax_fraction def calculate_item_values(self): - if not self.flat_discount_applied: + if not self.discount_amount_applied: for item in self.item_doclist: self.round_floats_in(item) @@ -193,25 +193,25 @@ class SellingController(StockController): self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total, self.precision("other_charges_total")) self.doc.other_charges_total_export = flt(self.doc.grand_total_export - - self.doc.net_total_export + flt(self.doc.flat_discount), self.precision("other_charges_total_export")) + self.doc.net_total_export + flt(self.doc.discount_amount), self.precision("other_charges_total_export")) self.doc.rounded_total = _round(self.doc.grand_total) self.doc.rounded_total_export = _round(self.doc.grand_total_export) - def apply_flat_discount(self): - if self.doc.flat_discount: - total_amount_for_flat_discount = self.get_flat_discountable_amount() + def apply_discount_amount(self): + if self.doc.discount_amount: + grand_total_for_discount_amount = self.get_grand_total_for_discount_amount() - if total_amount_for_flat_discount: - # calculate item amount after flat discount + if grand_total_for_discount_amount: + # calculate item amount after Discount Amount for item in self.item_doclist: - distributed_amount = self.doc.flat_discount * item.amount / total_amount_for_flat_discount + distributed_amount = flt(self.doc.discount_amount) * item.amount / grand_total_for_discount_amount item.amount = flt(item.amount - distributed_amount, self.precision("amount", item)) - self.flat_discount_applied = True - self.calculate_taxes_and_totals() + self.discount_amount_applied = True + self._calculate_taxes_and_totals() - def get_flat_discountable_amount(self): + def get_grand_total_for_discount_amount(self): actual_taxes_dict = {} for tax in self.tax_doclist: @@ -222,9 +222,9 @@ class SellingController(StockController): flt(tax.rate) / 100 actual_taxes_dict.setdefault(tax.idx, actual_tax_amount) - total_amount_for_flat_discount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()), + grand_total_for_discount_amount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()), self.precision("grand_total")) - return total_amount_for_flat_discount + return grand_total_for_discount_amount def calculate_outstanding_amount(self): # NOTE: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index c1ab098298..f39e214245 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -1,3 +1,21 @@ erpnext.patches.4_0.update_user_properties erpnext.patches.4_0.move_warehouse_user_to_restrictions -erpnext.patches.4_0.new_permissions \ No newline at end of file +erpnext.patches.4_0.new_permissions + +execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2014-01-03 +execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2014-01-03 +execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2014-01-03 +execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2014-01-03 \ No newline at end of file diff --git a/erpnext/public/js/transaction.js b/erpnext/public/js/transaction.js index e716c278ae..7db7aef51d 100644 --- a/erpnext/public/js/transaction.js +++ b/erpnext/public/js/transaction.js @@ -146,9 +146,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, validate: function() { - this.flat_discount_applied = false; this.calculate_taxes_and_totals(); - this.apply_flat_discount && this.apply_flat_discount(); }, set_default_values: function() { @@ -513,6 +511,13 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, calculate_taxes_and_totals: function() { + this.discount_amount_applied = false; + this._calculate_taxes_and_totals(); + if (wn.meta.get_docfield(this.frm.doc.doctype, "discount_amount")) + this.apply_discount_amount(); + }, + + _calculate_taxes_and_totals: function() { this.validate_conversion_rate(); this.frm.item_doclist = this.get_item_doclist(); this.frm.tax_doclist = this.get_tax_doclist(); @@ -524,7 +529,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ this.calculate_taxes(); this.calculate_totals(); this._cleanup(); - + this.show_item_wise_taxes(); }, @@ -533,11 +538,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ $.each(this.frm.tax_doclist, function(i, tax) { tax.item_wise_tax_detail = {}; - tax_fields = ["total", "tax_amount_after_flat_discount", + tax_fields = ["total", "tax_amount_after_discount_amount", "tax_amount_for_current_item", "grand_total_for_current_item", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"] - if (!me.flat_discount_applied) + if (!me.discount_amount_applied) tax_fields.push("tax_amount"); $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); @@ -581,10 +586,10 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ tax.tax_amount_for_current_item = current_tax_amount; // accumulate tax amount into tax.tax_amount - if (!me.flat_discount_applied) + if (!me.discount_amount_applied) tax.tax_amount += current_tax_amount; - tax.tax_amount_after_flat_discount += current_tax_amount; + tax.tax_amount_after_discount_amount += current_tax_amount; // for buying if(tax.category) { @@ -614,9 +619,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ if (n == me.frm.item_doclist.length - 1) { me.round_off_totals(tax); - // adjust flat discount loss in last tax iteration - if ((i == me.frm.tax_doclist.length - 1) && me.flat_discount_applied) - me.adjust_flat_discount_loss(tax); + // adjust Discount Amount loss in last tax iteration + if ((i == me.frm.tax_doclist.length - 1) && me.discount_amount_applied) + me.adjust_discount_amount_loss(tax); } }); }); @@ -625,15 +630,15 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ round_off_totals: function(tax) { tax.total = flt(tax.total, precision("total", tax)); tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)); - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount, + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount, precision("tax_amount", tax)); }, - adjust_flat_discount_loss: function(tax) { - var flat_discount_loss = this.frm.doc.grand_total - this.frm.doc.flat_discount - tax.total; - tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount + - flat_discount_loss, precision("tax_amount", tax)); - tax.total = flt(tax.total + flat_discount_loss, precision("total", tax)); + adjust_discount_amount_loss: function(tax) { + var discount_amount_loss = this.frm.doc.grand_total - flt(this.frm.doc.discount_amount) - tax.total; + tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount + + discount_amount_loss, precision("tax_amount", tax)); + tax.total = flt(tax.total + discount_amount_loss, precision("total", tax)); }, get_current_tax_amount: function(item, tax, item_tax_map) { diff --git a/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt b/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt index dc845290fe..05c3c598ca 100644 --- a/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt +++ b/erpnext/selling/Print Format/Quotation Classic/Quotation Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n
Flat DiscountDiscount Amount\ - \
\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t
\n\t\t\t\t\t\n\t\t\t

\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
Name
Address
Contact
\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t
Quotation Date
\n
\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt b/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt index 8b4b0d8f65..35850e62eb 100644 --- a/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt +++ b/erpnext/selling/Print Format/Quotation Modern/Quotation Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt b/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt index c4a1362ad3..3b4452666b 100644 --- a/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt +++ b/erpnext/selling/Print Format/Quotation Spartan/Quotation Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Quotation", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt b/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt index 1d36ee6a77..7ee19c0f2d 100644 --- a/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt +++ b/erpnext/selling/Print Format/Sales Order Classic/Sales Order Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt b/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt index 157c8eb29c..7cf481d7b8 100644 --- a/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt +++ b/erpnext/selling/Print Format/Sales Order Modern/Sales Order Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt b/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt index 8dce87eca4..8da27b7d70 100644 --- a/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt +++ b/erpnext/selling/Print Format/Sales Order Spartan/Sales Order Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Sales Order", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Selling", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/selling/doctype/quotation/quotation.txt b/erpnext/selling/doctype/quotation/quotation.txt index 5453cb4e18..4795653262 100644 --- a/erpnext/selling/doctype/quotation/quotation.txt +++ b/erpnext/selling/doctype/quotation/quotation.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:08", "docstatus": 0, - "modified": "2013-12-26 17:54:55", + "modified": "2014-01-03 14:54:05", "modified_by": "Administrator", "owner": "Administrator" }, @@ -462,9 +462,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency" }, { diff --git a/erpnext/selling/doctype/sales_order/sales_order.txt b/erpnext/selling/doctype/sales_order/sales_order.txt index 2469a467f6..2dc62f334a 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.txt +++ b/erpnext/selling/doctype/sales_order/sales_order.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-18 12:39:59", "docstatus": 0, - "modified": "2013-12-26 17:55:43", + "modified": "2014-01-03 14:51:19", "modified_by": "Administrator", "owner": "Administrator" }, @@ -482,9 +482,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency" }, { diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 4562c2b217..330e725ed8 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -226,10 +226,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.calculate_taxes_and_totals(); }, - flat_discount: function() { - this.flat_discount_applied = false; + discount_amount: function() { this.calculate_taxes_and_totals(); - this.apply_flat_discount(); }, commission_rate: function() { @@ -317,7 +315,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ calculate_item_values: function() { var me = this; - if (!this.flat_discount_applied) { + if (!this.discount_amount_applied) { $.each(this.frm.item_doclist, function(i, item) { wn.model.round_floats_in(item); item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item)); @@ -349,7 +347,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ cumulated_tax_fraction += tax.tax_fraction_for_current_item; }); - if(cumulated_tax_fraction && !me.flat_discount_applied) { + if(cumulated_tax_fraction && !me.discount_amount_applied) { item.amount = flt( (item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), precision("amount", item)); @@ -416,31 +414,33 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("other_charges_total")); this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export - - this.frm.doc.net_total_export + this.frm.doc.flat_discount, + this.frm.doc.net_total_export + flt(this.frm.doc.discount_amount), precision("other_charges_total_export")); this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total); this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export); }, - apply_flat_discount: function() { + apply_discount_amount: function() { var me = this; var distributed_amount = 0.0; - if (this.frm.doc.flat_discount) { - var total_amount_for_flat_discount = this.get_flat_discountable_amount(); - // calculate item amount after flat discount - $.each(this.frm.item_doclist, function(i, item) { - distributed_amount = me.frm.doc.flat_discount * item.amount / total_amount_for_flat_discount; - item.amount = flt(item.amount - distributed_amount, precision("amount", item)); - }); + if (this.frm.doc.discount_amount) { + var grand_total_for_discount_amount = this.get_grand_total_for_discount_amount(); + // calculate item amount after Discount Amount + if (grand_total_for_discount_amount) { + $.each(this.frm.item_doclist, function(i, item) { + distributed_amount = flt(me.frm.doc.discount_amount) * item.amount / grand_total_for_discount_amount; + item.amount = flt(item.amount - distributed_amount, precision("amount", item)); + }); - this.flat_discount_applied = true; - this.calculate_taxes_and_totals(); + this.discount_amount_applied = true; + this._calculate_taxes_and_totals(); + } } }, - get_flat_discountable_amount: function() { + get_grand_total_for_discount_amount: function() { var me = this; var total_actual_tax = 0.0; var actual_taxes_dict = {}; @@ -459,9 +459,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ total_actual_tax += value; }); - total_amount_for_flat_discount = flt(this.frm.doc.grand_total - total_actual_tax, + grand_total_for_discount_amount = flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total")); - return total_amount_for_flat_discount; + return grand_total_for_discount_amount; }, calculate_outstanding_amount: function() { diff --git a/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt b/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt index d16b67fea6..d4c0cc1983 100644 --- a/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt +++ b/erpnext/stock/Print Format/Delivery Note Classic/Delivery Note Classic.txt @@ -9,7 +9,7 @@ { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt b/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt index 9965634355..3b36f6f1c0 100644 --- a/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt +++ b/erpnext/stock/Print Format/Delivery Note Modern/Delivery Note Modern.txt @@ -9,7 +9,7 @@ { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt b/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt index 2623d76183..072d411004 100644 --- a/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt +++ b/erpnext/stock/Print Format/Delivery Note Spartan/Delivery Note Spartan.txt @@ -9,7 +9,7 @@ { "doc_type": "Delivery Note", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n", "module": "Stock", "name": "__common__", "print_format_type": "Client", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.txt b/erpnext/stock/doctype/delivery_note/delivery_note.txt index c328874959..b2677a39e5 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.txt +++ b/erpnext/stock/doctype/delivery_note/delivery_note.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:09", "docstatus": 0, - "modified": "2013-12-26 18:01:33", + "modified": "2014-01-03 14:53:03", "modified_by": "Administrator", "owner": "Administrator" }, @@ -492,9 +492,9 @@ }, { "doctype": "DocField", - "fieldname": "flat_discount", + "fieldname": "discount_amount", "fieldtype": "Currency", - "label": "Flat Discount", + "label": "Discount Amount", "options": "Company:company:default_currency" }, { From 5d5fe5d9d50a94403ecb52e1814f1c8afc56eb13 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jan 2014 18:28:53 +0530 Subject: [PATCH 33/87] Cost center field added in Purchase Receipt Item table --- .../purchase_receipt_item/purchase_receipt_item.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt index 9a641c2ba3..1d9397909d 100755 --- a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt +++ b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:10", "docstatus": 0, - "modified": "2013-12-18 10:38:39", + "modified": "2014-01-03 18:28:20", "modified_by": "Administrator", "owner": "Administrator" }, @@ -334,6 +334,16 @@ "report_hide": 0, "reqd": 0 }, + { + "default": ":Company", + "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "doctype": "DocField", + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center", + "print_hide": 1 + }, { "doctype": "DocField", "fieldname": "project_name", From a83337a2dd0102f26fd17e2d2d7da51cf059b843 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Fri, 3 Jan 2014 19:10:11 +0600 Subject: [PATCH 34/87] bumped to version 3.4.6 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 89c1332005..536e5af1ba 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.5", + "app_version": "3.4.6", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { From 42db5d76a9d709749f4a0ff161cbbeff4dac48f9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 6 Jan 2014 11:20:37 +0530 Subject: [PATCH 35/87] Fixes in overbilling validation --- controllers/accounts_controller.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 1a399219e4..778348d3cc 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -388,8 +388,9 @@ class AccountsController(TransactionBase): for item in self.doclist.get({"parentfield": "entries"}): if item.fields.get(item_ref_dn): already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s` - where %s=%s and docstatus=1""" % (based_on, self.tname, item_ref_dn, '%s'), - item.fields[item_ref_dn])[0][0] + where %s=%s and docstatus=1 and parent != %s""" % + (based_on, self.tname, item_ref_dn, '%s', '%s'), + (item.fields[item_ref_dn], self.doc.name), debug=1)[0][0] total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]), self.precision(based_on, item)) From b882fa14f4de7b7cc1ac8d5e946093b3ce78aa5d Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Mon, 6 Jan 2014 12:48:58 +0600 Subject: [PATCH 36/87] bumped to version 3.4.7 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 536e5af1ba..26fc50dbb8 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.6", + "app_version": "3.4.7", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { From 7e79f300a144a704a8f21f418aef641dbd7fcd68 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 6 Jan 2014 12:23:29 +0530 Subject: [PATCH 37/87] accounts payable fixed --- .../accounts_payable/accounts_payable.py | 61 ++++++++++++------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/accounts/report/accounts_payable/accounts_payable.py b/accounts/report/accounts_payable/accounts_payable.py index f9266dc9ea..1bd8a9f323 100644 --- a/accounts/report/accounts_payable/accounts_payable.py +++ b/accounts/report/accounts_payable/accounts_payable.py @@ -9,18 +9,20 @@ from accounts.report.accounts_receivable.accounts_receivable import get_ageing_d def execute(filters=None): if not filters: filters = {} - columns = get_columns() + supplier_naming_by = webnotes.conn.get_value("Buying Settings", None, "supp_master_name") + columns = get_columns(supplier_naming_by) entries = get_gl_entries(filters) - account_supplier = dict(webnotes.conn.sql("""select account.name, supplier.supplier_name - from `tabAccount` account, `tabSupplier` supplier - where account.master_type="Supplier" and supplier.name=account.master_name""")) - + account_map = dict(((r.name, r) for r in webnotes.conn.sql("""select acc.name, + supp.supplier_name, supp.name as supplier + from `tabAccount` acc, `tabSupplier` supp + where acc.master_type="Supplier" and supp.name=acc.master_name""", as_dict=1))) + entries_after_report_date = [[gle.voucher_type, gle.voucher_no] for gle in get_gl_entries(filters, before_report_date=False)] - + account_supplier_type_map = get_account_supplier_type_map() voucher_detail_map = get_voucher_details() - + # Age of the invoice on this date age_on = getdate(filters.get("report_date")) > getdate(nowdate()) \ and nowdate() or filters.get("report_date") @@ -37,9 +39,7 @@ def execute(filters=None): if abs(flt(outstanding_amount)) > 0.01: paid_amount = invoiced_amount - outstanding_amount - row = [gle.posting_date, gle.account, account_supplier.get(gle.account, ""), - gle.voucher_type, gle.voucher_no, gle.remarks, - account_supplier_type_map.get(gle.account), + row = [gle.posting_date, gle.account, gle.voucher_type, gle.voucher_no, voucher_details.get("due_date", ""), voucher_details.get("bill_no", ""), voucher_details.get("bill_date", ""), invoiced_amount, paid_amount, outstanding_amount] @@ -50,21 +50,38 @@ def execute(filters=None): else: ageing_based_on_date = gle.posting_date - row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount) + row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount) + \ + [account_map.get(gle.account).get("supplier") or ""] + + if supplier_naming_by == "Naming Series": + row += [account_map.get(gle.account).get("supplier_name") or ""] + + row += [account_supplier_type_map.get(gle.account), gle.remarks] data.append(row) - + + for i in range(0, len(data)): + data[i].insert(4, """""" \ + % ("/".join(["#Form", data[i][2], data[i][3]]),)) + return columns, data -def get_columns(): - return [ - "Posting Date:Date:80", "Account:Link/Account:150", "Supplier::150", "Voucher Type::110", - "Voucher No::120", "Remarks::150", "Supplier Type:Link/Supplier Type:120", - "Due Date:Date:80", "Bill No::80", "Bill Date:Date:80", +def get_columns(supplier_naming_by): + columns = [ + "Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110", + "Voucher No::120", "::30", "Due Date:Date:80", "Bill No::80", "Bill Date:Date:80", "Invoiced Amount:Currency:100", "Paid Amount:Currency:100", "Outstanding Amount:Currency:100", "Age:Int:50", "0-30:Currency:100", - "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100" + "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100", + "Supplier:Link/Supplier:150" ] - + + if supplier_naming_by == "Naming Series": + columns += ["Supplier Name::110"] + + columns += ["Supplier Type:Link/Supplier Type:120", "Remarks::150"] + + return columns + def get_gl_entries(filters, before_report_date=True): conditions, supplier_accounts = get_conditions(filters, before_report_date) gl_entries = [] @@ -102,10 +119,10 @@ def get_conditions(filters, before_report_date=True): def get_account_supplier_type_map(): account_supplier_type_map = {} - for each in webnotes.conn.sql("""select t2.name, t1.supplier_type from `tabSupplier` t1, - `tabAccount` t2 where t1.name = t2.master_name group by t2.name"""): + for each in webnotes.conn.sql("""select acc.name, supp.supplier_type from `tabSupplier` supp, + `tabAccount` acc where supp.name = acc.master_name group by acc.name"""): account_supplier_type_map[each[0]] = each[1] - + return account_supplier_type_map def get_voucher_details(): From 6b66c387ad3b5d5d83144c0dd41cc951f12f5fb9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 6 Jan 2014 16:28:17 +0530 Subject: [PATCH 38/87] Fixes in item-wise sales/purchase register --- .../item_wise_purchase_register.py | 3 ++- .../item_wise_sales_register/item_wise_sales_register.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index 7d81308a80..7d8a358aa1 100644 --- a/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -12,7 +12,8 @@ def execute(filters=None): item_list = get_items(filters) aii_account_map = get_aii_accounts() - item_tax, tax_accounts = get_tax_accounts(item_list, columns) + if item_list: + item_tax, tax_accounts = get_tax_accounts(item_list, columns) data = [] for d in item_list: diff --git a/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/accounts/report/item_wise_sales_register/item_wise_sales_register.py index dc5ecda3da..9f1fd87f70 100644 --- a/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -11,7 +11,8 @@ def execute(filters=None): last_col = len(columns) item_list = get_items(filters) - item_tax, tax_accounts = get_tax_accounts(item_list, columns) + if item_list: + item_tax, tax_accounts = get_tax_accounts(item_list, columns) data = [] for d in item_list: @@ -39,7 +40,6 @@ def get_columns(): "Qty:Float:120", "Rate:Currency:120", "Amount:Currency:120" ] - def get_conditions(filters): conditions = "" From 01441ef37f7dbf6ca25f2197b6a08a1db5a26658 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 7 Jan 2014 11:59:36 +0530 Subject: [PATCH 39/87] Removed unwanted debug --- controllers/accounts_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 778348d3cc..be74fef02a 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -390,7 +390,7 @@ class AccountsController(TransactionBase): already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s` where %s=%s and docstatus=1 and parent != %s""" % (based_on, self.tname, item_ref_dn, '%s', '%s'), - (item.fields[item_ref_dn], self.doc.name), debug=1)[0][0] + (item.fields[item_ref_dn], self.doc.name))[0][0] total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]), self.precision(based_on, item)) From a11e14424c7e608b15c078be3547785c938b8202 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 7 Jan 2014 12:02:45 +0530 Subject: [PATCH 40/87] fix branching, pip version and mysql-python version pinning in install_erpnext --- install_erpnext.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/install_erpnext.py b/install_erpnext.py index c95a03d3e5..01de4575b9 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -19,7 +19,7 @@ requirements = [ "jinja2", "markdown2", "markupsafe", - "mysql-python", + "mysql-python==1.2.4", "pygeoip", "python-dateutil", "python-memcached", @@ -148,13 +148,13 @@ def install_python_modules(): print "Installing Python Modules: (This may take some time)" print "-"*80 - if not exec_in_shell("which pip"): - exec_in_shell("easy_install pip") + if not exec_in_shell("which pip-2.7"): + exec_in_shell("easy_install-2.7 pip") - exec_in_shell("pip install --upgrade pip") - exec_in_shell("pip install --upgrade setuptools") - exec_in_shell("pip install --upgrade virtualenv") - exec_in_shell("pip install {}".format(' '.join(requirements))) + exec_in_shell("pip-2.7 install --upgrade pip") + exec_in_shell("pip-2.7 install --upgrade setuptools") + exec_in_shell("pip-2.7 install --upgrade virtualenv") + exec_in_shell("pip-2.7 install {}".format(' '.join(requirements))) def install_erpnext(install_path): print @@ -200,7 +200,7 @@ def setup_folders(install_path): app = os.path.join(install_path, "app") if not os.path.exists(app): print "Cloning erpnext" - exec_in_shell("cd %s && git clone https://github.com/webnotes/erpnext.git app" % install_path) + exec_in_shell("cd %s && git clone --branch master https://github.com/webnotes/erpnext.git app" % install_path) exec_in_shell("cd app && git config core.filemode false") if not os.path.exists(app): raise Exception, "Couldn't clone erpnext repository" @@ -208,7 +208,7 @@ def setup_folders(install_path): lib = os.path.join(install_path, "lib") if not os.path.exists(lib): print "Cloning wnframework" - exec_in_shell("cd %s && git clone https://github.com/webnotes/wnframework.git lib" % install_path) + exec_in_shell("cd %s && git clone --branch master https://github.com/webnotes/wnframework.git lib" % install_path) exec_in_shell("cd lib && git config core.filemode false") if not os.path.exists(lib): raise Exception, "Couldn't clone wnframework repository" From da282d405f857ddad3dc29993a7627b665906626 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 7 Jan 2014 12:41:09 +0530 Subject: [PATCH 41/87] Fixes in overbilling validation against DN/PR --- controllers/accounts_controller.py | 51 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index be74fef02a..839dce0b4b 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -387,35 +387,38 @@ class AccountsController(TransactionBase): for item in self.doclist.get({"parentfield": "entries"}): if item.fields.get(item_ref_dn): - already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s` - where %s=%s and docstatus=1 and parent != %s""" % - (based_on, self.tname, item_ref_dn, '%s', '%s'), - (item.fields[item_ref_dn], self.doc.name))[0][0] - - total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]), - self.precision(based_on, item)) - ref_amt = flt(webnotes.conn.get_value(ref_dt + " Item", item.fields[item_ref_dn], based_on), self.precision(based_on, item)) + if not ref_amt: + webnotes.msgprint(_("As amount for item") + ": " + item.item_code + _(" in ") + + ref_dt + _(" is zero, system will not check for over-billed")) + else: + already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s` + where %s=%s and docstatus=1 and parent != %s""" % + (based_on, self.tname, item_ref_dn, '%s', '%s'), + (item.fields[item_ref_dn], self.doc.name))[0][0] - tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code, - item_tolerance, global_tolerance) - - max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) + total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]), + self.precision(based_on, item)) - if total_billed_amt - max_allowed_amt > 0.01: - reduce_by = total_billed_amt - max_allowed_amt + tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code, + item_tolerance, global_tolerance) - webnotes.throw(_("Row #") + cstr(item.idx) + ": " + - _(" Max amount allowed for Item ") + cstr(item.item_code) + - _(" against ") + ref_dt + " " + - cstr(item.fields[ref_dt.lower().replace(" ", "_")]) + _(" is ") + - cstr(max_allowed_amt) + ". \n" + - _("""If you want to increase your overflow tolerance, please increase \ - tolerance % in Global Defaults or Item master. - Or, you must reduce the amount by """) + cstr(reduce_by) + "\n" + - _("""Also, please check if the order item has already been billed \ - in the Sales Order""")) + max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) + + if total_billed_amt - max_allowed_amt > 0.01: + reduce_by = total_billed_amt - max_allowed_amt + + webnotes.throw(_("Row #") + cstr(item.idx) + ": " + + _(" Max amount allowed for Item ") + cstr(item.item_code) + + _(" against ") + ref_dt + " " + + cstr(item.fields[ref_dt.lower().replace(" ", "_")]) + _(" is ") + + cstr(max_allowed_amt) + ". \n" + + _("""If you want to increase your overflow tolerance, please increase \ + tolerance % in Global Defaults or Item master. + Or, you must reduce the amount by """) + cstr(reduce_by) + "\n" + + _("""Also, please check if the order item has already been billed \ + in the Sales Order""")) def get_company_default(self, fieldname): from accounts.utils import get_company_default From 777bff6e8df41ff6575141c54fc6d96ec5469a0e Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 7 Jan 2014 14:17:44 +0600 Subject: [PATCH 42/87] bumped to version 3.4.8 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 26fc50dbb8..078ca16188 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.7", + "app_version": "3.4.8", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.4.3" + "requires_framework_version": "==3.4.4" } \ No newline at end of file From 10fd91c78e0c27941164306d43fbc5d87470fa1c Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 7 Jan 2014 16:18:41 +0530 Subject: [PATCH 43/87] Close tickets automatically through scheduler --- startup/schedule_handlers.py | 4 ++++ support/doctype/support_ticket/get_support_mails.py | 5 ----- support/doctype/support_ticket/support_ticket.py | 7 ++++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/startup/schedule_handlers.py b/startup/schedule_handlers.py index 252a091547..0cf06026d6 100644 --- a/startup/schedule_handlers.py +++ b/startup/schedule_handlers.py @@ -53,6 +53,10 @@ def execute_daily(): # email digest from setup.doctype.email_digest.email_digest import send run_fn(send) + + # auto close support tickets + from support.doctype.support_ticket.support_ticket import auto_close_tickets + run_fn(auto_close_tickets) def execute_weekly(): from setup.doctype.backup_manager.backup_manager import take_backups_weekly diff --git a/support/doctype/support_ticket/get_support_mails.py b/support/doctype/support_ticket/get_support_mails.py index 33cb023747..67ed9f6ae8 100644 --- a/support/doctype/support_ticket/get_support_mails.py +++ b/support/doctype/support_ticket/get_support_mails.py @@ -52,11 +52,6 @@ Original Query: subject = '['+cstr(d.name)+'] ' + cstr(d.subject), \ msg = cstr(response)) - def auto_close_tickets(self): - webnotes.conn.sql("""update `tabSupport Ticket` set status = 'Closed' - where status = 'Replied' - and date_sub(curdate(),interval 15 Day) > modified""") - def get_support_mails(): if cint(webnotes.conn.get_value('Email Settings', None, 'sync_support_mails')): SupportMailbox() diff --git a/support/doctype/support_ticket/support_ticket.py b/support/doctype/support_ticket/support_ticket.py index fd79583129..3030a146fe 100644 --- a/support/doctype/support_ticket/support_ticket.py +++ b/support/doctype/support_ticket/support_ticket.py @@ -66,4 +66,9 @@ class DocType(TransactionBase): def set_status(name, status): st = webnotes.bean("Support Ticket", name) st.doc.status = status - st.save() \ No newline at end of file + st.save() + +def auto_close_tickets(): + webnotes.conn.sql("""update `tabSupport Ticket` set status = 'Closed' + where status = 'Replied' + and date_sub(curdate(),interval 15 Day) > modified""") \ No newline at end of file From 69951e5d1ca6e42f3ec735c60f525add22680f43 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 7 Jan 2014 18:24:40 +0530 Subject: [PATCH 44/87] fix installer python packages issue --- install_erpnext.py | 60 ++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/install_erpnext.py b/install_erpnext.py index 01de4575b9..e285d4bbfe 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import os, sys import argparse +import subprocess is_redhat = is_debian = None root_password = None @@ -80,7 +81,7 @@ def validate_install(): return is_redhat, is_debian def install_using_yum(): - packages = "python python-setuptools gcc python-devel MySQL-python git memcached ntp vim-enhanced screen" + packages = "gcc MySQL-python git memcached ntp vim-enhanced screen" print "-"*80 print "Installing Packages: (This may take some time)" @@ -88,7 +89,10 @@ def install_using_yum(): print "-"*80 exec_in_shell("yum install -y %s" % packages) - if not exec_in_shell("which mysql"): + + try: + exec_in_shell("which mysql") + except subprocess.CalledProcessError: packages = "mysql mysql-server mysql-devel" print "Installing Packages:", packages exec_in_shell("yum install -y %s" % packages) @@ -101,26 +105,19 @@ def install_using_yum(): exec_in_shell('mysqladmin -u root password "%s"' % (root_password,)) print "Root password set as", root_password - # install htop - if not exec_in_shell("which htop"): - try: - exec_in_shell("cd /tmp && rpm -i --force http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm && yum install -y htop") - except: - pass - update_config_for_redhat() def update_config_for_redhat(): import re # set to autostart on startup - for service in ("mysqld", "memcached", "ntpd"): + for service in ("mysqld", "memcached"): exec_in_shell("chkconfig --level 2345 %s on" % service) exec_in_shell("service %s restart" % service) def install_using_apt(): exec_in_shell("apt-get update") - packages = "python python-setuptools python-dev build-essential python-pip python-mysqldb git memcached ntp vim screen htop" + packages = "python python-setuptools python-dev build-essential python-mysqldb git memcached ntp vim screen htop" print "-"*80 print "Installing Packages: (This may take some time)" print packages @@ -132,7 +129,9 @@ def install_using_apt(): exec_in_shell("echo mysql-server mysql-server/root_password password %s | sudo debconf-set-selections" % root_password) exec_in_shell("echo mysql-server mysql-server/root_password_again password %s | sudo debconf-set-selections" % root_password) - if not exec_in_shell("which mysql"): + try: + exec_in_shell("which mysql") + except subprocess.CalledProcessError: packages = "mysql-server libmysqlclient-dev" print "Installing Packages:", packages exec_in_shell("apt-get install -y %s" % packages) @@ -140,7 +139,7 @@ def install_using_apt(): update_config_for_debian() def update_config_for_debian(): - for service in ("mysql", "ntpd"): + for service in ("mysql",): exec_in_shell("service %s restart" % service) def install_python_modules(): @@ -148,13 +147,14 @@ def install_python_modules(): print "Installing Python Modules: (This may take some time)" print "-"*80 - if not exec_in_shell("which pip-2.7"): + try: + exec_in_shell("which pip2.7") + except subprocess.CalledProcessError: exec_in_shell("easy_install-2.7 pip") - exec_in_shell("pip-2.7 install --upgrade pip") - exec_in_shell("pip-2.7 install --upgrade setuptools") - exec_in_shell("pip-2.7 install --upgrade virtualenv") - exec_in_shell("pip-2.7 install {}".format(' '.join(requirements))) + exec_in_shell("pip2.7 install --upgrade setuptools --no-use-wheel") + exec_in_shell("pip2.7 install --upgrade setuptools") + exec_in_shell("pip2.7 install {}".format(' '.join(requirements))) def install_erpnext(install_path): print @@ -243,28 +243,8 @@ def post_install(install_path): def exec_in_shell(cmd): # using Popen instead of os.system - as recommended by python docs - from subprocess import Popen - import tempfile - - with tempfile.TemporaryFile() as stdout: - with tempfile.TemporaryFile() as stderr: - p = Popen(cmd, shell=True, stdout=stdout, stderr=stderr) - p.wait() - - stdout.seek(0) - out = stdout.read() - if out: out = out.decode('utf-8') - - stderr.seek(0) - err = stderr.read() - if err: err = err.decode('utf-8') - - if err and any((kw in err.lower() for kw in ["traceback", "error", "exception"])): - print out - raise Exception, err - else: - print "." - + import subprocess + out = subprocess.check_output(cmd, shell=True) return out def parse_args(): From 806017c92ab7b0bc2d0f5671dc55d16c88f0766d Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 7 Jan 2014 18:37:38 +0530 Subject: [PATCH 45/87] Price List and Item Price : Validfor Buying and Selling as separate check box --- accounts/doctype/pos_setting/pos_setting.js | 2 +- .../purchase_common/purchase_common.js | 2 +- buying/doctype/supplier/supplier.js | 2 +- buying/utils.py | 12 +-- controllers/accounts_controller.py | 18 ++-- .../p03_buying_selling_for_price_list.py | 21 +--- ...ice_list_and_item_details_in_item_price.py | 4 +- patches/patch_list.py | 1 + public/js/transaction.js | 9 +- selling/doctype/customer/customer.js | 2 +- selling/sales_common.js | 2 +- selling/utils/__init__.py | 14 ++- setup/page/setup_wizard/setup_wizard.py | 3 +- stock/doctype/item_price/item_price.js | 5 +- stock/doctype/item_price/item_price.py | 11 ++- stock/doctype/item_price/item_price.txt | 40 +++++--- stock/doctype/price_list/price_list.css | 7 -- stock/doctype/price_list/price_list.py | 15 ++- stock/doctype/price_list/price_list.txt | 19 ++-- stock/doctype/price_list/test_price_list.py | 8 +- stock/report/item_prices/item_prices.py | 4 +- utilities/demo/demo_docs/Item_Price.csv | 98 +++++++++---------- 22 files changed, 147 insertions(+), 152 deletions(-) delete mode 100644 stock/doctype/price_list/price_list.css diff --git a/accounts/doctype/pos_setting/pos_setting.js b/accounts/doctype/pos_setting/pos_setting.js index 8c5f254a52..dc13bb50ca 100755 --- a/accounts/doctype/pos_setting/pos_setting.js +++ b/accounts/doctype/pos_setting/pos_setting.js @@ -7,7 +7,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn){ }); cur_frm.set_query("selling_price_list", function() { - return { filters: { buying_or_selling: "Selling" } }; + return { filters: { selling: 1 } }; }); } diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 9661f6edaf..14b8279245 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -22,7 +22,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ if(this.frm.fields_dict.buying_price_list) { this.frm.set_query("buying_price_list", function() { return{ - filters: { 'buying_or_selling': "Buying" } + filters: { 'buying': 1 } } }); } diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js index 061861643d..ec4d3e606f 100644 --- a/buying/doctype/supplier/supplier.js +++ b/buying/doctype/supplier/supplier.js @@ -95,6 +95,6 @@ cur_frm.cscript.make_contact = function() { cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) { return{ - filters:{'buying_or_selling': "Buying"} + filters:{'buying': 1} } } \ No newline at end of file diff --git a/buying/utils.py b/buying/utils.py index 0d9c8fa838..35d89c559d 100644 --- a/buying/utils.py +++ b/buying/utils.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _ +from webnotes import msgprint, _, throw from webnotes.utils import getdate, flt, add_days, cstr import json @@ -90,7 +90,7 @@ def _get_price_list_rate(args, item_bean, meta): # try fetching from price list if args.buying_price_list and args.price_list_currency: price_list_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price` - where price_list=%s and item_code=%s and buying_or_selling='Buying'""", + where price_list=%s and item_code=%s and buying=1""", (args.buying_price_list, args.item_code), as_dict=1) if price_list_rate: @@ -122,14 +122,12 @@ def _validate_item_details(args, item): # validate if purchase item or subcontracted item if item.is_purchase_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + _("not a purchase item"), - raise_exception=True) + throw(_("Item") + (" %s: " % item.name) + _("not a purchase item")) if args.is_subcontracted == "Yes" and item.is_sub_contracted_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + + throw(_("Item") + (" %s: " % item.name) + _("not a sub-contracted item.") + - _("Please select a sub-contracted item or do not sub-contract the transaction."), - raise_exception=True) + _("Please select a sub-contracted item or do not sub-contract the transaction.")) def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): """returns last purchase details in stock uom""" diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 1a399219e4..6660a93e4e 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import _, msgprint +from webnotes import _, msgprint, throw from webnotes.utils import flt, cint, today, cstr from webnotes.model.code import get_obj from setup.utils import get_company_currency @@ -50,8 +50,8 @@ class AccountsController(TransactionBase): if accounts: if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts): - msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") + - self.doc.doctype + _(" can not be made."), raise_exception=1) + throw(_("Account for this ") + fieldname + _(" has been freezed. ") + + self.doc.doctype + _(" can not be made.")) def set_price_list_currency(self, buying_or_selling): if self.meta.get_field("currency"): @@ -179,17 +179,17 @@ class AccountsController(TransactionBase): """ if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \ (not tax.row_id or cint(tax.row_id) >= tax.idx): - msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ + throw((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ _("Please specify a valid") + " %(row_id_label)s") % { "idx": tax.idx, "taxes_doctype": tax.doctype, "row_id_label": self.meta.get_label("row_id", parentfield=self.other_fname) - }, raise_exception=True) + }) def validate_inclusive_tax(self, tax): def _on_previous_row_error(row_range): - msgprint((_("Row") + " # %(idx)s [%(doctype)s]: " + + throw((_("Row") + " # %(idx)s [%(doctype)s]: " + _("to be included in Item's rate, it is required that: ") + " [" + _("Row") + " # %(row_range)s] " + _("also be included in Item's rate")) % { "idx": tax.idx, @@ -200,12 +200,12 @@ class AccountsController(TransactionBase): parentfield=self.other_fname), "charge_type": tax.charge_type, "row_range": row_range - }, raise_exception=True) + }) if cint(tax.included_in_print_rate): if tax.charge_type == "Actual": # inclusive tax cannot be of type Actual - msgprint((_("Row") + throw((_("Row") + " # %(idx)s [%(doctype)s]: %(charge_type_label)s = \"%(charge_type)s\" " + "cannot be included in Item's rate") % { "idx": tax.idx, @@ -213,7 +213,7 @@ class AccountsController(TransactionBase): "charge_type_label": self.meta.get_label("charge_type", parentfield=self.other_fname), "charge_type": tax.charge_type, - }, raise_exception=True) + }) elif tax.charge_type == "On Previous Row Amount" and \ not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate): # referred row should also be inclusive diff --git a/patches/june_2013/p03_buying_selling_for_price_list.py b/patches/june_2013/p03_buying_selling_for_price_list.py index 2f92fe6a9e..15da085e53 100644 --- a/patches/june_2013/p03_buying_selling_for_price_list.py +++ b/patches/june_2013/p03_buying_selling_for_price_list.py @@ -8,20 +8,7 @@ from webnotes.utils import cint def execute(): webnotes.reload_doc("stock", "doctype", "price_list") webnotes.reload_doc("stock", "doctype", "item_price") - - try: - for price_list in webnotes.conn.sql_list("""select name from `tabPrice List`"""): - buying, selling = False, False - for b, s in webnotes.conn.sql("""select distinct buying, selling - from `tabItem Price` where price_list_name=%s""", price_list): - buying = buying or cint(b) - selling = selling or cint(s) - - buying_or_selling = "Selling" if selling else "Buying" - webnotes.conn.set_value("Price List", price_list, "buying_or_selling", buying_or_selling) - except webnotes.SQLError, e: - if e.args[0] == 1054: - webnotes.conn.sql("""update `tabPrice List` set buying_or_selling='Selling' - where ifnull(buying_or_selling, '')='' """) - else: - raise \ No newline at end of file + + webnotes.conn.sql("""update `tabPrice List` pl, `tabItem Price` ip + set pl.selling=ip.selling, pl.buying=ip.buying + where pl.name=ip.price_list_name""") \ No newline at end of file diff --git a/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py b/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py index 3b4ca833f1..b92f7d052a 100644 --- a/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py +++ b/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py @@ -12,9 +12,7 @@ def execute(): where ip.item_code=i.name""") webnotes.conn.sql("""update `tabItem Price` ip, `tabPrice List` pl - set ip.price_list=pl.name, ip.currency=pl.currency, - ip.buying_or_selling=pl.buying_or_selling - where ip.parent=pl.name""") + set ip.price_list=pl.name, ip.currency=pl.currency where ip.parent=pl.name""") webnotes.conn.sql("""update `tabItem Price` set parent=null, parenttype=null, parentfield=null, idx=null""") \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 608ba77168..d291d762c5 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -263,4 +263,5 @@ patch_list = [ "patches.1311.p08_email_digest_recipients", "execute:webnotes.delete_doc('DocType', 'Warehouse Type')", "patches.1312.p02_update_item_details_in_item_price", + "patches.1401.p01_make_buying_selling_as_check_box_in_price_list", ] \ No newline at end of file diff --git a/public/js/transaction.js b/public/js/transaction.js index 4c4a810ed2..0fe0535c6b 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -330,8 +330,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ doctype: tax.doctype, row_id_label: wn.meta.get_label(tax.doctype, "row_id", tax.name) }); - msgprint(msg); - throw msg; + wn.throw(msg); } }, @@ -347,8 +346,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ charge_type_label: wn.meta.get_label(tax.doctype, "charge_type", tax.name), charge_type: tax.charge_type }); - msgprint(msg); - throw msg; + wn.throw(msg); }; var on_previous_row_error = function(row_range) { @@ -363,8 +361,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ row_range: row_range, }); - msgprint(msg); - throw msg; + wn.throw(msg); }; if(cint(tax.included_in_print_rate)) { diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index 5e0ccc98f2..5d046904d3 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -122,6 +122,6 @@ cur_frm.fields_dict.lead_name.get_query = function(doc,cdt,cdn) { cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) { return{ - filters:{'buying_or_selling': "Selling"} + filters:{'selling': 1} } } diff --git a/selling/sales_common.js b/selling/sales_common.js index dddc2b568d..f4f643015e 100644 --- a/selling/sales_common.js +++ b/selling/sales_common.js @@ -48,7 +48,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ if(this.frm.fields_dict.selling_price_list) { this.frm.set_query("selling_price_list", function() { - return { filters: { buying_or_selling: "Selling" } }; + return { filters: { selling: 1 } }; }); } diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py index 5974da7d8b..85c20e86d8 100644 --- a/selling/utils/__init__.py +++ b/selling/utils/__init__.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _ +from webnotes import msgprint, _, throw from webnotes.utils import flt, cint, comma_and import json @@ -100,7 +100,7 @@ def _get_item_code(barcode=None, serial_no=None): where name=%s""", serial_no) if not item_code: - msgprint(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no), raise_exception=True) + throw(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no)) return item_code[0] @@ -111,14 +111,12 @@ def _validate_item_details(args, item): # validate if sales item or service item if args.order_type == "Maintenance": if item.is_service_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + + throw(_("Item") + (" %s: " % item.name) + _("not a service item.") + - _("Please select a service item or change the order type to Sales."), - raise_exception=True) + _("Please select a service item or change the order type to Sales.")) elif item.is_sales_item != "Yes": - msgprint(_("Item") + (" %s: " % item.name) + _("not a sales item"), - raise_exception=True) + throw(_("Item") + (" %s: " % item.name) + _("not a sales item")) def _get_basic_details(args, item_bean, warehouse_fieldname): item = item_bean.doc @@ -147,7 +145,7 @@ def _get_basic_details(args, item_bean, warehouse_fieldname): def _get_price_list_rate(args, item_bean, meta): ref_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price` - where price_list=%s and item_code=%s and buying_or_selling='Selling'""", + where price_list=%s and item_code=%s and selling=1""", (args.selling_price_list, args.item_code), as_dict=1) if not ref_rate: diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index c1d3571ea5..ededd472a8 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -98,7 +98,8 @@ def create_price_lists(args): { "doctype": "Price List", "price_list_name": "Standard " + pl_type, - "buying_or_selling": pl_type, + "buying": 1 if pl_type == "Buying" else 0, + "selling": 1 if pl_type == "Selling" else 0, "currency": args["currency"] }, { diff --git a/stock/doctype/item_price/item_price.js b/stock/doctype/item_price/item_price.js index bece26c6b5..9f38fdb18e 100644 --- a/stock/doctype/item_price/item_price.js +++ b/stock/doctype/item_price/item_price.js @@ -2,11 +2,10 @@ // License: GNU General Public License v3. See license.txt $.extend(cur_frm.cscript, { - onload: function () { - // Fetch price list details - cur_frm.add_fetch("price_list", "buying_or_selling", "buying_or_selling"); + cur_frm.add_fetch("price_list", "buying", "buying"); + cur_frm.add_fetch("price_list", "selling", "selling"); cur_frm.add_fetch("price_list", "currency", "currency"); // Fetch item details diff --git a/stock/doctype/item_price/item_price.py b/stock/doctype/item_price/item_price.py index 072d70096e..9a8e3d35fb 100644 --- a/stock/doctype/item_price/item_price.py +++ b/stock/doctype/item_price/item_price.py @@ -1,7 +1,5 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -# For license information, please see license.txt +# License: GNU General Public License v3. See license.txt from __future__ import unicode_literals import webnotes @@ -19,8 +17,11 @@ class DocType: self.update_item_details() def update_price_list_details(self): - self.doc.buying_or_selling, self.doc.currency = webnotes.conn.get_value("Price List", - self.doc.price_list, ["buying_or_selling", "currency"]) + if not self.doc.selling and not self.doc.buying: + self.doc.buying, self.doc.selling = webnotes.conn.get_value("Price List", + self.doc.price_list, ["buying", "selling"]) + + self.doc.currency = webnotes.conn.get_value("Price List", self.doc.price_list, "currency") def update_item_details(self): self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item", diff --git a/stock/doctype/item_price/item_price.txt b/stock/doctype/item_price/item_price.txt index fc411eb1d6..b25fd30812 100644 --- a/stock/doctype/item_price/item_price.txt +++ b/stock/doctype/item_price/item_price.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-02 16:29:48", "docstatus": 0, - "modified": "2013-10-31 12:59:02", + "modified": "2014-01-07 18:11:10", "modified_by": "Administrator", "owner": "Administrator" }, @@ -43,6 +43,13 @@ "doctype": "DocType", "name": "Item Price" }, + { + "doctype": "DocField", + "fieldname": "price_list_details", + "fieldtype": "Section Break", + "label": "Price List", + "options": "icon-tags" + }, { "doctype": "DocField", "fieldname": "price_list", @@ -52,6 +59,27 @@ "options": "Price List", "reqd": 1 }, + { + "doctype": "DocField", + "fieldname": "buying", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Buying" + }, + { + "doctype": "DocField", + "fieldname": "selling", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Selling" + }, + { + "doctype": "DocField", + "fieldname": "item_details", + "fieldtype": "Section Break", + "label": "Item", + "options": "icon-tag" + }, { "doctype": "DocField", "fieldname": "item_code", @@ -83,16 +111,6 @@ "fieldname": "col_br_1", "fieldtype": "Column Break" }, - { - "doctype": "DocField", - "fieldname": "buying_or_selling", - "fieldtype": "Select", - "in_filter": 1, - "in_list_view": 1, - "label": "Valid for Buying or Selling?", - "options": "Selling\nBuying", - "reqd": 0 - }, { "doctype": "DocField", "fieldname": "item_name", diff --git a/stock/doctype/price_list/price_list.css b/stock/doctype/price_list/price_list.css deleted file mode 100644 index 61b069442f..0000000000 --- a/stock/doctype/price_list/price_list.css +++ /dev/null @@ -1,7 +0,0 @@ -.table-grid tbody tr { - cursor: pointer; -} - -.table-grid thead tr { - height: 50px; -} \ No newline at end of file diff --git a/stock/doctype/price_list/price_list.py b/stock/doctype/price_list/price_list.py index d0e5d2b6d4..569e759159 100644 --- a/stock/doctype/price_list/price_list.py +++ b/stock/doctype/price_list/price_list.py @@ -3,16 +3,15 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _ +from webnotes import msgprint, _, throw from webnotes.utils import comma_or, cint from webnotes.model.controller import DocListController import webnotes.defaults class DocType(DocListController): def validate(self): - if self.doc.buying_or_selling not in ["Buying", "Selling"]: - msgprint(_(self.meta.get_label("buying_or_selling")) + " " + _("must be one of") + " " + - comma_or(["Buying", "Selling"]), raise_exception=True) + if not self.doc.buying and not self.doc.selling: + throw(_("Price List must be one of Buying or Selling")) if not self.doclist.get({"parentfield": "valid_for_territories"}): # if no territory, set default territory @@ -34,15 +33,15 @@ class DocType(DocListController): cart_settings.validate_price_lists() def set_default_if_missing(self): - if self.doc.buying_or_selling=="Selling": + if self.doc.selling: if not webnotes.conn.get_value("Selling Settings", None, "selling_price_list"): webnotes.set_value("Selling Settings", "Selling Settings", "selling_price_list", self.doc.name) - elif self.doc.buying_or_selling=="Buying": + elif self.doc.buying: if not webnotes.conn.get_value("Buying Settings", None, "buying_price_list"): webnotes.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.doc.name) def update_item_price(self): webnotes.conn.sql("""update `tabItem Price` set currency=%s, - buying_or_selling=%s, modified=NOW() where price_list=%s""", - (self.doc.currency, self.doc.buying_or_selling, self.doc.name)) \ No newline at end of file + buying=%s, selling=%s, modified=NOW() where price_list=%s""", + (self.doc.currency, self.doc.buying, self.doc.selling, self.doc.name)) \ No newline at end of file diff --git a/stock/doctype/price_list/price_list.txt b/stock/doctype/price_list/price_list.txt index d43076bcc8..69c3ecbc4c 100644 --- a/stock/doctype/price_list/price_list.txt +++ b/stock/doctype/price_list/price_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-25 11:35:09", "docstatus": 0, - "modified": "2013-10-31 19:24:33", + "modified": "2014-01-06 18:28:23", "modified_by": "Administrator", "owner": "Administrator" }, @@ -61,14 +61,19 @@ "reqd": 1 }, { - "default": "Selling", "doctype": "DocField", - "fieldname": "buying_or_selling", - "fieldtype": "Select", + "fieldname": "buying", + "fieldtype": "Check", "in_list_view": 1, - "label": "Valid for Buying or Selling?", - "options": "Buying\nSelling", - "reqd": 1 + "label": "Buying" + }, + { + "doctype": "DocField", + "fieldname": "selling", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Selling", + "reqd": 0 }, { "doctype": "DocField", diff --git a/stock/doctype/price_list/test_price_list.py b/stock/doctype/price_list/test_price_list.py index 86dcd1a594..bdcacc3452 100644 --- a/stock/doctype/price_list/test_price_list.py +++ b/stock/doctype/price_list/test_price_list.py @@ -12,7 +12,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List", "currency": "INR", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", @@ -25,7 +25,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List 2", "currency": "INR", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", @@ -38,7 +38,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List India", "currency": "INR", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", @@ -51,7 +51,7 @@ test_records = [ "doctype": "Price List", "price_list_name": "_Test Price List Rest of the World", "currency": "USD", - "buying_or_selling": "Selling" + "selling": 1 }, { "doctype": "Applicable Territory", diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index da8b5007d5..e744cc73e4 100644 --- a/stock/report/item_prices/item_prices.py +++ b/stock/report/item_prices/item_prices.py @@ -65,13 +65,13 @@ def get_price_list(): rate = {} - price_list = webnotes.conn.sql("""select item_code, buying_or_selling, + price_list = webnotes.conn.sql("""select item_code, buying, selling, concat(price_list, " - ", currency, " ", ref_rate) as price from `tabItem Price`""", as_dict=1) for j in price_list: if j.price: - rate.setdefault(j.item_code, {}).setdefault(j.buying_or_selling, []).append(j.price) + rate.setdefault(j.item_code, {}).setdefault("Buying" if j.buying else "Selling", []).append(j.price) item_rate_map = {} for item in rate: diff --git a/utilities/demo/demo_docs/Item_Price.csv b/utilities/demo/demo_docs/Item_Price.csv index d70b7b3e67..cd7a13937f 100644 --- a/utilities/demo/demo_docs/Item_Price.csv +++ b/utilities/demo/demo_docs/Item_Price.csv @@ -1,49 +1,49 @@ -Data Import Template,,,,,,, -Table:,Item Price,,,,,, -,,,,,,, -,,,,,,, -Notes:,,,,,,, -Please do not change the template headings.,,,,,,, -First data column must be blank.,,,,,,, -"If you are uploading new records, leave the ""name"""" (ID) column blank.""",,,,,,, -"If you are uploading new records, ""Naming Series"""" becomes mandatory"," if present.""",,,,,, -Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,, -"For updating, you can update only selective columns.",,,,,,, -You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,, -,,,,,,, -DocType:,Item Price,,,,,, -Column Labels:,ID,Price List,Item Code,Rate,Valid for Buying or Selling?,Item Name,Item Description -Column Name:,name,price_list,item_code,ref_rate,buying_or_selling,item_name,item_description -Mandatory:,Yes,Yes,Yes,Yes,No,No,No -Type:,Data (text),Link,Link,Currency,Select,Data,Text -Info:,,Valid Price List,Valid Item,,"One of: Selling, Buying",, -Start entering data below this line,,,,,,, -,,Standard Buying,Base Bearing Plate,15,Buying,, -,,Standard Buying,Base Plate,20,Buying,, -,,Standard Buying,Bearing Block,10,Buying,, -,,Standard Buying,Bearing Collar,20,Buying,, -,,Standard Buying,Bearing Pipe,15,Buying,, -,,Standard Buying,Blade Rib,10,Buying,, -,,Standard Buying,Disc Collars,74,Buying,, -,,Standard Buying,External Disc,45,Buying,, -,,Standard Buying,Internal Disc,33,Buying,, -,,Standard Buying,Shaft,30,Buying,, -,,Standard Buying,Stand,40,Buying,, -,,Standard Buying,Upper Bearing Plate,50,Buying,, -,,Standard Buying,Wing Sheet,22,Buying,, -,,Standard Selling,Wind Turbine,21,Selling,, -,,Standard Selling,Wind Mill A Series,28,Selling,, -,,Standard Selling,Wind MIll C Series,14,Selling,, -,,Standard Selling,Base Bearing Plate,28,Selling,, -,,Standard Selling,Base Plate,21,Selling,, -,,Standard Selling,Bearing Block,14,Selling,, -,,Standard Selling,Bearing Collar,103.6,Selling,, -,,Standard Selling,Bearing Pipe,63,Selling,, -,,Standard Selling,Blade Rib,46.2,Selling,, -,,Standard Selling,Disc Collars,42,Selling,, -,,Standard Selling,External Disc,56,Selling,, -,,Standard Selling,Internal Disc,70,Selling,, -,,Standard Selling,Shaft,340,Selling,, -,,Standard Selling,Stand,400,Selling,, -,,Standard Selling,Upper Bearing Plate,300,Selling,, -,,Standard Selling,Wing Sheet,30.8,Selling,, \ No newline at end of file +Data Import Template,,,,,,,, +Table:,Item Price,,,,,,, +,,,,,,,, +,,,,,,,, +Notes:,,,,,,,, +Please do not change the template headings.,,,,,,,, +First data column must be blank.,,,,,,,, +"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,, +"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,, +Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,, +"For updating, you can update only selective columns.",,,,,,,, +You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,, +,,,,,,,, +DocType:,Item Price,,,,,,, +Column Labels:,ID,Price List,Item Code,Rate,Buying,Selling,Item Name,Item Description +Column Name:,name,price_list,item_code,ref_rate,buying,selling,item_name,item_description +Mandatory:,Yes,Yes,Yes,Yes,No,No,No,No +Type:,Data (text),Link,Link,Currency,Check,Check,Data,Text +Info:,,Valid Price List,Valid Item,,0 or 1,0 or 1,, +Start entering data below this line,,,,,,,, +,,Standard Buying,Base Bearing Plate,15,1,,, +,,Standard Buying,Base Plate,20,1,,, +,,Standard Buying,Bearing Block,10,1,,, +,,Standard Buying,Bearing Collar,20,1,,, +,,Standard Buying,Bearing Pipe,15,1,,, +,,Standard Buying,Blade Rib,10,1,,, +,,Standard Buying,Disc Collars,74,1,,, +,,Standard Buying,External Disc,45,1,,, +,,Standard Buying,Internal Disc,33,1,,, +,,Standard Buying,Shaft,30,1,,, +,,Standard Buying,Stand,40,1,,, +,,Standard Buying,Upper Bearing Plate,50,1,,, +,,Standard Buying,Wing Sheet,22,1,,, +,,Standard Selling,Wind Turbine,21,,1,, +,,Standard Selling,Wind Mill A Series,28,,1,, +,,Standard Selling,Wind MIll C Series,14,,1,, +,,Standard Selling,Base Bearing Plate,28,,1,, +,,Standard Selling,Base Plate,21,,1,, +,,Standard Selling,Bearing Block,14,,1,, +,,Standard Selling,Bearing Collar,103.6,,1,, +,,Standard Selling,Bearing Pipe,63,,1,, +,,Standard Selling,Blade Rib,46.2,,1,, +,,Standard Selling,Disc Collars,42,,1,, +,,Standard Selling,External Disc,56,,1,, +,,Standard Selling,Internal Disc,70,,1,, +,,Standard Selling,Shaft,340,,1,, +,,Standard Selling,Stand,400,,1,, +,,Standard Selling,Upper Bearing Plate,300,,1,, +,,Standard Selling,Wing Sheet,30.8,,1,, From 029f698c657bfef53456403e920f8ab5514b4871 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 7 Jan 2014 19:43:35 +0530 Subject: [PATCH 46/87] patch for item price and price list --- .../Print Format/POS Invoice/POS Invoice.txt | 4 +-- patches/1401/__init__.py | 0 ...ying_selling_as_check_box_in_price_list.py | 29 +++++++++++++++++++ stock/doctype/item_price/item_price.py | 7 ++--- stock/doctype/item_price/item_price.txt | 8 +++-- stock/doctype/price_list/price_list.py | 16 +++++----- .../item_wise_price_list_rate/__init__.py | 0 .../item_wise_price_list_rate.txt | 22 ++++++++++++++ 8 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 patches/1401/__init__.py create mode 100644 patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py create mode 100644 stock/report/item_wise_price_list_rate/__init__.py create mode 100644 stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index aab8e18491..4f1b20a945 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-09-13 17:17:47", + "modified": "2014-01-07 18:46:29", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", diff --git a/patches/1401/__init__.py b/patches/1401/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py b/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py new file mode 100644 index 0000000000..d5eb3e8d36 --- /dev/null +++ b/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py @@ -0,0 +1,29 @@ +# Copyright (c) 2014, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + webnotes.reload_doc("stock", "doctype", "price_list") + webnotes.reload_doc("stock", "doctype", "item_price") + + if "buying_or_selling" in webnotes.conn.get_table_columns("Price List"): + webnotes.conn.sql("""update `tabPrice List` set + selling = + case + when buying_or_selling='Selling' + then 1 + end, + buying = + case + when buying_or_selling='Buying' + then 1 + end + """) + webnotes.conn.sql("""update `tabItem Price` ip, `tabPrice List` pl + set ip.buying=pl.buying, ip.selling=pl.selling + where ip.price_list=pl.name""") + + webnotes.conn.sql("""udpate `tabItem Price` set selling=1 where ifnull(selling, 0)=0 and + ifnull(buying, 0)=0""") \ No newline at end of file diff --git a/stock/doctype/item_price/item_price.py b/stock/doctype/item_price/item_price.py index 9a8e3d35fb..e2c9f2fcb0 100644 --- a/stock/doctype/item_price/item_price.py +++ b/stock/doctype/item_price/item_price.py @@ -17,11 +17,8 @@ class DocType: self.update_item_details() def update_price_list_details(self): - if not self.doc.selling and not self.doc.buying: - self.doc.buying, self.doc.selling = webnotes.conn.get_value("Price List", - self.doc.price_list, ["buying", "selling"]) - - self.doc.currency = webnotes.conn.get_value("Price List", self.doc.price_list, "currency") + self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List", + self.doc.price_list, ["buying", "selling", "currency"]) def update_item_details(self): self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item", diff --git a/stock/doctype/item_price/item_price.txt b/stock/doctype/item_price/item_price.txt index b25fd30812..f329a5ff07 100644 --- a/stock/doctype/item_price/item_price.txt +++ b/stock/doctype/item_price/item_price.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-02 16:29:48", "docstatus": 0, - "modified": "2014-01-07 18:11:10", + "modified": "2014-01-07 19:16:49", "modified_by": "Administrator", "owner": "Administrator" }, @@ -64,14 +64,16 @@ "fieldname": "buying", "fieldtype": "Check", "in_list_view": 1, - "label": "Buying" + "label": "Buying", + "read_only": 1 }, { "doctype": "DocField", "fieldname": "selling", "fieldtype": "Check", "in_list_view": 1, - "label": "Selling" + "label": "Selling", + "read_only": 1 }, { "doctype": "DocField", diff --git a/stock/doctype/price_list/price_list.py b/stock/doctype/price_list/price_list.py index 569e759159..40841cfaac 100644 --- a/stock/doctype/price_list/price_list.py +++ b/stock/doctype/price_list/price_list.py @@ -4,14 +4,14 @@ from __future__ import unicode_literals import webnotes from webnotes import msgprint, _, throw -from webnotes.utils import comma_or, cint +from webnotes.utils import cint from webnotes.model.controller import DocListController import webnotes.defaults class DocType(DocListController): def validate(self): - if not self.doc.buying and not self.doc.selling: - throw(_("Price List must be one of Buying or Selling")) + if not cint(self.doc.buying) and not cint(self.doc.selling): + throw(_("Price List must be applicable for Buying or Selling")) if not self.doclist.get({"parentfield": "valid_for_territories"}): # if no territory, set default territory @@ -24,24 +24,24 @@ class DocType(DocListController): else: # at least one territory self.validate_table_has_rows("valid_for_territories") - + def on_update(self): self.set_default_if_missing() self.update_item_price() cart_settings = webnotes.get_obj("Shopping Cart Settings") if cint(cart_settings.doc.enabled): cart_settings.validate_price_lists() - + def set_default_if_missing(self): - if self.doc.selling: + if cint(self.doc.selling): if not webnotes.conn.get_value("Selling Settings", None, "selling_price_list"): webnotes.set_value("Selling Settings", "Selling Settings", "selling_price_list", self.doc.name) - elif self.doc.buying: + elif cint(self.doc.buying): if not webnotes.conn.get_value("Buying Settings", None, "buying_price_list"): webnotes.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.doc.name) def update_item_price(self): webnotes.conn.sql("""update `tabItem Price` set currency=%s, buying=%s, selling=%s, modified=NOW() where price_list=%s""", - (self.doc.currency, self.doc.buying, self.doc.selling, self.doc.name)) \ No newline at end of file + (self.doc.currency, cint(self.doc.buying), cint(self.doc.selling), self.doc.name)) \ No newline at end of file diff --git a/stock/report/item_wise_price_list_rate/__init__.py b/stock/report/item_wise_price_list_rate/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt b/stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt new file mode 100644 index 0000000000..f4d1d67ca4 --- /dev/null +++ b/stock/report/item_wise_price_list_rate/item_wise_price_list_rate.txt @@ -0,0 +1,22 @@ +[ + { + "creation": "2013-09-25 10:21:15", + "docstatus": 0, + "modified": "2014-01-07 18:35:22", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Report", + "is_standard": "Yes", + "json": "{\"filters\":[[\"Item Price\",\"price_list\",\"like\",\"%\"],[\"Item Price\",\"item_code\",\"like\",\"%\"]],\"columns\":[[\"name\",\"Item Price\"],[\"price_list\",\"Item Price\"],[\"item_code\",\"Item Price\"],[\"item_name\",\"Item Price\"],[\"item_description\",\"Item Price\"],[\"ref_rate\",\"Item Price\"],[\"buying\",\"Item Price\"],[\"selling\",\"Item Price\"],[\"currency\",\"Item Price\"]],\"sort_by\":\"Item Price.modified\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}", + "name": "__common__", + "ref_doctype": "Price List", + "report_name": "Item-wise Price List Rate", + "report_type": "Report Builder" + }, + { + "doctype": "Report", + "name": "Item-wise Price List Rate" + } +] \ No newline at end of file From 8d0ef21911df9cc4daba5a10bf94f588941d4e69 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 7 Jan 2014 19:45:33 +0530 Subject: [PATCH 47/87] pos invoice print format changes --- accounts/Print Format/POS Invoice/POS Invoice.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index 4f1b20a945..4710a4e562 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2014-01-07 18:46:29", + "modified": "2014-01-07 19:44:47", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\n\n\n\n\n\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\n\t
RECEIPT NO: DATE:
M/s
\n\t\n\t
\n\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", From 9e2358c54473501bdb6e6b0baee22ee797319c01 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 7 Jan 2014 22:15:04 +0600 Subject: [PATCH 48/87] bumped to version 3.4.9 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 078ca16188..d88d22438b 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.8", + "app_version": "3.4.9", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { From d659343541284611afec55a474abc3a9c555d446 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 8 Jan 2014 17:29:23 +0530 Subject: [PATCH 49/87] Payment Reconciliation: Fix for outstanding voucher query --- .../payment_to_invoice_matching_tool.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py b/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py index dea5fb59c9..fc58418245 100644 --- a/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py +++ b/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py @@ -140,13 +140,13 @@ def gl_entry_details(doctype, txt, searchfield, start, page_len, filters): and ifnull(gle.%(account_type)s, 0) > 0 and (select ifnull(abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))), 0) from `tabGL Entry` - where against_voucher_type = '%(dt)s' + where account = '%(acc)s' + and against_voucher_type = '%(dt)s' and against_voucher = gle.voucher_no and voucher_no != gle.voucher_no) - != abs(ifnull(gle.debit, 0) - ifnull(gle.credit, 0) - ) - and if(gle.voucher_type='Sales Invoice', (select is_pos from `tabSales Invoice` - where name=gle.voucher_no), 0)=0 + != abs(ifnull(gle.debit, 0) - ifnull(gle.credit, 0)) + and if(gle.voucher_type='Sales Invoice', ifnull((select is_pos from `tabSales Invoice` + where name=gle.voucher_no), 0), 0)=0 %(mcond)s ORDER BY gle.posting_date desc, gle.voucher_no desc limit %(start)s, %(page_len)s""" % { From f7a102ffe334876fb481219a764529f318aee52d Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 8 Jan 2014 19:35:01 +0530 Subject: [PATCH 50/87] POS print format fixed --- accounts/Print Format/POS Invoice/POS Invoice.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/Print Format/POS Invoice/POS Invoice.txt b/accounts/Print Format/POS Invoice/POS Invoice.txt index aab8e18491..7f1bba4c96 100644 --- a/accounts/Print Format/POS Invoice/POS Invoice.txt +++ b/accounts/Print Format/POS Invoice/POS Invoice.txt @@ -2,14 +2,14 @@ { "creation": "2011-12-21 11:08:55", "docstatus": 0, - "modified": "2013-09-13 17:17:47", + "modified": "2014-01-08 19:32:16", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n \n \n \n \n \n \n \n
RECEIPT NO: DATE:
M/s
\n\n
\n\n\n", + "html": "\n\t\n\n\t\t\n\t\t\n\n\t\t\n\t\t\n\t\n\n\t\n\t\t\n\t\t
\n\t\t
\n\t\t
\n\t\t
\n\t\t
\n\t\n", "module": "Accounts", "name": "__common__", "print_format_type": "Client", From 102b417b52f6781e7959e5aa8849d63ba78d4fd6 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 9 Jan 2014 11:39:06 +0530 Subject: [PATCH 51/87] Fix: Typo on patch --- .../1401/p01_make_buying_selling_as_check_box_in_price_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py b/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py index d5eb3e8d36..b764a7f935 100644 --- a/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py +++ b/patches/1401/p01_make_buying_selling_as_check_box_in_price_list.py @@ -25,5 +25,5 @@ def execute(): set ip.buying=pl.buying, ip.selling=pl.selling where ip.price_list=pl.name""") - webnotes.conn.sql("""udpate `tabItem Price` set selling=1 where ifnull(selling, 0)=0 and + webnotes.conn.sql("""update `tabItem Price` set selling=1 where ifnull(selling, 0)=0 and ifnull(buying, 0)=0""") \ No newline at end of file From 4bbf91bea18518d56b99e04059d346e2ba548609 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 9 Jan 2014 12:44:44 +0530 Subject: [PATCH 52/87] Added match condition in general ledger report --- accounts/report/general_ledger/general_ledger.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/accounts/report/general_ledger/general_ledger.py b/accounts/report/general_ledger/general_ledger.py index 855b7d1c7a..2f5716ece3 100644 --- a/accounts/report/general_ledger/general_ledger.py +++ b/accounts/report/general_ledger/general_ledger.py @@ -72,6 +72,11 @@ def get_conditions(filters): if filters.get("voucher_no"): conditions.append("voucher_no=%(voucher_no)s") + + + from webnotes.widgets.reportview import build_match_conditions + match_conditions = build_match_conditions("GL Entry") + if match_conditions: conditions.append(match_conditions) return "and {}".format(" and ".join(conditions)) if conditions else "" From cdbd4218a825f605ec15569ab6713683a6d112bb Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 9 Jan 2014 15:49:26 +0530 Subject: [PATCH 53/87] Accounts Receivable fix for partial payment in pos --- .../accounts_receivable/accounts_receivable.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 945bae434a..26e1c8cd47 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -65,15 +65,23 @@ class AccountsReceivableReport(object): if getdate(e.posting_date) <= report_date) def is_receivable(self, gle, future_vouchers): - return ((not gle.against_voucher) or (gle.against_voucher==gle.voucher_no) or - ((gle.against_voucher_type, gle.against_voucher) in future_vouchers)) + return ( + # advance + (not gle.against_voucher) or + + # sales invoice + (gle.against_voucher==gle.voucher_no and gle.debit > 0) or + + # entries adjusted with future vouchers + ((gle.against_voucher_type, gle.against_voucher) in future_vouchers) + ) def get_outstanding_amount(self, gle, report_date): payment_received = 0.0 for e in self.get_gl_entries_for(gle.account, gle.voucher_type, gle.voucher_no): if getdate(e.posting_date) <= report_date and e.name!=gle.name: payment_received += (flt(e.credit) - flt(e.debit)) - + return flt(gle.debit) - flt(gle.credit) - payment_received def get_customer(self, account): From 11bf06ad76a6c510eafa2b9d4c6066ccd9f893cd Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 9 Jan 2014 16:22:09 +0600 Subject: [PATCH 54/87] bumped to version 3.5.0 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index d88d22438b..65fa55c02d 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.9", + "app_version": "3.5.0", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.4.4" + "requires_framework_version": "==3.5.0" } \ No newline at end of file From aeb68b28998b5261a046e5002bb391aeacba20e8 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 9 Jan 2014 15:54:18 +0530 Subject: [PATCH 55/87] Accounts Receivable fix for partial payment in pos --- accounts/report/accounts_receivable/accounts_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/report/accounts_receivable/accounts_receivable.py b/accounts/report/accounts_receivable/accounts_receivable.py index 26e1c8cd47..7758b24744 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.py +++ b/accounts/report/accounts_receivable/accounts_receivable.py @@ -34,7 +34,7 @@ class AccountsReceivableReport(object): for gle in self.get_entries_till(self.filters.report_date): if self.is_receivable(gle, future_vouchers): outstanding_amount = self.get_outstanding_amount(gle, self.filters.report_date) - if abs(outstanding_amount) > 0.01: + if abs(outstanding_amount) > 0.0: due_date = self.get_due_date(gle) invoiced_amount = gle.debit if (gle.debit > 0) else 0 payment_received = invoiced_amount - outstanding_amount From 3e846d19d44fb46579b8ff42d5913651bc21cbf5 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 9 Jan 2014 16:26:53 +0600 Subject: [PATCH 56/87] bumped to version 3.5.1 --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 65fa55c02d..8499ee84d3 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.5.0", + "app_version": "3.5.1", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { From 68b0d54b4b814dd3781fad07c1a2bd43b46ad59f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 9 Jan 2014 17:25:55 +0530 Subject: [PATCH 57/87] Set default accounts in company related to perpetual inventory, only it is enabled --- setup/doctype/company/company.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py index 12281b4415..88d9dcaaa5 100644 --- a/setup/doctype/company/company.py +++ b/setup/doctype/company/company.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import webnotes from webnotes import _, msgprint -from webnotes.utils import cstr +from webnotes.utils import cstr, cint import webnotes.defaults @@ -237,21 +237,28 @@ class DocType: account.insert() def set_default_accounts(self): - accounts = { + def _set_default_accounts(accounts): + for a in accounts: + account_name = accounts[a] + " - " + self.doc.abbr + if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name): + webnotes.conn.set(self.doc, a, account_name) + + _set_default_accounts({ "default_income_account": "Sales", "default_expense_account": "Cost of Goods Sold", "receivables_group": "Accounts Receivable", "payables_group": "Accounts Payable", - "default_cash_account": "Cash", - "stock_received_but_not_billed": "Stock Received But Not Billed", - "stock_adjustment_account": "Stock Adjustment", - "expenses_included_in_valuation": "Expenses Included In Valuation" - } + "default_cash_account": "Cash" + }) + + if cint(webnotes.conn.get_value("Accounts Settings", None, "auto_accounting_for_stock")): + _set_default_accounts({ + "stock_received_but_not_billed": "Stock Received But Not Billed", + "stock_adjustment_account": "Stock Adjustment", + "expenses_included_in_valuation": "Expenses Included In Valuation" + }) + - for a in accounts: - account_name = accounts[a] + " - " + self.doc.abbr - if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name): - webnotes.conn.set(self.doc, a, account_name) def create_default_cost_center(self): cc_list = [ From f3ded044e0686164f7271c130d8b2ad05bef7809 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 9 Jan 2014 17:38:50 +0530 Subject: [PATCH 58/87] Monthly Salary Register: Month is now optional --- hr/report/monthly_salary_register/monthly_salary_register.js | 2 +- hr/report/monthly_salary_register/monthly_salary_register.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hr/report/monthly_salary_register/monthly_salary_register.js b/hr/report/monthly_salary_register/monthly_salary_register.js index 5d3abccde9..32b4ef35fb 100644 --- a/hr/report/monthly_salary_register/monthly_salary_register.js +++ b/hr/report/monthly_salary_register/monthly_salary_register.js @@ -7,7 +7,7 @@ wn.query_reports["Monthly Salary Register"] = { "fieldname":"month", "label": wn._("Month"), "fieldtype": "Select", - "options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", + "options": "\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", "default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][wn.datetime.str_to_obj(wn.datetime.get_today()).getMonth()], }, diff --git a/hr/report/monthly_salary_register/monthly_salary_register.py b/hr/report/monthly_salary_register/monthly_salary_register.py index 8bd8f36ac8..9b8a84fd91 100644 --- a/hr/report/monthly_salary_register/monthly_salary_register.py +++ b/hr/report/monthly_salary_register/monthly_salary_register.py @@ -59,8 +59,8 @@ def get_columns(salary_slips): def get_salary_slips(filters): conditions, filters = get_conditions(filters) - salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s""" % - conditions, filters, as_dict=1) + salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s + order by employee, month""" % conditions, filters, as_dict=1) if not salary_slips: msgprint(_("No salary slip found for month: ") + cstr(filters.get("month")) + From 371663169c7d93f294d190c2c844a0293cf0543a Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 10 Jan 2014 15:05:44 +0530 Subject: [PATCH 59/87] pos view showing inclusive taxes --- accounts/doctype/sales_invoice/pos.js | 51 +++++++++++++++------------ 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index adbdca1b63..ce3784abd3 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -60,10 +60,16 @@ erpnext.POS = Class.extend({
\
\

\ - \ - \ +
\ +
\ + \ +
\ +
\ + \ +
\ +
\

\ \
\ @@ -82,7 +88,7 @@ erpnext.POS = Class.extend({ me.refresh(); }); - this.call_function("delete-items", function() {me.remove_selected_item();}); + this.call_function("remove-items", function() {me.remove_selected_items();}); this.call_function("make-payment", function() {me.make_payment();}); }, check_transaction_type: function() { @@ -333,7 +339,7 @@ erpnext.POS = Class.extend({ } this.disable_text_box_and_button(); - this.make_payment_button(); + this.hide_payment_button(); // If quotation to is not Customer then remove party if (this.frm.doctype == "Quotation") { @@ -370,21 +376,21 @@ erpnext.POS = Class.extend({ var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges", this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype); $(this.wrapper).find(".tax-table") - .toggle((taxes && taxes.length && - flt(me.frm.doc.other_charges_total_export || - me.frm.doc.other_charges_added_import) != 0.0) ? true : false) + .toggle((taxes && taxes.length) ? true : false) .find("tbody").empty(); $.each(taxes, function(i, d) { - $(repl('\ - %(description)s %(rate)s\ - %(tax_amount)s\ - ', { - description: d.description, - rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")), - tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate), - me.frm.doc.currency) - })).appendTo(".tax-table tbody"); + if (d.tax_amount) { + $(repl('\ + %(description)s %(rate)s\ + %(tax_amount)s\ + ', { + description: d.description, + rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")), + tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate), + me.frm.doc.currency) + })).appendTo(".tax-table tbody"); + } }); }, set_totals: function() { @@ -427,7 +433,7 @@ erpnext.POS = Class.extend({ $(this.wrapper).find('input, button').each(function () { $(this).prop('disabled', true); }); - $(this.wrapper).find(".delete-items").hide(); + $(this.wrapper).find(".remove-items").hide(); $(this.wrapper).find(".make-payment").hide(); } else { @@ -437,14 +443,14 @@ erpnext.POS = Class.extend({ $(this.wrapper).find(".make-payment").show(); } }, - make_payment_button: function() { + hide_payment_button: function() { var me = this; // Show Make Payment button only in Sales Invoice if (this.frm.doctype != "Sales Invoice") $(this.wrapper).find(".make-payment").hide(); }, refresh_delete_btn: function() { - $(this.wrapper).find(".delete-items").toggle($(".item-cart .warning").length ? true : false); + $(this.wrapper).find(".remove-items").toggle($(".item-cart .warning").length ? true : false); }, add_item_thru_barcode: function() { var me = this; @@ -466,7 +472,7 @@ erpnext.POS = Class.extend({ } }); }, - remove_selected_item: function() { + remove_selected_items: function() { var me = this; var selected_items = []; var no_of_items = $(this.wrapper).find("#cart tbody tr").length; @@ -487,6 +493,7 @@ erpnext.POS = Class.extend({ } } }); + this.refresh_grid(); }, refresh_grid: function() { From 03463ef73bf373af5a2415b093018c1e978f6a9a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 10 Jan 2014 16:28:41 +0530 Subject: [PATCH 60/87] Move related property setters to custom field property --- patches/1401/__init__.py | 0 ...elated_property_setters_to_custom_field.py | 35 +++++++++++++++++++ patches/patch_list.py | 1 + 3 files changed, 36 insertions(+) create mode 100644 patches/1401/__init__.py create mode 100644 patches/1401/p01_move_related_property_setters_to_custom_field.py diff --git a/patches/1401/__init__.py b/patches/1401/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/patches/1401/p01_move_related_property_setters_to_custom_field.py b/patches/1401/p01_move_related_property_setters_to_custom_field.py new file mode 100644 index 0000000000..6b28553977 --- /dev/null +++ b/patches/1401/p01_move_related_property_setters_to_custom_field.py @@ -0,0 +1,35 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +import webnotes +from webnotes.model.meta import get_field + +def execute(): + webnotes.reload_doc("core", "doctype", "custom_field") + + custom_fields = {} + for cf in webnotes.conn.sql("""select dt, fieldname from `tabCustom Field`""", as_dict=1): + custom_fields.setdefault(cf.dt, []).append(cf.fieldname) + + delete_list = [] + for ps in webnotes.conn.sql("""select * from `tabProperty Setter`""", as_dict=1): + if ps.field_name in custom_fields.get(ps.doc_type, []): + + if ps.property == "previous_field": + property_name = "insert_after" + + field_meta = get_field(ps.doc_type, ps.value) + property_value = field_meta.label if field_meta else "" + else: + property_name = ps.property + property_value =ps.value + + webnotes.conn.sql("""update `tabCustom Field` + set %s=%s where dt=%s and fieldname=%s""" % (property_name, '%s', '%s', '%s'), + (property_value, ps.doc_type, ps.field_name)) + + delete_list.append(ps.name) + + if delete_list: + webnotes.conn.sql("""delete from `tabProperty Setter` where name in (%s)""" % + ', '.join(['%s']*len(delete_list)), tuple(delete_list)) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 608ba77168..e4d2975ea3 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -263,4 +263,5 @@ patch_list = [ "patches.1311.p08_email_digest_recipients", "execute:webnotes.delete_doc('DocType', 'Warehouse Type')", "patches.1312.p02_update_item_details_in_item_price", + "patches.1401.p01_move_related_property_setters_to_custom_field", ] \ No newline at end of file From 35a9d585b4f767c0b8447dafb6dc2b96819707bb Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 13 Jan 2014 12:24:27 +0530 Subject: [PATCH 61/87] Bank Reconciliation Statement: Show balance in debit or credit column based on account type --- .../bank_reconciliation_statement.js | 4 +- .../bank_reconciliation_statement.py | 53 ++++++++----------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js index b93f182f31..7f32e261c7 100644 --- a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js +++ b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js @@ -8,6 +8,7 @@ wn.query_reports["Bank Reconciliation Statement"] = { "label": wn._("Bank Account"), "fieldtype": "Link", "options": "Account", + "reqd": 1, "get_query": function() { return { "query": "accounts.utils.get_account_list", @@ -22,7 +23,8 @@ wn.query_reports["Bank Reconciliation Statement"] = { "fieldname":"report_date", "label": wn._("Date"), "fieldtype": "Date", - "default": get_today() + "default": get_today(), + "reqd": 1 }, ] } \ No newline at end of file diff --git a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py index 431a6496d2..5672497189 100644 --- a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -3,13 +3,14 @@ from __future__ import unicode_literals import webnotes -from webnotes import _, msgprint from webnotes.utils import flt def execute(filters=None): if not filters: filters = {} - - columns = get_columns() + + debit_or_credit = webnotes.conn.get_value("Account", filters["account"], "debit_or_credit") + + columns = get_columns() data = get_entries(filters) from accounts.utils import get_balance_on @@ -20,47 +21,39 @@ def execute(filters=None): total_debit += flt(d[4]) total_credit += flt(d[5]) - if webnotes.conn.get_value("Account", filters["account"], "debit_or_credit") == 'Debit': + if debit_or_credit == 'Debit': bank_bal = flt(balance_as_per_company) - flt(total_debit) + flt(total_credit) else: bank_bal = flt(balance_as_per_company) + flt(total_debit) - flt(total_credit) data += [ - ["", "", "", "Balance as per company books", balance_as_per_company, ""], + get_balance_row("Balance as per company books", balance_as_per_company, debit_or_credit), ["", "", "", "Amounts not reflected in bank", total_debit, total_credit], - ["", "", "", "Balance as per bank", bank_bal, ""] + get_balance_row("Balance as per bank", bank_bal, debit_or_credit) ] - - return columns, data + return columns, data def get_columns(): return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100", "Clearance Date:Date:110", "Against Account:Link/Account:200", "Debit:Currency:120", "Credit:Currency:120" ] - -def get_conditions(filters): - conditions = "" - if not filters.get("account"): - msgprint(_("Please select Bank Account"), raise_exception=1) - else: - conditions += " and jvd.account = %(account)s" - - if not filters.get("report_date"): - msgprint(_("Please select Date on which you want to run the report"), raise_exception=1) - else: - conditions += """ and jv.posting_date <= %(report_date)s - and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s""" - - return conditions def get_entries(filters): - conditions = get_conditions(filters) - entries = webnotes.conn.sql("""select jv.name, jv.posting_date, jv.clearance_date, - jvd.against_account, jvd.debit, jvd.credit - from `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv - where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= '' %s - order by jv.name DESC""" % conditions, filters, as_list=1) + entries = webnotes.conn.sql("""select + jv.name, jv.posting_date, jv.clearance_date, jvd.against_account, jvd.debit, jvd.credit + from + `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv + where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= '' + and jvd.account = %(account)s and jv.posting_date <= %(report_date)s + and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s + order by jv.name DESC""", filters, as_list=1) - return entries \ No newline at end of file + return entries + +def get_balance_row(label, amount, debit_or_credit): + if debit_or_credit == "Debit": + return ["", "", "", label, amount, 0] + else: + return ["", "", "", label, 0, amount] \ No newline at end of file From 14bf711d04e31cc5cb45ab0799ed6dab3a8ebcf5 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 13 Jan 2014 13:28:07 +0530 Subject: [PATCH 62/87] Fixes in frozen accounts validation --- accounts/doctype/gl_entry/gl_entry.py | 3 ++- controllers/accounts_controller.py | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index d3c6317787..694917ffcd 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -146,11 +146,12 @@ def update_outstanding_amt(account, against_voucher_type, against_voucher, on_ca webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" % (against_voucher_type, bal, against_voucher)) -def validate_frozen_account(account, adv_adj): +def validate_frozen_account(account, adv_adj=None): frozen_account = webnotes.conn.get_value("Account", account, "freeze_account") if frozen_account == 'Yes' and not adv_adj: frozen_accounts_modifier = webnotes.conn.get_value( 'Accounts Settings', None, 'frozen_accounts_modifier') + if not frozen_accounts_modifier: webnotes.throw(account + _(" is a frozen account. \ Either make the account active or assign role in Accounts Settings \ diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index a65bf260ee..8d33327569 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes import _, msgprint, throw +from webnotes import _, throw from webnotes.utils import flt, cint, today, cstr from webnotes.model.code import get_obj from setup.utils import get_company_currency @@ -44,14 +44,13 @@ class AccountsController(TransactionBase): def validate_for_freezed_account(self): for fieldname in ["customer", "supplier"]: if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname): - accounts = webnotes.conn.get_values("Account", {"master_type": fieldname.title(), - "master_name": self.doc.fields[fieldname], "company": self.doc.company}, - "freeze_account", as_dict=1) - + accounts = webnotes.conn.get_values("Account", + {"master_type": fieldname.title(), "master_name": self.doc.fields[fieldname], + "company": self.doc.company}, "name") if accounts: - if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts): - throw(_("Account for this ") + fieldname + _(" has been freezed. ") + - self.doc.doctype + _(" can not be made.")) + from accounts.doctype.gl_entry.gl_entry import validate_frozen_account + for account in accounts: + validate_frozen_account(account[0]) def set_price_list_currency(self, buying_or_selling): if self.meta.get_field("currency"): From 0b3c10601c6eedffcdfcbf2f91c4a238b2aa6ac9 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 13 Jan 2014 13:34:34 +0530 Subject: [PATCH 63/87] Increase and decrease quantity buttons in POS --- accounts/doctype/sales_invoice/pos.js | 39 ++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index ce3784abd3..1d58f2d2dc 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -19,8 +19,10 @@ erpnext.POS = Class.extend({ \ \ \ - \ - \ + \ + \ + \ + \ \ \ \ @@ -357,8 +359,18 @@ erpnext.POS = Class.extend({ $(repl('\ \ - \ + \ + \ \ ', { @@ -370,6 +382,11 @@ erpnext.POS = Class.extend({ } )).appendTo($items); }); + + this.wrapper.find(".increase-qty, .decrease-qty").on("click", function() { + var item_code = $(this).closest("tr").attr("id"); + me.selected_item_qty_operation(item_code, $(this).attr("class")); + }); }, show_taxes: function() { var me = this; @@ -501,6 +518,22 @@ erpnext.POS = Class.extend({ this.frm.script_manager.trigger("calculate_taxes_and_totals"); this.refresh(); }, + selected_item_qty_operation: function(item_code, operation) { + var me = this; + var child = wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, + this.frm.cscript.fname, this.frm.doctype); + + $.each(child, function(i, d) { + if (d.item_code == item_code) { + if (operation == "increase-qty") + d.qty += 1; + else if (operation == "decrease-qty") + d.qty != 1 ? d.qty -= 1 : d.qty = 1; + + me.refresh(); + } + }); + }, make_payment: function() { var me = this; var no_of_items = $(this.wrapper).find("#cart tbody tr").length; From c43d58ac79d6144eb6252ff611cc9605f290006d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 13 Jan 2014 17:55:24 +0530 Subject: [PATCH 64/87] Delete Property Setters for Custom Fields, and set them inside Custom Field --- ...elated_property_setters_to_custom_field.py | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/patches/1401/p01_move_related_property_setters_to_custom_field.py b/patches/1401/p01_move_related_property_setters_to_custom_field.py index 6b28553977..cf9221bcfd 100644 --- a/patches/1401/p01_move_related_property_setters_to_custom_field.py +++ b/patches/1401/p01_move_related_property_setters_to_custom_field.py @@ -2,34 +2,24 @@ # License: GNU General Public License v3. See license.txt import webnotes -from webnotes.model.meta import get_field def execute(): webnotes.reload_doc("core", "doctype", "custom_field") - custom_fields = {} - for cf in webnotes.conn.sql("""select dt, fieldname from `tabCustom Field`""", as_dict=1): - custom_fields.setdefault(cf.dt, []).append(cf.fieldname) - + cf_doclist = webnotes.get_doctype("Custom Field") + delete_list = [] - for ps in webnotes.conn.sql("""select * from `tabProperty Setter`""", as_dict=1): - if ps.field_name in custom_fields.get(ps.doc_type, []): - - if ps.property == "previous_field": - property_name = "insert_after" + for d in webnotes.conn.sql("""select cf.name as cf_name, ps.property, + ps.value, ps.name as ps_name + from `tabProperty Setter` ps, `tabCustom Field` cf + where ps.doctype_or_field = 'DocField' and ps.property != 'previous_field' + and ps.doc_type=cf.dt and ps.field_name=cf.fieldname""", as_dict=1): + if cf_doclist.get_field(d.property): + webnotes.conn.sql("""update `tabCustom Field` + set `%s`=%s where name=%s""" % (d.property, '%s', '%s'), (d.value, d.cf_name)) - field_meta = get_field(ps.doc_type, ps.value) - property_value = field_meta.label if field_meta else "" - else: - property_name = ps.property - property_value =ps.value + delete_list.append(d.ps_name) - webnotes.conn.sql("""update `tabCustom Field` - set %s=%s where dt=%s and fieldname=%s""" % (property_name, '%s', '%s', '%s'), - (property_value, ps.doc_type, ps.field_name)) - - delete_list.append(ps.name) - if delete_list: webnotes.conn.sql("""delete from `tabProperty Setter` where name in (%s)""" % ', '.join(['%s']*len(delete_list)), tuple(delete_list)) \ No newline at end of file From 1e347910d5a7e30dea13883fa5f6b651efa93146 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Mon, 13 Jan 2014 19:07:07 +0600 Subject: [PATCH 65/87] bumped to version 3.6.0 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 8499ee84d3..8e033d52a2 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.5.1", + "app_version": "3.6.0", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.5.0" + "requires_framework_version": "==3.7.0" } \ No newline at end of file From b9b6a6cea5ad443a4f3e7124b95d8ca8b6b08481 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 13 Jan 2014 21:21:56 +0530 Subject: [PATCH 66/87] Moved webnotes scheduler event hooks --- erpnext/hooks.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/hooks.txt b/erpnext/hooks.txt index 9d4291b2e3..0c8b71a98f 100644 --- a/erpnext/hooks.txt +++ b/erpnext/hooks.txt @@ -46,13 +46,9 @@ standard_queries = Customer:erpnext.selling.utils.get_customer_list scheduler_event = all:erpnext.support.doctype.support_ticket.get_support_mails.get_support_mails scheduler_event = all:erpnext.hr.doctype.job_applicant.get_job_applications.get_job_applications scheduler_event = all:erpnext.selling.doctype.lead.get_leads.get_leads -scheduler_event = all:webnotes.utils.email_lib.bulk.flush #### Daily -scheduler_event = daily:webnotes.core.doctype.event.event.send_event_digest -scheduler_event = daily:webnotes.core.doctype.notification_count.notification_count.delete_event_notification_count -scheduler_event = daily:webnotes.utils.email_lib.bulk.clear_outbox scheduler_event = daily:erpnext.accounts.doctype.sales_invoice.sales_invoice.manage_recurring_invoices scheduler_event = daily:erpnext.setup.doctype.backup_manager.backup_manager.take_backups_daily scheduler_event = daily:erpnext.stock.utils.reorder_item From d23ae108ae4537748ac4e0aade597423c71aae5a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 14 Jan 2014 15:52:09 +0530 Subject: [PATCH 67/87] Fixes in Comment, if comment by not mentioned, consider owner --- startup/event_handlers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/startup/event_handlers.py b/startup/event_handlers.py index f0323ea36a..b04b588505 100644 --- a/startup/event_handlers.py +++ b/startup/event_handlers.py @@ -70,6 +70,6 @@ def on_build(): def comment_added(doc): """add comment to feed""" - home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, doc.comment_by, - '"' + doc.comment + '"', '#6B24B3') + home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, + doc.comment_by or doc.owner, '"' + doc.comment + '"', '#6B24B3') From d91af2853eff03635fcb69f1ffff3fab847bd4f4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 14 Jan 2014 15:56:52 +0530 Subject: [PATCH 68/87] Allowed import for customer issue --- support/doctype/customer_issue/customer_issue.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/support/doctype/customer_issue/customer_issue.txt b/support/doctype/customer_issue/customer_issue.txt index f9fbc6bd6a..76d49a8199 100644 --- a/support/doctype/customer_issue/customer_issue.txt +++ b/support/doctype/customer_issue/customer_issue.txt @@ -2,11 +2,12 @@ { "creation": "2013-01-10 16:34:30", "docstatus": 0, - "modified": "2013-11-02 16:59:22", + "modified": "2014-01-14 15:56:22", "modified_by": "Administrator", "owner": "harshada@webnotestech.com" }, { + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "icon": "icon-bug", From 3a193708927cee8b5c788c75221ec47a0f54e24e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 14 Jan 2014 17:44:34 +0530 Subject: [PATCH 69/87] Rounding issue and divisional loss adjustment --- .../purchase_invoice/purchase_invoice.py | 3 +- controllers/accounts_controller.py | 28 +++++++++++------- controllers/buying_controller.py | 16 +++++++--- .../production_order/test_production_order.py | 2 ++ public/js/transaction.js | 29 ++++++++++++++----- 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 0b8ad46dd0..06b7a3ad2e 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -358,7 +358,8 @@ class DocType(BuyingController): # expense will be booked in sales invoice stock_item_and_auto_accounting_for_stock = True - valuation_amt = item.amount + item.item_tax_amount + item.rm_supp_cost + valuation_amt = flt(item.amount + item.item_tax_amount + item.rm_supp_cost, + self.precision("amount", item)) gl_entries.append( self.get_gl_dict({ diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 8d33327569..e5b0b9d75b 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -223,20 +223,22 @@ class AccountsController(TransactionBase): _on_previous_row_error("1 - %d" % (tax.row_id,)) def calculate_taxes(self): - for item in self.item_doclist: + # maintain actual tax rate based on idx + actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist + if tax.charge_type == "Actual"]) + + for n, item in enumerate(self.item_doclist): item_tax_map = self._load_item_tax_rate(item.item_tax_rate) for i, tax in enumerate(self.tax_doclist): # tax_amount represents the amount of tax for the current step current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map) - - # case when net total is 0 but there is an actual type charge - # in this case add the actual amount to tax.tax_amount - # and tax.grand_total_for_current_item for the first such iteration - if tax.charge_type=="Actual" and \ - not (current_tax_amount or self.doc.net_total or tax.tax_amount): - zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax)) - current_tax_amount += zero_net_total_adjustment + + # Adjust divisional loss to the last item + if tax.charge_type == "Actual": + actual_tax_dict[tax.idx] -= current_tax_amount + if n == len(self.item_doclist) - 1: + current_tax_amount += actual_tax_dict[tax.idx] # store tax_amount for current item as it will be used for # charge type = 'On Previous Row Amount' @@ -248,7 +250,8 @@ class AccountsController(TransactionBase): if tax.category: # if just for valuation, do not add the tax amount in total # hence, setting it as 0 for further steps - current_tax_amount = 0.0 if (tax.category == "Valuation") else current_tax_amount + current_tax_amount = 0.0 if (tax.category == "Valuation") \ + else current_tax_amount current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0 @@ -267,6 +270,11 @@ class AccountsController(TransactionBase): # in tax.total, accumulate grand total of each item tax.total += tax.grand_total_for_current_item + # set precision in the last item iteration + if n == len(self.item_doclist) - 1: + tax.total = flt(tax.total, self.precision("total", tax)) + tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax)) + def get_current_tax_amount(self, item, tax, item_tax_map): tax_rate = self._get_tax_rate(tax, item_tax_map) current_tax_amount = 0.0 diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 3c6981d6cb..7954ca0abb 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -175,23 +175,31 @@ class BuyingController(StockController): stock_items = self.get_stock_items() stock_items_qty, stock_items_amount = 0, 0 + last_stock_item_idx = 1 for d in self.doclist.get({"parentfield": parentfield}): if d.item_code and d.item_code in stock_items: stock_items_qty += flt(d.qty) stock_items_amount += flt(d.amount) + last_stock_item_idx = d.idx total_valuation_amount = sum([flt(d.tax_amount) for d in self.doclist.get({"parentfield": "purchase_tax_details"}) if d.category in ["Valuation", "Valuation and Total"]]) - - for item in self.doclist.get({"parentfield": parentfield}): + + valuation_amount_adjustment = total_valuation_amount + for i, item in enumerate(self.doclist.get({"parentfield": parentfield})): if item.item_code and item.qty and item.item_code in stock_items: item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \ else flt(item.qty) / stock_items_qty - item.item_tax_amount = flt(item_proportion * total_valuation_amount, - self.precision("item_tax_amount", item)) + if i == (last_stock_item_idx - 1): + item.item_tax_amount = flt(valuation_amount_adjustment, + self.precision("item_tax_amount", item)) + else: + item.item_tax_amount = flt(item_proportion * total_valuation_amount, + self.precision("item_tax_amount", item)) + valuation_amount_adjustment -= item.item_tax_amount self.round_floats_in(item) diff --git a/manufacturing/doctype/production_order/test_production_order.py b/manufacturing/doctype/production_order/test_production_order.py index ca28708cc1..da45a9bdb6 100644 --- a/manufacturing/doctype/production_order/test_production_order.py +++ b/manufacturing/doctype/production_order/test_production_order.py @@ -35,6 +35,7 @@ class TestProductionOrder(unittest.TestCase): stock_entry.doc.fg_completed_qty = 4 stock_entry.doc.posting_date = "2013-05-12" + stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013" stock_entry.run_method("get_items") stock_entry.submit() @@ -52,6 +53,7 @@ class TestProductionOrder(unittest.TestCase): stock_entry = make_stock_entry(pro_order, "Manufacture/Repack") stock_entry = webnotes.bean(stock_entry) stock_entry.doc.posting_date = "2013-05-12" + stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013" stock_entry.doc.fg_completed_qty = 15 stock_entry.run_method("get_items") stock_entry.insert() diff --git a/public/js/transaction.js b/public/js/transaction.js index 0fe0535c6b..1e03833bd6 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -540,6 +540,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ calculate_taxes: function() { var me = this; + var actual_tax_dict = {}; + + // maintain actual tax rate based on idx + $.each(this.frm.tax_doclist, function(i, tax) { + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] = flt(tax.rate); + } + }); $.each(this.frm.item_doclist, function(n, item) { var item_tax_map = me._load_item_tax_rate(item.item_tax_rate); @@ -549,15 +557,15 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map); me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount); - - // case when net total is 0 but there is an actual type charge - // in this case add the actual amount to tax.tax_amount - // and tax.grand_total_for_current_item for the first such iteration - if(tax.charge_type == "Actual" && - !(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) { - var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax)); - current_tax_amount += zero_net_total_adjustment; + + // Adjust divisional loss to the last item + if (tax.charge_type == "Actual") { + actual_tax_dict[tax.idx] -= current_tax_amount; + if (n == me.frm.item_doclist.length - 1) { + current_tax_amount += actual_tax_dict[tax.idx] } + } + // store tax_amount for current item as it will be used for // charge type = 'On Previous Row Amount' @@ -589,6 +597,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ // in tax.total, accumulate grand total for each item tax.total += tax.grand_total_for_current_item; + + if (n == me.frm.item_doclist.length - 1) { + tax.total = flt(tax.total, precision("total", tax)); + tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax)); + } }); }); }, From ee6200576a53ad6ca8de685b028ddb44c2b30e96 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 14 Jan 2014 18:34:10 +0530 Subject: [PATCH 70/87] Highest priority to user properties while fetching warehouse from item --- selling/utils/__init__.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py index 85c20e86d8..f495f58e44 100644 --- a/selling/utils/__init__.py +++ b/selling/utils/__init__.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, _, throw -from webnotes.utils import flt, cint, comma_and +from webnotes import _, throw +from webnotes.utils import flt, cint import json def get_customer_list(doctype, txt, searchfield, start, page_len, filters): @@ -121,10 +121,16 @@ def _validate_item_details(args, item): def _get_basic_details(args, item_bean, warehouse_fieldname): item = item_bean.doc + from webnotes.defaults import get_user_default_as_list + user_default_warehouse_list = get_user_default_as_list('warehouse') + user_default_warehouse = user_default_warehouse_list[0] \ + if len(user_default_warehouse_list)==1 else "" + out = webnotes._dict({ "item_code": item.name, "description": item.description_html or item.description, - warehouse_fieldname: item.default_warehouse or args.get(warehouse_fieldname), + warehouse_fieldname: user_default_warehouse or item.default_warehouse \ + or args.get(warehouse_fieldname), "income_account": item.default_income_account or args.income_account \ or webnotes.conn.get_value("Company", args.company, "default_income_account"), "expense_account": item.purchase_account or args.expense_account \ From f55d9414cd23612bc2e5c29907b63e0e439dfcd3 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 14 Jan 2014 19:19:14 +0600 Subject: [PATCH 71/87] bumped to version 3.6.1 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 8e033d52a2..45acaf2cd3 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.6.0", + "app_version": "3.6.1", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.7.0" + "requires_framework_version": "==3.7.1" } \ No newline at end of file From c5d4fc38aa57e4bde919d5e8e1859fcd11e3e4d3 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 15 Jan 2014 10:54:07 +0530 Subject: [PATCH 72/87] Fixes in monthly salary register --- .../monthly_salary_register/monthly_salary_register.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hr/report/monthly_salary_register/monthly_salary_register.py b/hr/report/monthly_salary_register/monthly_salary_register.py index 9b8a84fd91..42c62e474b 100644 --- a/hr/report/monthly_salary_register/monthly_salary_register.py +++ b/hr/report/monthly_salary_register/monthly_salary_register.py @@ -50,9 +50,9 @@ def get_columns(salary_slips): where ifnull(d_modified_amount, 0) != 0 and parent in (%s)""" % (', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips])) - columns = columns + [(e + ":Link/Earning Type:120") for e in earning_types] + \ + columns = columns + [(e + ":Currency:120") for e in earning_types] + \ ["Arrear Amount:Currency:120", "Leave Encashment Amount:Currency:150", - "Gross Pay:Currency:120"] + [(d + ":Link/Deduction Type:120") for d in ded_types] + \ + "Gross Pay:Currency:120"] + [(d + ":Currency:120") for d in ded_types] + \ ["Total Deduction:Currency:120", "Net Pay:Currency:120"] return columns, earning_types, ded_types @@ -102,6 +102,6 @@ def get_ss_ded_map(salary_slips): ss_ded_map = {} for d in ss_deductions: ss_ded_map.setdefault(d.parent, webnotes._dict()).setdefault(d.d_type, []) - ss_ded_map[d.parent][d.e_type] = flt(d.d_modified_amount) + ss_ded_map[d.parent][d.d_type] = flt(d.d_modified_amount) return ss_ded_map \ No newline at end of file From a6df26839dea38b04a17ecf29fafd2f60bc73d8b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 15 Jan 2014 12:21:14 +0530 Subject: [PATCH 73/87] Higher priority to user's default price list over customer's default price list --- utilities/transaction_base.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 5c28d8d8b6..f783faa9ec 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -79,9 +79,10 @@ class TransactionBase(StatusUpdater): """ customer_defaults = self.get_customer_defaults() - customer_defaults["selling_price_list"] = customer_defaults.get("price_list") or \ - webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or \ - self.doc.selling_price_list + customer_defaults["selling_price_list"] = self.get_user_default_price_list("Selling") or \ + customer_defaults.get("price_list") or \ + webnotes.conn.get_value("Customer Group", self.doc.customer_group, + "default_price_list") or self.doc.selling_price_list for fieldname, val in customer_defaults.items(): if self.meta.get_field(fieldname): @@ -90,6 +91,12 @@ class TransactionBase(StatusUpdater): if self.meta.get_field("sales_team") and self.doc.customer: self.set_sales_team_for_customer() + def get_user_default_price_list(self, price_list_for): + from webnotes.defaults import get_user_default_as_list + user_default_price_list = get_user_default_as_list("selling_price_list" + if price_list_for=="Selling" else "buying_price_list") + return user_default_price_list[0] if len(user_default_price_list)==1 else "" + def set_sales_team_for_customer(self): from webnotes.model import default_fields @@ -120,8 +127,9 @@ class TransactionBase(StatusUpdater): out["supplier_name"] = supplier.supplier_name if supplier.default_currency: out["currency"] = supplier.default_currency - if supplier.default_price_list: - out["buying_price_list"] = supplier.default_price_list + + out["buying_price_list"] = self.get_user_default_price_list("Buying") or \ + supplier.default_price_list or self.doc.buying_price_list return out From 76dd468f0ed39d5bd09fb06107b7fd479e5deb02 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 15 Jan 2014 14:23:38 +0530 Subject: [PATCH 74/87] update about erpnext with version number --- public/js/conf.js | 15 ++++++++------- public/js/toolbar.js | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/public/js/conf.js b/public/js/conf.js index 929bfcaa59..1fe21c7611 100644 --- a/public/js/conf.js +++ b/public/js/conf.js @@ -24,16 +24,17 @@ $(document).bind('toolbar_setup', function() { wn.provide('wn.ui.misc'); wn.ui.misc.about = function() { if(!wn.ui.misc.about_dialog) { - var d = new wn.ui.Dialog({title: wn._('About ERPNext')}) + var d = new wn.ui.Dialog({title: wn._('About')}) $(d.body).html(repl("
\ -

"+wn._("ERPNext is an open-source web based ERP made by Web Notes Technologies Pvt Ltd.\ - to provide an integrated tool to manage most processes in a small organization.\ - For more information about Web Notes, or to buy hosting servies, go to ")+ - "https://erpnext.com.

\ -

"+wn._("To report an issue, go to ")+"GitHub Issues

\ -
\ +

ERPNext

\ +

v" + wn.boot.app_version + "

\ +

"+wn._("An open source ERP made for the web.

") + + "

"+wn._("To report an issue, go to ")+"GitHub Issues

\ +

http://erpnext.org.

\

License: GNU General Public License Version 3

\ +
\ +

© 2014 Web Notes Technologies Pvt. Ltd and contributers

\
", wn.app)); wn.ui.misc.about_dialog = d; diff --git a/public/js/toolbar.js b/public/js/toolbar.js index e0affaf61d..1d6fa919b2 100644 --- a/public/js/toolbar.js +++ b/public/js/toolbar.js @@ -21,6 +21,6 @@ erpnext.toolbar.setup = function() { '+wn._('Live Chat')+''); } - $("#toolbar-tools").append('
  • \ + $("#toolbar-tools").append('
  • \ Latest Updates
  • '); -} \ No newline at end of file +} From a682d45846de23f3c03382a4d371befe2b5342f7 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 15 Jan 2014 16:39:01 +0530 Subject: [PATCH 75/87] webnotes/erpnext # 1320 - hide fields fix --- accounts/doctype/pos_setting/pos_setting.txt | 4 ++-- .../doctype/purchase_receipt_item/purchase_receipt_item.txt | 4 ++-- stock/doctype/stock_entry_detail/stock_entry_detail.txt | 6 +++--- stock/doctype/stock_reconciliation/stock_reconciliation.txt | 5 +++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/accounts/doctype/pos_setting/pos_setting.txt b/accounts/doctype/pos_setting/pos_setting.txt index 09a3757985..4319c268ed 100755 --- a/accounts/doctype/pos_setting/pos_setting.txt +++ b/accounts/doctype/pos_setting/pos_setting.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 12:15:51", "docstatus": 0, - "modified": "2013-11-02 16:58:38", + "modified": "2014-01-15 16:23:58", "modified_by": "Administrator", "owner": "Administrator" }, @@ -154,7 +154,7 @@ "reqd": 1 }, { - "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "doctype": "DocField", "fieldname": "expense_account", "fieldtype": "Link", diff --git a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt index 1d9397909d..9bc66a42da 100755 --- a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt +++ b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:10", "docstatus": 0, - "modified": "2014-01-03 18:28:20", + "modified": "2014-01-15 16:00:44", "modified_by": "Administrator", "owner": "Administrator" }, @@ -336,7 +336,7 @@ }, { "default": ":Company", - "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "doctype": "DocField", "fieldname": "cost_center", "fieldtype": "Link", diff --git a/stock/doctype/stock_entry_detail/stock_entry_detail.txt b/stock/doctype/stock_entry_detail/stock_entry_detail.txt index b97928b961..25835e0bf3 100644 --- a/stock/doctype/stock_entry_detail/stock_entry_detail.txt +++ b/stock/doctype/stock_entry_detail/stock_entry_detail.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-29 18:22:12", "docstatus": 0, - "modified": "2013-11-08 16:15:44", + "modified": "2014-01-15 16:08:45", "modified_by": "Administrator", "owner": "Administrator" }, @@ -165,7 +165,7 @@ "read_only": 1 }, { - "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "doctype": "DocField", "fieldname": "expense_account", "fieldtype": "Link", @@ -175,7 +175,7 @@ }, { "default": ":Company", - "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "doctype": "DocField", "fieldname": "cost_center", "fieldtype": "Link", diff --git a/stock/doctype/stock_reconciliation/stock_reconciliation.txt b/stock/doctype/stock_reconciliation/stock_reconciliation.txt index c9959d36e3..7d5021c89e 100644 --- a/stock/doctype/stock_reconciliation/stock_reconciliation.txt +++ b/stock/doctype/stock_reconciliation/stock_reconciliation.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-28 10:35:31", "docstatus": 0, - "modified": "2013-09-24 15:35:12", + "modified": "2014-01-15 15:45:07", "modified_by": "Administrator", "owner": "Administrator" }, @@ -102,7 +102,7 @@ "reqd": 1 }, { - "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "doctype": "DocField", "fieldname": "expense_account", "fieldtype": "Link", @@ -110,6 +110,7 @@ "options": "Account" }, { + "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)", "doctype": "DocField", "fieldname": "cost_center", "fieldtype": "Link", From 39eb7faeb9148cb667834cbdce00eab926ac2a25 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 15 Jan 2014 17:36:18 +0530 Subject: [PATCH 76/87] Update billing percentage and status from SI/PI in SO/PO, when net total is zero --- .../accounts_settings/accounts_settings.py | 8 +++- .../purchase_invoice/purchase_invoice.py | 3 +- .../doctype/sales_invoice/sales_invoice.py | 2 + controllers/status_updater.py | 37 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/accounts/doctype/accounts_settings/accounts_settings.py b/accounts/doctype/accounts_settings/accounts_settings.py index a6e993863d..2475fdaf66 100644 --- a/accounts/doctype/accounts_settings/accounts_settings.py +++ b/accounts/doctype/accounts_settings/accounts_settings.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import webnotes from webnotes import _ +from webnotes.utils import cint class DocType: def __init__(self, d, dl): @@ -14,7 +15,12 @@ class DocType: def on_update(self): webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock) - if self.doc.auto_accounting_for_stock: + if cint(self.doc.auto_accounting_for_stock): + # set default perpetual account in company + for company in webnotes.conn.sql("select name from tabCompany"): + webnotes.bean("Company", company[0]).save() + + # Create account head for warehouses warehouse_list = webnotes.conn.sql("select name, company from tabWarehouse", as_dict=1) warehouse_with_no_company = [d.name for d in warehouse_list if not d.company] if warehouse_with_no_company: diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 06b7a3ad2e..fcd6846507 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -302,6 +302,7 @@ class DocType(BuyingController): self.make_gl_entries() self.update_against_document_in_jv() self.update_prevdoc_status() + self.update_billing_status_for_zero_amount_refdoc("Purchase Order") def make_gl_entries(self): auto_accounting_for_stock = \ @@ -421,7 +422,7 @@ class DocType(BuyingController): remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher") self.update_prevdoc_status() - + self.update_billing_status_for_zero_amount_refdoc("Purchase Order") self.make_cancel_gl_entries() def on_update(self): diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index bfba30fa1b..a39702b3fc 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -88,6 +88,7 @@ class DocType(SellingController): self.update_status_updater_args() self.update_prevdoc_status() + self.update_billing_status_for_zero_amount_refdoc("Sales Order") # this sequence because outstanding may get -ve self.make_gl_entries() @@ -114,6 +115,7 @@ class DocType(SellingController): self.update_status_updater_args() self.update_prevdoc_status() + self.update_billing_status_for_zero_amount_refdoc("Sales Order") self.make_cancel_gl_entries() diff --git a/controllers/status_updater.py b/controllers/status_updater.py index a285c4798d..1743887bf7 100644 --- a/controllers/status_updater.py +++ b/controllers/status_updater.py @@ -232,6 +232,43 @@ class StatusUpdater(DocListController): 'Fully %(keyword)s', 'Partly %(keyword)s')) where name='%(name)s'""" % args) + + def update_billing_status_for_zero_amount_refdoc(self, ref_dt): + ref_fieldname = ref_dt.lower().replace(" ", "_") + zero_amount_refdoc = [] + all_zero_amount_refdoc = webnotes.conn.sql_list("""select name from `tab%s` + where docstatus=1 and net_total = 0""" % ref_dt) + + for item in self.doclist.get({"parentfield": "entries"}): + if item.fields.get(ref_fieldname) \ + and item.fields.get(ref_fieldname) in all_zero_amount_refdoc \ + and item.fields.get(ref_fieldname) not in zero_amount_refdoc: + zero_amount_refdoc.append(item.fields[ref_fieldname]) + + if zero_amount_refdoc: + self.update_biling_status(zero_amount_refdoc, ref_dt, ref_fieldname) + + def update_biling_status(self, zero_amount_refdoc, ref_dt, ref_fieldname): + for ref_dn in zero_amount_refdoc: + ref_doc_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) from `tab%s Item` + where parent=%s""" % (ref_dt, '%s'), (ref_dn))[0][0]) + + billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) + from `tab%s Item` where %s=%s and docstatus=1""" % + (self.doc.doctype, ref_fieldname, '%s'), (ref_dn))[0][0]) + + per_billed = ((ref_doc_qty if billed_qty > ref_doc_qty else billed_qty)\ + / ref_doc_qty)*100 + webnotes.conn.set_value(ref_dt, ref_dn, "per_billed", per_billed) + + from webnotes.model.meta import has_field + if has_field(ref_dt, "billing_status"): + if per_billed < 0.001: billing_status = "Not Billed" + elif per_billed >= 99.99: billing_status = "Fully Billed" + else: billing_status = "Partly Billed" + + webnotes.conn.set_value(ref_dt, ref_dn, "billing_status", billing_status) + def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None): """ Returns the tolerance for the item, if not set, returns global tolerance From 5cdb8cea135f2df03e8a662fe37be28cc5735794 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Jan 2014 12:08:12 +0530 Subject: [PATCH 77/87] Reset filters in Item Price report on each route --- stock/doctype/item/item.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index c9aa75e7b7..e18a0f2809 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -29,10 +29,7 @@ cur_frm.cscript.make_dashboard = function() { cur_frm.cscript.edit_prices_button = function() { cur_frm.add_custom_button("Add / Edit Prices", function() { - wn.route_options = { - "item_code": cur_frm.doc.name - }; - wn.set_route("Report", "Item Price"); + wn.set_route("Report", "Item Price", {"item_code": cur_frm.doc.name}); }, "icon-money"); } From e31a97f3558479d6b6a989e1d716e21351c62547 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Jan 2014 14:24:32 +0530 Subject: [PATCH 78/87] Calculate taxes and charges total in server side --- .../purchase_common/purchase_common.js | 30 +++++++++++-------- controllers/buying_controller.py | 22 ++++++++++++-- controllers/selling_controller.py | 3 +- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 14b8279245..e3957ab847 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -302,11 +302,11 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ calculate_totals: function() { var tax_count = this.frm.tax_doclist.length; - this.frm.doc.grand_total = flt( - tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total, + this.frm.doc.grand_total = flt(tax_count ? + this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total, precision("grand_total")); - this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate, - precision("grand_total_import")); + this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / + this.frm.doc.conversion_rate, precision("grand_total_import")); this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("total_tax")); @@ -321,20 +321,26 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ } // other charges added/deducted + this.frm.doc.other_charges_added = 0.0 + this.frm.doc.other_charges_deducted = 0.0 if(tax_count) { this.frm.doc.other_charges_added = wn.utils.sum($.map(this.frm.tax_doclist, - function(tax) { return (tax.add_deduct_tax == "Add" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; })); + function(tax) { return (tax.add_deduct_tax == "Add" + && in_list(["Valuation and Total", "Total"], tax.category)) ? + tax.tax_amount : 0.0; })); this.frm.doc.other_charges_deducted = wn.utils.sum($.map(this.frm.tax_doclist, - function(tax) { return (tax.add_deduct_tax == "Deduct" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; })); + function(tax) { return (tax.add_deduct_tax == "Deduct" + && in_list(["Valuation and Total", "Total"], tax.category)) ? + tax.tax_amount : 0.0; })); - wn.model.round_floats_in(this.frm.doc, ["other_charges_added", "other_charges_deducted"]); - - this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added / this.frm.doc.conversion_rate, - precision("other_charges_added_import")); - this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted / this.frm.doc.conversion_rate, - precision("other_charges_deducted_import")); + wn.model.round_floats_in(this.frm.doc, + ["other_charges_added", "other_charges_deducted"]); } + this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added / + this.frm.doc.conversion_rate, precision("other_charges_added_import")); + this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted / + this.frm.doc.conversion_rate, precision("other_charges_deducted_import")); }, _cleanup: function() { diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 7954ca0abb..bdc7327c5f 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -124,8 +124,8 @@ class BuyingController(StockController): self.round_floats_in(self.doc, ["net_total", "net_total_import"]) def calculate_totals(self): - self.doc.grand_total = flt(self.tax_doclist and \ - self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total")) + self.doc.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist + else self.doc.net_total, self.precision("grand_total")) self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate, self.precision("grand_total_import")) @@ -137,6 +137,24 @@ class BuyingController(StockController): if self.meta.get_field("rounded_total_import"): self.doc.rounded_total_import = _round(self.doc.grand_total_import) + + if self.meta.get_field("other_charges_added"): + self.doc.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist + if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]), + self.precision("other_charges_added")) + + if self.meta.get_field("other_charges_deducted"): + self.doc.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist + if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]), + self.precision("other_charges_deducted")) + + if self.meta.get_field("other_charges_added_import"): + self.doc.other_charges_added_import = flt(self.doc.other_charges_added / + self.doc.conversion_rate, self.precision("other_charges_added_import")) + + if self.meta.get_field("other_charges_deducted_import"): + self.doc.other_charges_deducted_import = flt(self.doc.other_charges_deducted / + self.doc.conversion_rate, self.precision("other_charges_deducted_import")) def calculate_outstanding_amount(self): if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus < 2: diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 67c1462662..4806c73a81 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -191,7 +191,8 @@ class SellingController(StockController): self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total, self.precision("other_charges_total")) - self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export, + self.doc.other_charges_total_export = flt( + self.doc.grand_total_export - self.doc.net_total_export, self.precision("other_charges_total_export")) self.doc.rounded_total = _round(self.doc.grand_total) From 6933617538236c33f1ae2c103483b4161dc1dab3 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 16 Jan 2014 16:59:22 +0600 Subject: [PATCH 79/87] bumped to version 3.6.2 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 45acaf2cd3..c2524671a0 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.6.1", + "app_version": "3.6.2", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.7.1" + "requires_framework_version": "==3.7.2" } \ No newline at end of file From f6b77479d75318ee2cfe17c68d63a40ac14e6160 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 16 Jan 2014 18:18:49 +0530 Subject: [PATCH 80/87] Patch: Update billing status for zero value order --- hr/doctype/salary_manager/salary_manager.js | 2 +- ...ate_billing_status_for_zero_value_order.py | 29 +++++++++++++++++++ patches/patch_list.py | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 patches/1401/update_billing_status_for_zero_value_order.py diff --git a/hr/doctype/salary_manager/salary_manager.js b/hr/doctype/salary_manager/salary_manager.js index 032c29e509..ec485ca671 100644 --- a/hr/doctype/salary_manager/salary_manager.js +++ b/hr/doctype/salary_manager/salary_manager.js @@ -43,7 +43,7 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) { jv = locals['Journal Voucher'][jv]; jv.voucher_type = 'Bank Voucher'; jv.user_remark = wn._('Payment of salary for the month: ') + doc.month + - wn._('and fiscal year: ') + doc.fiscal_year; + wn._(' and fiscal year: ') + doc.fiscal_year; jv.fiscal_year = doc.fiscal_year; jv.company = doc.company; jv.posting_date = dateutil.obj_to_str(new Date()); diff --git a/patches/1401/update_billing_status_for_zero_value_order.py b/patches/1401/update_billing_status_for_zero_value_order.py new file mode 100644 index 0000000000..afeed55ed4 --- /dev/null +++ b/patches/1401/update_billing_status_for_zero_value_order.py @@ -0,0 +1,29 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +import webnotes +from webnotes.utils import flt + +def execute(): + for order_type in ["Sales", "Purchase"]: + for d in webnotes.conn.sql("""select par.name, sum(ifnull(child.qty, 0)) as total_qty + from `tab%s Order` par, `tab%s Order Item` child + where par.name = child.parent and par.docstatus = 1 + and ifnull(par.net_total, 0) = 0 group by par.name""" % + (order_type, order_type), as_dict=1): + + billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) + from `tab%s Invoice Item` where %s=%s and docstatus=1""" % + (order_type, "sales_order" if order_type=="Sales" else "purchase_order", '%s'), + (d.name))[0][0]) + + per_billed = ((d.total_qty if billed_qty > d.total_qty else billed_qty)\ + / d.total_qty)*100 + webnotes.conn.set_value(order_type+ " Order", d.name, "per_billed", per_billed) + + if order_type == "Sales": + if per_billed < 0.001: billing_status = "Not Billed" + elif per_billed >= 99.99: billing_status = "Fully Billed" + else: billing_status = "Partly Billed" + + webnotes.conn.set_value("Sales Order", d.name, "billing_status", billing_status) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 04a9288c60..2598ae8c94 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -265,4 +265,5 @@ patch_list = [ "patches.1312.p02_update_item_details_in_item_price", "patches.1401.p01_move_related_property_setters_to_custom_field", "patches.1401.p01_make_buying_selling_as_check_box_in_price_list", + "patches.1401.update_billing_status_for_zero_value_order", ] \ No newline at end of file From e1e63a91d6f4571621cf519ce9c337085b216f3a Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 17 Jan 2014 11:12:20 +0530 Subject: [PATCH 81/87] Allow renaming of campaign --- accounts/doctype/sales_invoice/sales_invoice.txt | 4 ++-- selling/doctype/campaign/campaign.js | 13 +------------ selling/doctype/campaign/campaign.txt | 3 ++- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 99bfe5cdf0..0433f31ad6 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-11-18 15:16:50", + "modified": "2014-01-16 15:36:16", "modified_by": "Administrator", "owner": "Administrator" }, @@ -1091,7 +1091,7 @@ "fieldtype": "Select", "label": "Recurring Type", "no_copy": 1, - "options": "Monthly\nQuarterly\nHalf-yearly\nYearly", + "options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly", "print_hide": 1, "read_only": 0 }, diff --git a/selling/doctype/campaign/campaign.js b/selling/doctype/campaign/campaign.js index 6271a163cb..33479579a5 100644 --- a/selling/doctype/campaign/campaign.js +++ b/selling/doctype/campaign/campaign.js @@ -1,13 +1,2 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - - - -//--------- ONLOAD ------------- -cur_frm.cscript.onload = function(doc, cdt, cdn) { - -} - -cur_frm.cscript.refresh = function(doc, cdt, cdn) { - -} \ No newline at end of file +// License: GNU General Public License v3. See license.txt \ No newline at end of file diff --git a/selling/doctype/campaign/campaign.txt b/selling/doctype/campaign/campaign.txt index 7025bf5654..7170e051d6 100644 --- a/selling/doctype/campaign/campaign.txt +++ b/selling/doctype/campaign/campaign.txt @@ -2,11 +2,12 @@ { "creation": "2013-01-10 16:34:18", "docstatus": 0, - "modified": "2013-07-05 14:29:57", + "modified": "2014-01-16 12:52:19", "modified_by": "Administrator", "owner": "Administrator" }, { + "allow_rename": 1, "autoname": "field:campaign_name", "description": "Keep Track of Sales Campaigns. Keep track of Leads, Quotations, Sales Order etc from Campaigns to gauge Return on Investment. ", "doctype": "DocType", From f32314dd0b2fbbe0d183f77ad8ac5af4ef42a223 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Jan 2014 11:53:25 +0530 Subject: [PATCH 82/87] Do not set income/expense account automatically in company master --- setup/doctype/company/company.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py index 88d9dcaaa5..34e5ca4a59 100644 --- a/setup/doctype/company/company.py +++ b/setup/doctype/company/company.py @@ -244,8 +244,6 @@ class DocType: webnotes.conn.set(self.doc, a, account_name) _set_default_accounts({ - "default_income_account": "Sales", - "default_expense_account": "Cost of Goods Sold", "receivables_group": "Accounts Receivable", "payables_group": "Accounts Payable", "default_cash_account": "Cash" @@ -257,8 +255,6 @@ class DocType: "stock_adjustment_account": "Stock Adjustment", "expenses_included_in_valuation": "Expenses Included In Valuation" }) - - def create_default_cost_center(self): cc_list = [ From bc99c9d6e0d7871decb8b092c94bad70db520e67 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Jan 2014 12:04:24 +0530 Subject: [PATCH 83/87] Priority to user's deafult price list over customer's default price list --- utilities/transaction_base.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index f783faa9ec..6c515a52b6 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -78,8 +78,9 @@ class TransactionBase(StatusUpdater): 3. Clears existing Sales Team and fetches the one mentioned in Customer """ customer_defaults = self.get_customer_defaults() - - customer_defaults["selling_price_list"] = self.get_user_default_price_list("Selling") or \ + + customer_defaults["selling_price_list"] = \ + self.get_user_default_price_list("selling_price_list") or \ customer_defaults.get("price_list") or \ webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or self.doc.selling_price_list @@ -91,11 +92,11 @@ class TransactionBase(StatusUpdater): if self.meta.get_field("sales_team") and self.doc.customer: self.set_sales_team_for_customer() - def get_user_default_price_list(self, price_list_for): - from webnotes.defaults import get_user_default_as_list - user_default_price_list = get_user_default_as_list("selling_price_list" - if price_list_for=="Selling" else "buying_price_list") - return user_default_price_list[0] if len(user_default_price_list)==1 else "" + def get_user_default_price_list(self, price_list): + from webnotes.defaults import get_defaults_for + user_default_price_list = get_defaults_for(webnotes.session.user).get(price_list) + return cstr(user_default_price_list) \ + if not isinstance(user_default_price_list, list) else "" def set_sales_team_for_customer(self): from webnotes.model import default_fields @@ -128,7 +129,7 @@ class TransactionBase(StatusUpdater): if supplier.default_currency: out["currency"] = supplier.default_currency - out["buying_price_list"] = self.get_user_default_price_list("Buying") or \ + out["buying_price_list"] = self.get_user_default_price_list("buying_price_list") or \ supplier.default_price_list or self.doc.buying_price_list return out From da08124df2d7cc1ba7ce47ede4b8b988ce3b7f77 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Fri, 17 Jan 2014 15:27:19 +0530 Subject: [PATCH 84/87] remove mysql-python pinning to 1.2.4 --- install_erpnext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_erpnext.py b/install_erpnext.py index e285d4bbfe..8e1448362b 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -20,7 +20,7 @@ requirements = [ "jinja2", "markdown2", "markupsafe", - "mysql-python==1.2.4", + "mysql-python", "pygeoip", "python-dateutil", "python-memcached", From 96db41d996472f7f40a8267171dd01cf51de0d44 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Fri, 17 Jan 2014 17:26:31 +0600 Subject: [PATCH 85/87] bumped to version 3.6.3 --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index c2524671a0..450e2bca6d 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.6.2", + "app_version": "3.6.3", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { @@ -74,5 +74,5 @@ "type": "module" } }, - "requires_framework_version": "==3.7.2" + "requires_framework_version": "==3.7.3" } \ No newline at end of file From ed87335513986af2ba6766e331906078c830a9bd Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 17 Jan 2014 18:57:21 +0530 Subject: [PATCH 86/87] decimal places fix in item prices report --- stock/report/item_prices/item_prices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index e744cc73e4..5eee7df42d 100644 --- a/stock/report/item_prices/item_prices.py +++ b/stock/report/item_prices/item_prices.py @@ -15,7 +15,7 @@ def execute(filters=None): bom_rate = get_item_bom_rate() val_rate_map = get_valuation_rate() - precision = get_currency_precision or 2 + precision = get_currency_precision() or 2 data = [] for item in sorted(item_map): From 719f2803b3ca826860c4bfbbbe374bc613e733c6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 20 Jan 2014 17:01:28 +0530 Subject: [PATCH 87/87] Fixed conflict while merging with develop branch --- .../doctype/stock_reconciliation/stock_reconciliation.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt index 0a639d5e74..6f9d04d492 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt @@ -2,11 +2,7 @@ { "creation": "2013-03-28 10:35:31", "docstatus": 0, -<<<<<<< HEAD:erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.txt - "modified": "2013-12-20 16:06:50", -======= "modified": "2014-01-15 15:45:07", ->>>>>>> dbb495548352d46b30bf84fb4b29ef4a247cb21c:stock/doctype/stock_reconciliation/stock_reconciliation.txt "modified_by": "Administrator", "owner": "Administrator" },
    ItemQtyItemQtyRate
    %(item_code)s%(item_name)s\ +
    \ + \ +
    \ +
    \ +
    \ + \ +
    \ +
    %(amount)s
    %(rate)s