From 0c2c521d387b7251b6e1fea25299b3d0c086f1cc Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 6 Feb 2013 14:20:07 +0530 Subject: [PATCH 1/4] cleanp: bookmarks --- home/page/latest_updates/latest_updates.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js index db64849e72..7e28824229 100644 --- a/home/page/latest_updates/latest_updates.js +++ b/home/page/latest_updates/latest_updates.js @@ -1,4 +1,10 @@ erpnext.updates = [ + ["6th February, 2013", [ + "Bookmarks: Add bookmarks via toolbar by clicking on the sign.", + ]], + ["5th February, 2013", [ + "Holiday Block List: Block users from taking leave on certain days.", + ]], ["2nd February, 2013", [ "Warehouse: Added table Warehouse User to restrict Warehouse Entry per user.", ]], From 22807a61cd020e2497dde13f37acfe04f07d1b52 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 6 Feb 2013 15:41:32 +0530 Subject: [PATCH 2/4] patch to remove accounts/utils folder and removed unrequired test cases related to unused tax controller --- .../purchase_invoice/test_purchase_invoice.py | 101 ---- .../sales_invoice/test_sales_invoice.py | 315 ------------ controllers/tax_controller.py | 456 ------------------ controllers/transaction_controller.py | 123 ----- .../remove_account_utils_folder.py | 6 + patches/patch_list.py | 1 + 6 files changed, 7 insertions(+), 995 deletions(-) delete mode 100644 controllers/tax_controller.py delete mode 100644 controllers/transaction_controller.py create mode 100644 patches/february_2013/remove_account_utils_folder.py diff --git a/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 861c2895cc..606ebb9bb4 100644 --- a/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -166,106 +166,5 @@ class TestPurchaseReceipt(unittest.TestCase): for d in gl_entries: self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account)) - # def test_purchase_invoice(self): - # from webnotes.model.doclist import DocList - # controller = webnotes.insert(DocList(purchase_invoice_doclist)) - # controller.load_from_db() - # - # from controllers.tax_controller import TaxController - # tax_controller = TaxController(controller.doc, controller.doclist) - # tax_controller.item_table_field = "entries" - # tax_controller.calculate_taxes_and_totals() - # - # controller.doc = tax_controller.doc - # controller.doclist = tax_controller.doclist - # - # controller.save() - # controller.load_from_db() - # dl = controller.doclist - # - # # test net total - # self.assertEqual(dl[0].net_total, 1250) - # - # # test tax amounts and totals - # expected_values = [ - # ["Shipping Charges - %s" % abbr, 100, 1350], - # ["Customs Duty - %s" % abbr, 125, 1350], - # ["Excise Duty - %s" % abbr, 140, 1490], - # ["Education Cess - %s" % abbr, 2.8, 1492.8], - # ["S&H Education Cess - %s" % abbr, 1.4, 1494.2], - # ["CST - %s" % abbr, 29.88, 1524.08], - # ["VAT - Test - %s" % abbr, 156.25, 1680.33], - # ["Discount - %s" % abbr, -168.03, 1512.30], - # ] - # for i, tax in enumerate(dl.get({"parentfield": "other_charges"})): - # self.assertEqual(tax.account_head, expected_values[i][0]) - # self.assertEqual(tax.tax_amount, expected_values[i][1]) - # self.assertEqual(tax.total, expected_values[i][2]) - # - # # test item tax amount - # expected_values = [ - # ["Home Desktop 100", 90], - # ["Home Desktop 200", 135] - # ] - # for i, item in enumerate(dl.get({"parentfield": "purchase_invoice_items"})): - # self.assertEqual(item.item_code, expected_values[i][0]) - # self.assertEqual(item.item_tax_amount, expected_values[i][1]) - # - # - # def test_purchase_invoice_having_zero_amount_items(self): - # from webnotes.model.doclist import DocList - # sample_purchase_invoice_doclist = [] + purchase_invoice_doclist - # - # # set rate and amount as 0 - # sample_purchase_invoice_doclist[1]["import_rate"] = 0 - # sample_purchase_invoice_doclist[2]["import_rate"] = 0 - # - # - # controller = webnotes.insert(DocList(sample_purchase_invoice_doclist)) - # controller.load_from_db() - # - # from controllers.tax_controller import TaxController - # tax_controller = TaxController(controller.doc, controller.doclist) - # tax_controller.item_table_field = "entries" - # tax_controller.calculate_taxes_and_totals() - # - # controller.doc = tax_controller.doc - # controller.doclist = tax_controller.doclist - # - # controller.save() - # controller.load_from_db() - # dl = controller.doclist - # - # # test net total - # self.assertEqual(dl[0].net_total, 0) - # - # # test tax amounts and totals - # expected_values = [ - # ["Shipping Charges - %s" % abbr, 100, 100], - # ["Customs Duty - %s" % abbr, 0, 100], - # ["Excise Duty - %s" % abbr, 0, 100], - # ["Education Cess - %s" % abbr, 0, 100], - # ["S&H Education Cess - %s" % abbr, 0, 100], - # ["CST - %s" % abbr, 2, 102], - # ["VAT - Test - %s" % abbr, 0, 102], - # ["Discount - %s" % abbr, -10.2, 91.8], - # ] - # for i, tax in enumerate(dl.get({"parentfield": "other_charges"})): - # # print tax.account_head, tax.tax_amount, tax.total - # self.assertEqual(tax.account_head, expected_values[i][0]) - # self.assertEqual(tax.tax_amount, expected_values[i][1]) - # self.assertEqual(tax.total, expected_values[i][2]) - # - # # test item tax amount - # expected_values = [ - # ["Home Desktop 100", 0], - # ["Home Desktop 200", 0] - # ] - # for i, item in enumerate(dl.get({"parentfield": "purchase_invoice_items"})): - # self.assertEqual(item.item_code, expected_values[i][0]) - # self.assertEqual(item.item_tax_amount, expected_values[i][1]) - - - def tearDown(self): webnotes.conn.rollback() \ No newline at end of file diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index cf0fbdabe4..bb2157c2a4 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -228,321 +228,6 @@ class TestSalesInvoice(unittest.TestCase): for gle in gl_entries: self.assertEqual([gle.debit, gle.credit], expected_gl_entries[gle.account]) - - # - # def test_inclusive_rate_validations(self): - # doclist = [] + [d.copy() for d in sales_invoice_doclist] - # doclist[1]["export_rate"] = 62.5 - # doclist[2]["export_rate"] = 191 - # for i in [3, 5, 6, 7, 8, 9]: - # doclist[i]["included_in_print_rate"] = 1 - # - # # tax type "Actual" cannot be inclusive - # self.assertRaises(webnotes.ValidationError, webnotes.insert, - # DocList(doclist)) - # - # doclist[3]["included_in_print_rate"] = 0 - # # taxes above included type 'On Previous Row Total' should also be included - # self.assertRaises(webnotes.ValidationError, webnotes.insert, - # DocList(doclist)) - # - # def test_sales_invoice_with_inclusive_tax(self): - # doclist = [ - # # parent - # { - # "doctype": "Sales Invoice", - # "debit_to": "West Wind Inc. - %s" % abbr, - # "customer_name": "West Wind Inc.", - # "naming_series": "INV", "posting_date": nowdate(), - # "company": company, - # "fiscal_year": webnotes.conn.get_default("fiscal_year"), - # "currency": webnotes.conn.get_default("currency"), - # "price_list_currency": webnotes.conn.get_default("currency"), - # "conversion_rate": 1.0, "plc_conversion_rate": 1.0, - # "grand_total_export": 0 - # }, - # # items - # { - # "doctype": "Sales Invoice Item", "warehouse": "Default Warehouse", - # "item_code": "Home Desktop 100", "qty": 10, "export_rate": 62.503, - # "parentfield": "entries", - # "uom": "Nos", "item_tax_rate": json.dumps({"Excise Duty - %s" % abbr: 10}) - # }, - # { - # "doctype": "Sales Invoice Item", "warehouse": "Default Warehouse", - # "item_code": "Home Desktop 200", "qty": 5, "export_rate": 190.6608, - # "parentfield": "entries", - # "uom": "Nos" - # }, - # # taxes - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "On Net Total", - # "account_head": "Excise Duty - %s" % abbr, "rate": 12, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Amount", - # "account_head": "Education Cess - %s" % abbr, "rate": 2, "row_id": 1, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Amount", - # "account_head": "S&H Education Cess - %s" % abbr, "rate": 1, "row_id": 1, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Total", - # "account_head": "CST - %s" % abbr, "rate": 2, "row_id": 3, - # "parentfield": "other_charges", "included_in_print_rate": 1, - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "On Net Total", - # "account_head": "VAT - Test - %s" % abbr, "rate": 12.5, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "On Net Total", - # "account_head": "Customs Duty - %s" % abbr, "rate": 10, - # "parentfield": "other_charges", - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "Actual", - # "account_head": "Shipping Charges - %s" % abbr, "rate": 100, - # "parentfield": "other_charges", - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Total", - # "account_head": "adj_rate - %s" % abbr, "rate": -10, "row_id": 7, - # "parentfield": "other_charges", - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # ] - # - # controller = webnotes.insert(DocList(doclist)) - # controller.load_from_db() - # - # from controllers.tax_controller import TaxController - # tax_controller = TaxController(controller.doc, controller.doclist) - # tax_controller.item_table_field = "entries" - # tax_controller.calculate_taxes_and_totals() - # - # controller.doc = tax_controller.doc - # controller.doclist = tax_controller.doclist - # - # controller.save() - # controller.load_from_db() - # dl = controller.doclist - # - # # test item values calculation - # expected_values = [ - # { - # "item_code": "Home Desktop 100", - # "ref_rate": 62.503, - # "adj_rate": 0, - # "export_amount": 625.03, - # "base_ref_rate": 50, - # "basic_rate": 50, - # "amount": 500 - # }, - # { - # "item_code": "Home Desktop 200", - # "ref_rate": 190.6608, - # "adj_rate": 0, - # "export_amount": 953.3, - # "base_ref_rate": 150, - # "basic_rate": 150, - # "amount": 750 - # }, - # ] - # for i, item in enumerate(dl.get({"parentfield": "entries"})): - # for key, val in expected_values[i].items(): - # self.assertEqual(item.fields.get(key), val) - # - # # test tax amounts and totals - # expected_values = [ - # ["Excise Duty - %s" % abbr, 140, 1390, 0, 1578.33], - # ["Education Cess - %s" % abbr, 2.8, 1392.8, 0, 1578.33], - # ["S&H Education Cess - %s" % abbr, 1.4, 1394.2, 0, 1578.33], - # ["CST - %s" % abbr, 27.88, 1422.08, 0, 1578.33], - # ["VAT - Test - %s" % abbr, 156.25, 1578.33, 0, 1578.33], - # ["Customs Duty - %s" % abbr, 125, 1703.33, 125, 1703.33], - # ["Shipping Charges - %s" % abbr, 100, 1803.33, 100, 1803.33], - # ["adj_rate - %s" % abbr, -180.33, 1623, -180.33, 1623], - # ] - # for i, tax in enumerate(dl.get({"parentfield": "other_charges"})): - # # print tax.account_head, tax.tax_amount, tax.total, tax.tax_amount_print, \ - # # tax.total_print - # self.assertEqual(tax.account_head, expected_values[i][0]) - # self.assertEqual(tax.tax_amount, expected_values[i][1]) - # self.assertEqual(tax.total, expected_values[i][2]) - # # self.assertEqual(tax.tax_amount_print, expected_values[i][3]) - # self.assertEqual(tax.total_print, expected_values[i][4]) - # - # # test net total - # self.assertEqual(dl[0].net_total, 1250) - # - # # # test grand total - # self.assertEqual(dl[0].grand_total, 1623) - # self.assertEqual(dl[0].grand_total_export, 1623) - # - # def test_usd_sales_invoice_with_inclusive_tax(self): - # # print - # # print "-"*80 - # # print "test_usd_sales_invoice_with_inclusive_tax" - # # print "-"*80 - # - # # Note: below values were obtained through manual calculation and verified by test - # - # doclist = [ - # # parent - # { - # "doctype": "Sales Invoice", - # "debit_to": "West Wind Inc. - %s" % abbr, - # "customer_name": "West Wind Inc.", - # "naming_series": "INV", "posting_date": nowdate(), - # "company": company, - # "fiscal_year": webnotes.conn.get_default("fiscal_year"), - # "currency": "USD", "price_list_currency": "USD", "conversion_rate": 50.0, - # "plc_conversion_rate": 50.0, "grand_total_export": 0 - # }, - # # items - # { - # "doctype": "Sales Invoice Item", "warehouse": "Default Warehouse", - # "item_code": "Home Desktop 100", "qty": 10, "export_rate": 50, - # "adj_rate": 10, "parentfield": "entries", - # "uom": "Nos", "item_tax_rate": json.dumps({"Excise Duty - %s" % abbr: 10}) - # }, - # { - # "doctype": "Sales Invoice Item", "warehouse": "Default Warehouse", - # "item_code": "Home Desktop 200", "qty": 5, "export_rate": 150, - # "adj_rate": 20, "parentfield": "entries", - # "uom": "Nos" - # }, - # # taxes - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "On Net Total", - # "account_head": "Excise Duty - %s" % abbr, "rate": 12, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Amount", - # "account_head": "Education Cess - %s" % abbr, "rate": 2, "row_id": 1, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Amount", - # "account_head": "S&H Education Cess - %s" % abbr, "rate": 1, "row_id": 1, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Total", - # "account_head": "CST - %s" % abbr, "rate": 2, "row_id": 3, - # "parentfield": "other_charges", "included_in_print_rate": 1, - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "On Net Total", - # "account_head": "VAT - Test - %s" % abbr, "rate": 12.5, - # "parentfield": "other_charges", "included_in_print_rate": 1 - # }, - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "On Net Total", - # "account_head": "Customs Duty - %s" % abbr, "rate": 10, - # "parentfield": "other_charges", - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # { - # "doctype": "Sales Taxes and Charges", "charge_type": "Actual", - # "account_head": "Shipping Charges - %s" % abbr, "rate": 100, - # "parentfield": "other_charges", - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # { - # "doctype": "Sales Taxes and Charges", - # "charge_type": "On Previous Row Total", - # "account_head": "adj_rate - %s" % abbr, "rate": -10, "row_id": 7, - # "parentfield": "other_charges", - # "cost_center_other_charges": "Default Cost Center - %s" % abbr - # }, - # ] - # - # controller = webnotes.insert(DocList(doclist)) - # controller.load_from_db() - # - # from controllers.tax_controller import TaxController - # tax_controller = TaxController(controller.doc, controller.doclist) - # tax_controller.item_table_field = "entries" - # tax_controller.calculate_taxes_and_totals() - # - # controller.doc = tax_controller.doc - # controller.doclist = tax_controller.doclist - # - # controller.save() - # controller.load_from_db() - # dl = controller.doclist - # - # # test item values calculation - # expected_values = [ - # { - # "item_code": "Home Desktop 100", - # "ref_rate": 55.5556, - # "adj_rate": 10, - # "export_amount": 500, - # "base_ref_rate": 2222.1156, - # "basic_rate": 1999.904, - # "amount": 19999.04 - # }, - # { - # "item_code": "Home Desktop 200", - # "ref_rate": 187.5, - # "adj_rate": 20, - # "export_amount": 750, - # "base_ref_rate": 7375.664, - # "basic_rate": 5900.5312, - # "amount": 29502.66 - # }, - # ] - # for i, item in enumerate(dl.get({"parentfield": "entries"})): - # for key, val in expected_values[i].items(): - # self.assertEqual(item.fields.get(key), val) - # - # # test tax amounts and totals - # expected_values = [ - # ["Excise Duty - %s" % abbr, 5540.22, 55041.92, 0, 1250], - # ["Education Cess - %s" % abbr, 110.81, 55152.73, 0, 1250], - # ["S&H Education Cess - %s" % abbr, 55.4, 55208.13, 0, 1250], - # ["CST - %s" % abbr, 1104.16, 56312.29, 0, 1250], - # ["VAT - Test - %s" % abbr, 6187.71, 62500, 0, 1250], - # ["Customs Duty - %s" % abbr, 4950.17, 67450.17, 99.01, 1349.01], - # ["Shipping Charges - %s" % abbr, 5000, 72450.17, 100, 1449.01], - # ["adj_rate - %s" % abbr, -7245.01, 65205.16, -144.9, 1304.11], - # ] - # for i, tax in enumerate(dl.get({"parentfield": "other_charges"})): - # # print tax.account_head, tax.tax_amount, tax.total, tax.tax_amount_print, \ - # # tax.total_print - # self.assertEqual(tax.account_head, expected_values[i][0]) - # self.assertEqual(tax.tax_amount, expected_values[i][1]) - # self.assertEqual(tax.total, expected_values[i][2]) - # # self.assertEqual(tax.tax_amount_print, expected_values[i][3]) - # self.assertEqual(tax.total_print, expected_values[i][4]) - # - # # test net total - # self.assertEqual(dl[0].net_total, 49501.7) - # - # # # test grand total - # self.assertEqual(dl[0].grand_total, 65205.16) - # self.assertEqual(dl[0].grand_total_export, 1304.11) - # def tearDown(self): webnotes.conn.rollback() \ No newline at end of file diff --git a/controllers/tax_controller.py b/controllers/tax_controller.py deleted file mode 100644 index 617c4cc7df..0000000000 --- a/controllers/tax_controller.py +++ /dev/null @@ -1,456 +0,0 @@ -# ERPNext - web based ERP (http://erpnext.com) -# Copyright (C) 2012 Web Notes Technologies Pvt Ltd -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from __future__ import unicode_literals -import webnotes -import webnotes.model -from webnotes import _, msgprint -from webnotes.utils import cint, flt -from webnotes.model.utils import round_floats_in_doc -import json - -from controllers.transaction_controller import TransactionController - -class TaxController(TransactionController): - def append_taxes(self): - """append taxes as per tax master link field""" - # clear tax table - self.doclist = self.doclist.get({"parentfield": ["!=", - self.fmap.taxes_and_charges]}) - - tax_master_doctype = self.meta.get_options(self.fmap.taxes_and_charges_master) - master_tax_list = webnotes.get_doclist(tax_master_doctype, - self.doc.fields.get(self.fmap.taxes_and_charges_master)).get( - {"parentfield": self.fmap.taxes_and_charges}) - - for base_tax in master_tax_list: - tax = _dict([[field, base_tax.fields.get(field)] - for field in base_tax.fields - if field not in webnotes.model.default_fields]) - tax.update({ - "doctype": self.meta.get_options(self.fmap.taxes_and_charges), - "parentfield": self.fmap.taxes_and_charges, - "rate": flt(tax.rate, self.precision.tax.rate), - }) - self.doclist.append(tax) - - def calculate_taxes_and_totals(self): - """ - Calculates: - * amount for each item - * valuation_tax_amount for each item, - * tax amount and tax total for each tax - * net total - * total taxes - * grand total - """ - self.doc.fields[self.fmap.exchange_rate] = \ - flt(self.doc.fields.get(self.fmap.exchange_rate), - self.precision.main[self.fmap.exchange_rate]) - - self.calculate_item_values() - - self.initialize_taxes() - if self.meta.get_field("included_in_print_rate", - parentfield=self.fmap.taxes_and_charges): - self.determine_exclusive_rate() - - self.calculate_net_total() - self.calculate_taxes() - self.calculate_totals() - self.set_amount_in_words() - self.cleanup() - - def calculate_item_values(self): - def _set_base(item, print_field, base_field): - """set values in base currency""" - item.fields[base_field] = flt((flt(item.fields[print_field], - self.precision.item[print_field]) * \ - self.doc.fields.get(self.fmap.exchange_rate)), - self.precision.item[base_field]) - - for item in self.item_doclist: - round_floats_in_doc(item, self.precision.item) - - if item.fields.get(self.fmap.discount) == 100: - if not item.fields.get(self.fmap.print_ref_rate): - item.fields[self.fmap.print_ref_rate] = \ - item.fields.get(self.fmap.print_rate) - item.fields[self.fmap.print_rate] = 0 - else: - if item.fields.get(self.fmap.print_ref_rate): - item.fields[self.fmap.print_rate] = \ - flt(item.fields.get(self.fmap.print_ref_rate) * - (1.0 - (item.fields.get(self.fmap.discount) / 100.0)), - self.precision.item[self.fmap.print_rate]) - else: - # assume that print rate and discount are specified - item.fields[self.fmap.print_ref_rate] = \ - flt(item.fields.get(self.fmap.print_rate) / - (1.0 - (item.fields.get(self.fmap.discount) / 100.0)), - self.precision.item[self.fmap.print_ref_rate]) - - item.fields[self.fmap.print_amount] = \ - flt(item.fields.get(self.fmap.print_rate) * \ - item.fields.get("qty"), - self.precision.item[self.fmap.print_amount]) - - _set_base(item, self.fmap.print_ref_rate, self.fmap.ref_rate) - _set_base(item, self.fmap.print_rate, self.fmap.rate) - _set_base(item, self.fmap.print_amount, "amount") - - def initialize_taxes(self): - for tax in self.tax_doclist: - # initialize totals to 0 - tax.tax_amount = tax.total = tax.total_print = 0 - tax.grand_total_for_current_item = tax.tax_amount_for_current_item = 0 - - # for actual type, user can mention actual tax amount in tax.tax_amount_print - if tax.charge_type != "Actual" or tax.rate: - tax.tax_amount_print = 0 - - self.validate_on_previous_row(tax) - self.validate_included_tax(tax) - - # round relevant values - round_floats_in_doc(tax, self.precision.tax) - - def calculate_net_total(self): - self.doc.net_total = 0 - self.doc.fields[self.fmap.net_total_print] = 0 - - for item in self.item_doclist: - self.doc.net_total += item.amount - self.doc.fields[self.fmap.net_total_print] += \ - item.fields.get(self.fmap.print_amount) - - self.doc.net_total = flt(self.doc.net_total, self.precision.main.net_total) - self.doc.fields[self.fmap.net_total_print] = \ - flt(self.doc.fields.get(self.fmap.net_total_print), - self.precision.main.get(self.fmap.net_total_print)) - - def calculate_taxes(self): - for item in self.item_doclist: - item_tax_map = self._load_item_tax_rate(item.item_tax_rate) - item.fields[self.fmap.valuation_tax_amount] = 0 - - 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) - - if hasattr(self, "set_valuation_tax_amount"): - self.set_valuation_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 not (current_tax_amount or self.doc.net_total or tax.tax_amount) and \ - tax.charge_type=="Actual": - zero_net_total_adjustment = flt((tax.tax_amount_print * - self.doc.fields.get(self.fmap.exchange_rate)) or tax.rate, - self.precision.tax.tax_amount) - 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 - - # accumulate tax amount into tax.tax_amount - tax.tax_amount += tax.tax_amount_for_current_item - - # accumulate tax_amount_print only if tax is not included - # and if tax amount of actual type is entered in 'rate' field - if not cint(tax.included_in_print_rate) and (tax.charge_type != "Actual" - or tax.rate): - tax.tax_amount_print += flt((tax.tax_amount_for_current_item / - self.doc.fields.get(self.fmap.exchange_rate)), - self.precision.tax.tax_amount_print) - - if tax.category == "Valuation": - # if just for valuation, do not add the tax amount in total - # hence, setting it as 0 for further steps - current_tax_amount = 0 - - # Calculate tax.total viz. grand total till that step - # 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.tax.total) - - # if inclusive pricing, current_tax_amount should not be considered - if cint(tax.included_in_print_rate): - current_tax_amount = 0 - - tax.grand_total_print_for_current_item = \ - flt(item.fields.get(self.fmap.print_amount) + - (current_tax_amount / self.doc.fields.get( - self.fmap.exchange_rate)), - self.precision.tax.total_print) - else: - tax.grand_total_for_current_item = \ - flt(self.tax_doclist[i-1].grand_total_for_current_item + - current_tax_amount, self.precision.tax.total) - - # if inclusive pricing, current_tax_amount should not be considered - if cint(tax.included_in_print_rate): - current_tax_amount = 0 - - tax.grand_total_print_for_current_item = \ - flt(self.tax_doclist[i-1].grand_total_print_for_current_item + - (current_tax_amount / self.doc.fields.get( - self.fmap.exchange_rate)), - self.precision.tax.total_print) - - # in tax.total, accumulate grand total of each item - tax.total += tax.grand_total_for_current_item - tax.total_print += tax.grand_total_print_for_current_item - - # TODO store tax_breakup for each item - - def get_current_tax_amount(self, item, tax, item_tax_map): - tax_rate = self._get_tax_rate(tax, item_tax_map) - - if tax.charge_type == "Actual": - # distribute the tax amount proportionally to each item row - actual = flt(tax.rate or (tax.tax_amount_print * \ - self.doc.fields.get(self.fmap.exchange_rate)), - self.precision.tax.tax_amount) - current_tax_amount = (self.doc.net_total - and ((item.amount / self.doc.net_total) * actual) - or 0) - elif tax.charge_type == "On Net Total": - current_tax_amount = (tax_rate / 100.0) * item.amount - elif tax.charge_type == "On Previous Row Amount": - current_tax_amount = (tax_rate / 100.0) * \ - self.tax_doclist[cint(tax.row_id) - 1].tax_amount_for_current_item - 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 - - return flt(current_tax_amount, self.precision.tax.tax_amount) - - def calculate_totals(self): - if self.tax_doclist: - self.doc.grand_total = flt(self.tax_doclist[-1].total, - self.precision.main.grand_total) - self.doc.fields[self.fmap.grand_total_print] = \ - flt(self.tax_doclist[-1].total_print, - self.precision.main[self.fmap.grand_total_print]) - else: - self.doc.grand_total = flt(self.doc.net_total, - self.precision.main.grand_total) - self.doc.fields[self.fmap.grand_total_print] = \ - flt(self.doc.fields.get(self.fmap.net_total_print), - self.precision.main[self.fmap.grand_total_print]) - - self.doc.fields[self.fmap.taxes_and_charges_total] = \ - flt(self.doc.grand_total - self.doc.net_total, - self.precision.main[self.fmap.taxes_and_charges_total]) - - self.doc.taxes_and_charges_total_print = \ - flt(self.doc.fields.get(self.fmap.grand_total_print) - \ - self.doc.fields.get(self.fmap.net_total_print), - self.precision.main.taxes_and_charges_total_print) - - self.doc.rounded_total = round(self.doc.grand_total) - self.doc.fields[self.fmap.rounded_total_print] = \ - round(self.doc.fields.get(self.fmap.grand_total_print)) - - def set_amount_in_words(self): - from webnotes.utils import money_in_words - base_currency = webnotes.conn.get_value("Company", self.doc.currency, - "default_currency") - - self.doc.fields[self.fmap.grand_total_in_words] = \ - money_in_words(self.doc.grand_total, base_currency) - self.doc.fields[self.fmap.rounded_total_in_words] = \ - money_in_words(self.doc.rounded_total, base_currency) - - self.doc.fields[self.fmap.grand_total_in_words_print] = \ - money_in_words(self.doc.fields.get(self.fmap.grand_total_print), - self.doc.currency) - self.doc.fields[self.fmap.rounded_total_in_words_print] = \ - money_in_words(self.doc.fields.get(self.fmap.rounded_total_print), - self.doc.currency) - - def validate_on_previous_row(self, tax): - """ - validate if a valid row id is mentioned in case of - On Previous Row Amount and On Previous Row Total - """ - 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]: " + \ - _("Please specify a valid") + " %(row_id_label)s") % { - "idx": tax.idx, - "taxes_doctype": tax.parenttype, - "row_id_label": self.meta.get_label("row_id", - parentfield=self.fmap.taxes_and_charges) - }, raise_exception=True) - - def validate_included_tax(self, tax): - """ - validate conditions related to "Is this Tax Included in Rate?" - """ - def _on_previous_row_error(tax, row_range): - msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ - _("If") + " '%(inclusive_label)s' " + _("is checked for") + \ - " '%(charge_type_label)s' = '%(charge_type)s', " + _("then") + " " + \ - _("Row") + " # %(row_range)s " + _("should also have") + \ - " '%(inclusive_label)s' = " + _("checked")) % { - "idx": tax.idx, - "taxes_doctype": tax.doctype, - "inclusive_label": self.meta.get_label("included_in_print_rate", - parentfield=self.fmap.taxes_and_charges), - "charge_type_label": self.meta.get_label("charge_type", - parentfield=self.fmap.taxes_and_charges), - "charge_type": tax.charge_type, - "row_range": row_range, - }, raise_exception=True) - - if cint(tax.included_in_print_rate): - if tax.charge_type == "Actual": - # now inclusive rate for type 'Actual' - msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ - "'%(charge_type_label)s' = '%(charge_type)s' " + \ - _("cannot be included in item's rate")) % { - "idx": tax.idx, - "taxes_doctype": self.meta.get_options( - self.fmap.taxes_and_charges), - "charge_type_label": self.meta.get_label("charge_type", - parentfield=self.fmap.taxes_and_charges), - "charge_type": tax.charge_type, - }, raise_exception=True) - - elif tax.charge_type == "On Previous Row Amount" and \ - not cint(self.tax_doclist[cint(tax.row_id) - 1]\ - .included_in_print_rate): - # for an inclusive tax of type "On Previous Row Amount", - # dependent row should also be inclusive - _on_previous_row_error(tax, 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.idx - 1]]): - # for an inclusive tax of type "On Previous Row Total", - # all rows above it should also be inclusive - _on_previous_row_error(tax, "1 - %d" % (tax.idx - 1)) - - def determine_exclusive_rate(self): - if not any((cint(tax.included_in_print_rate) for tax in self.tax_doclist)): - # if no tax is marked as included in print rate, no need to proceed further - return - - for item in self.item_doclist: - item_tax_map = self._load_item_tax_rate(item.item_tax_rate) - - cumulated_tax_fraction = 0 - - for i, tax in enumerate(self.tax_doclist): - if cint(tax.included_in_print_rate): - tax.tax_fraction_for_current_item = \ - self.get_current_tax_fraction(tax, item_tax_map) - else: - tax.tax_fraction_for_current_item = 0 - - if i==0: - tax.grand_total_fraction_for_current_item = 1 + \ - tax.tax_fraction_for_current_item - else: - tax.grand_total_fraction_for_current_item = \ - self.tax_doclist[i-1].grand_total_fraction_for_current_item \ - + tax.tax_fraction_for_current_item - - cumulated_tax_fraction += tax.tax_fraction_for_current_item - - if cumulated_tax_fraction: - item.fields[self.fmap.rate] = \ - flt((item.fields.get(self.fmap.print_rate) * \ - self.doc.fields.get(self.fmap.exchange_rate)) / - (1 + cumulated_tax_fraction), self.precision.item[self.fmap.rate]) - - item.amount = flt(item.fields.get(self.fmap.rate) * item.qty, - self.precision.item.amount) - - item.fields[self.fmap.ref_rate] = \ - flt(item.fields.get(self.fmap.rate) / (1 - \ - (item.fields.get(self.fmap.discount) / 100.0)), - self.precision.item[self.fmap.ref_rate]) - - # print item.print_rate, 1+cumulated_tax_fraction, item.rate, item.amount - # print "-"*10 - - def get_current_tax_fraction(self, tax, item_tax_map): - """ - Get tax fraction for calculating tax exclusive amount - from tax inclusive amount - """ - current_tax_fraction = 0 - - if cint(tax.included_in_print_rate): - tax_rate = self._get_tax_rate(tax, item_tax_map) - - if tax.charge_type == "On Net Total": - current_tax_fraction = tax_rate / 100.0 - - elif tax.charge_type == "On Previous Row Amount": - current_tax_fraction = (tax_rate / 100.0) * \ - self.tax_doclist[cint(tax.row_id) - 1]\ - .tax_fraction_for_current_item - - elif tax.charge_type == "On Previous Row Total": - current_tax_fraction = (tax_rate / 100.0) * \ - self.tax_doclist[cint(tax.row_id) - 1]\ - .grand_total_fraction_for_current_item - - # print tax.account_head, tax_rate, current_tax_fraction - - return current_tax_fraction - - def _load_item_tax_rate(self, item_tax_rate): - if not item_tax_rate: - return {} - - return json.loads(item_tax_rate) - - def _get_tax_rate(self, tax, item_tax_map): - if item_tax_map.has_key(tax.account_head): - return flt(item_tax_map.get(tax.account_head), self.precision.tax.rate) - else: - return tax.rate - - def cleanup(self): - def _del(f, doc): - if f in doc.fields: - del doc.fields[f] - elif self.fmap.get(f) and self.fmap.get(f) in doc.fields: - del doc.fields[self.fmap.get(f)] - - for f in ["taxes_and_charges_total_print", "rounded_total_in_words_print", - "rounded_total_print", "rounded_total_in_words", "rounded_total"]: - _del(f, self.doc) - - for f in ["grand_total_print_for_current_item", "tax_amount_print", - "grand_total_for_current_item", "tax_amount_for_current_item", - "total_print"]: - for doc in self.doclist.get({"parentfield": self.fmap.taxes_and_charges}): - _del(f, doc) - - for f in ["item_tax_amount"]: - for doc in self.doclist.get({"parentfield": self.item_table_field}): - _del(f, doc) - diff --git a/controllers/transaction_controller.py b/controllers/transaction_controller.py deleted file mode 100644 index 3e4d62e291..0000000000 --- a/controllers/transaction_controller.py +++ /dev/null @@ -1,123 +0,0 @@ -# ERPNext - web based ERP (http://erpnext.com) -# Copyright (C) 2012 Web Notes Technologies Pvt Ltd -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from __future__ import unicode_literals -import webnotes -import webnotes.model -from webnotes import _, _dict -from webnotes.utils import cint -import json - -from webnotes.model.controller import DocListController - -class TransactionController(DocListController): - def __init__(self, doc, doclist): - super(TransactionController, self).__init__(doc, doclist) - self.cur_docstatus = cint(webnotes.conn.get_value(self.doc.doctype, - self.doc.name, "docstatus")) - - @property - def precision(self): - if not hasattr(self, "_precision"): - self._precision = _dict() - self._precision.main = self.meta.get_precision_map() - self._precision.item = self.meta.get_precision_map(parentfield = \ - self.item_table_field) - if self.meta.get_field(self.fmap.taxes_and_charges): - self._precision.tax = self.meta.get_precision_map(parentfield = \ - self.fmap.taxes_and_charges) - return self._precision - - @property - def item_doclist(self): - if not hasattr(self, "_item_doclist"): - self._item_doclist = self.doclist.get({"parentfield": self.item_table_field}) - return self._item_doclist - - @property - def tax_doclist(self): - if not hasattr(self, "_tax_doclist"): - self._tax_doclist = self.doclist.get( - {"parentfield": self.fmap.taxes_and_charges}) - return self._tax_doclist - - @property - def stock_items(self): - if not hasattr(self, "_stock_items"): - item_codes = list(set(item.item_code for item in self.item_doclist)) - self._stock_items = [r[0] for r in webnotes.conn.sql("""select name - from `tabItem` where name in (%s) and is_stock_item='Yes'""" % \ - (", ".join((["%s"]*len(item_codes))),), item_codes)] - - return self._stock_items - - @property - def fmap(self): - if not hasattr(self, "_fmap"): - if self.doc.doctype in ["Lead", "Quotation", "Sales Order", "Sales Invoice", - "Delivery Note"]: - self._fmap = webnotes._dict( { - "exchange_rate": "conversion_rate", - "taxes_and_charges": "other_charges", - "taxes_and_charges_master": "charge", - "taxes_and_charges_total": "other_charges_total", - "net_total_print": "net_total_print", - "grand_total_print": "grand_total_export", - "grand_total_in_words": "grand_total_in_words", - "grand_total_in_words_print": "grand_total_in_words_print", - "rounded_total_print": "rounded_total_export", - "rounded_total_in_words": "in_words", - "rounded_total_in_words_print": "in_words_export", - "print_ref_rate": "ref_rate", - "discount": "adj_rate", - "print_rate": "export_rate", - "print_amount": "export_amount", - "ref_rate": "base_ref_rate", - "rate": "basic_rate", - - "plc_exchange_rate": "plc_conversion_rate", - "tax_calculation": "other_charges_calculation", - "cost_center": "cost_center_other_charges", - }) - else: - self._fmap = webnotes._dict({ - "exchange_rate": "conversion_rate", - "taxes_and_charges": "purchase_tax_details", - "taxes_and_charges_master": "purchase_other_charges", - "taxes_and_charges_total": "total_tax", - "net_total_print": "net_total_import", - "grand_total_print": "grand_total_import", - "grand_total_in_words": "in_words", - "grand_total_in_words_print": "in_words_import", - "rounded_total_print": "rounded_total_print", - "rounded_total_in_words": "rounded_total_in_words", - "rounded_total_in_words_print": "rounded_total_in_words_print", - "print_ref_rate": "import_ref_rate", - "discount": "discount_rate", - "print_rate": "import_rate", - "print_amount": "import_amount", - "ref_rate": "purchase_ref_rate", - "rate": "purchase_rate", - - "valuation_tax_amount": "item_tax_amount" - }) - - if self.doc.doctype == "Purchase Invoice": - self._fmap.update({ - "rate": "rate" - }) - - return self._fmap or webnotes._dict() \ No newline at end of file diff --git a/patches/february_2013/remove_account_utils_folder.py b/patches/february_2013/remove_account_utils_folder.py new file mode 100644 index 0000000000..718826baa0 --- /dev/null +++ b/patches/february_2013/remove_account_utils_folder.py @@ -0,0 +1,6 @@ +def execute(): + from webnotes.utils import get_base_path + import shutil + import os + + shutil.rmtree(os.path.join(get_base_path(), "app", "accounts", "utils")) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 80cdb4df11..cf9c189cb4 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -165,4 +165,5 @@ patch_list = [ "patches.february_2013.payment_reconciliation_reset_values", "patches.february_2013.remove_sales_order_pending_items", "patches.february_2013.account_negative_balance", + "patches.february_2013.remove_account_utils_folder", ] \ No newline at end of file From 627086937418ab4a569b943add017f1951fac0c5 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 6 Feb 2013 15:42:41 +0530 Subject: [PATCH 3/4] fix in remove account utils folder patch --- patches/february_2013/remove_account_utils_folder.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/patches/february_2013/remove_account_utils_folder.py b/patches/february_2013/remove_account_utils_folder.py index 718826baa0..5d0313bbfb 100644 --- a/patches/february_2013/remove_account_utils_folder.py +++ b/patches/february_2013/remove_account_utils_folder.py @@ -3,4 +3,6 @@ def execute(): import shutil import os - shutil.rmtree(os.path.join(get_base_path(), "app", "accounts", "utils")) \ No newline at end of file + utils_path = os.path.join(get_base_path(), "app", "accounts", "utils") + if os.path.exists(utils_path): + shutil.rmtree(utils_path) \ No newline at end of file From 8c713e7f0c6c8cfa49a0587f01bfcb99f07224d0 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 6 Feb 2013 16:10:48 +0530 Subject: [PATCH 4/4] added holidy_block_list_allow --- hr/doctype/employee/employee.py | 16 +++++ .../holiday_block_list/holiday_block_list.py | 9 ++- .../holiday_block_list/holiday_block_list.txt | 23 +++++- .../holiday_block_list_allow/__init__.py | 0 .../holiday_block_list_allow.py | 8 +++ .../holiday_block_list_allow.txt | 35 ++++++++++ .../leave_application/leave_application.py | 27 ++----- .../test_leave_application.py | 70 +++++++++++++------ public/js/toolbar.js | 2 +- 9 files changed, 144 insertions(+), 46 deletions(-) create mode 100644 hr/doctype/holiday_block_list_allow/__init__.py create mode 100644 hr/doctype/holiday_block_list_allow/holiday_block_list_allow.py create mode 100644 hr/doctype/holiday_block_list_allow/holiday_block_list_allow.txt diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index 4360c7e7ac..d08da1acba 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -70,6 +70,11 @@ class DocType: webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id) webnotes.conn.set_default("employee_name", self.doc.employee_name, self.doc.user_id) webnotes.conn.set_default("company", self.doc.company, self.doc.user_id) + + # add employee role if missing + if not "Employee" in webnotes.conn.sql_list("""select role from tabUserRole + where parent=%s""", self.doc.user_id): + webnotes.get_obj("Profile", self.doc.user_id).add_role("Employee") def validate_date(self): import datetime @@ -134,4 +139,15 @@ test_records = [[{ "status": "Active", "company": "_Test Company", "user_id": "test@erpnext.com" +}], +[{ + "doctype":"Employee", + "employee_name": "_Test Employee 1", + "naming_series": "_T-Employee-", + "date_of_joining": "2010-01-01", + "date_of_birth": "1980-01-01", + "gender": "Male", + "status": "Active", + "company": "_Test Company", + "user_id": "test1@erpnext.com" }]] \ No newline at end of file diff --git a/hr/doctype/holiday_block_list/holiday_block_list.py b/hr/doctype/holiday_block_list/holiday_block_list.py index 4ebe49e188..619f373e37 100644 --- a/hr/doctype/holiday_block_list/holiday_block_list.py +++ b/hr/doctype/holiday_block_list/holiday_block_list.py @@ -31,4 +31,11 @@ test_records = [[{ "parentfield": "holiday_block_list_dates", "block_date": "2013-01-02", "reason": "First work day" - }]] \ No newline at end of file + }, { + "doctype": "Holiday Block List Allow", + "parent": "_Test Holiday Block List", + "parenttype": "Holiday Block List", + "parentfield": "holiday_block_list_allowed", + "allow_user": "test1@erpnext.com", + } + ]] \ No newline at end of file diff --git a/hr/doctype/holiday_block_list/holiday_block_list.txt b/hr/doctype/holiday_block_list/holiday_block_list.txt index 732e783b35..31b2f98ee1 100644 --- a/hr/doctype/holiday_block_list/holiday_block_list.txt +++ b/hr/doctype/holiday_block_list/holiday_block_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-04 15:31:29", "docstatus": 0, - "modified": "2013-02-04 15:38:57", + "modified": "2013-02-06 14:39:09", "modified_by": "Administrator", "owner": "Administrator" }, @@ -53,6 +53,13 @@ "options": "Fiscal Year", "reqd": 1 }, + { + "description": "Stop users from making Leave Applications on following days.", + "doctype": "DocField", + "fieldname": "block_days", + "fieldtype": "Section Break", + "label": "Block Days" + }, { "doctype": "DocField", "fieldname": "holiday_block_list_dates", @@ -60,6 +67,20 @@ "label": "Holiday Block List Dates", "options": "Holiday Block List Date" }, + { + "description": "Allow the following users to make Leave Applications for block days.", + "doctype": "DocField", + "fieldname": "allow_list", + "fieldtype": "Section Break", + "label": "Allow Users" + }, + { + "doctype": "DocField", + "fieldname": "holiday_block_list_allowed", + "fieldtype": "Table", + "label": "Holiday Block List Allowed", + "options": "Holiday Block List Allow" + }, { "doctype": "DocPerm" } diff --git a/hr/doctype/holiday_block_list_allow/__init__.py b/hr/doctype/holiday_block_list_allow/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/hr/doctype/holiday_block_list_allow/holiday_block_list_allow.py b/hr/doctype/holiday_block_list_allow/holiday_block_list_allow.py new file mode 100644 index 0000000000..928aa9ff9f --- /dev/null +++ b/hr/doctype/holiday_block_list_allow/holiday_block_list_allow.py @@ -0,0 +1,8 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/hr/doctype/holiday_block_list_allow/holiday_block_list_allow.txt b/hr/doctype/holiday_block_list_allow/holiday_block_list_allow.txt new file mode 100644 index 0000000000..bdbd2a0186 --- /dev/null +++ b/hr/doctype/holiday_block_list_allow/holiday_block_list_allow.txt @@ -0,0 +1,35 @@ +[ + { + "creation": "2013-02-06 14:31:03", + "docstatus": 0, + "modified": "2013-02-06 14:31:03", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "DocType", + "istable": 1, + "module": "HR", + "name": "__common__" + }, + { + "doctype": "DocField", + "fieldname": "allow_user", + "fieldtype": "Link", + "label": "Allow User", + "name": "__common__", + "options": "Profile", + "parent": "Holiday Block List Allow", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0, + "width": "200px" + }, + { + "doctype": "DocType", + "name": "Holiday Block List Allow" + }, + { + "doctype": "DocField" + } +] \ No newline at end of file diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py index 8c7124e92d..cab8f17b69 100755 --- a/hr/doctype/leave_application/leave_application.py +++ b/hr/doctype/leave_application/leave_application.py @@ -53,6 +53,8 @@ class DocType: if department: block_list = webnotes.conn.get_value("Department", department, "holiday_block_list") if block_list: + if self.is_user_in_allow_list(block_list): + return for d in webnotes.conn.sql("""select block_date, reason from `tabHoliday Block List Date` where parent=%s""", block_list, as_dict=1): block_date = getdate(d.block_date) @@ -61,6 +63,10 @@ class DocType: + ": " + formatdate(d.block_date) + _(" Reason: ") + d.reason) raise LeaveDayBlockedError + def is_user_in_allow_list(self, block_list): + return webnotes.session.user in webnotes.conn.sql_list("""select allow_user + from `tabHoliday Block List Allow` where parent=%s""", block_list) + def get_holidays(self): tot_hol = webnotes.conn.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1 where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name @@ -147,23 +153,4 @@ def get_approver_list(): def is_lwp(leave_type): lwp = webnotes.conn.sql("select is_lwp from `tabLeave Type` where name = %s", leave_type) - return lwp and cint(lwp[0][0]) or 0 - -test_records = [ - [{ - "doctype": "Leave Allocation", - "leave_type": "_Test Leave Type", - "fiscal_year": "_Test Fiscal Year", - "employee":"_T-Employee-0001", - "new_leaves_allocated": 15, - "docstatus": 1 - }], - [{ - "doctype": "Leave Application", - "leave_type": "_Test Leave Type", - "from_date": "2013-05-01", - "to_date": "2013-05-05", - "posting_date": "2013-01-02", - "fiscal_year": "_Test Fiscal Year", - "employee": "_T-Employee-0001" - }]] \ No newline at end of file + return lwp and cint(lwp[0][0]) or 0 \ No newline at end of file diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py index fac36857c4..e485289ffa 100644 --- a/hr/doctype/leave_application/test_leave_application.py +++ b/hr/doctype/leave_application/test_leave_application.py @@ -1,26 +1,50 @@ - import sys - import unittest +import sys +import unittest - from hr.doctype.leave_application.leave_application import test_records, LeaveDayBlockedError +from hr.doctype.leave_application.leave_application import LeaveDayBlockedError - class TestLeaveApplication(unittest.TestCase): - def setUp(self): - from webnotes.test_runner import make_test_records - make_test_records("Leave Application") - - def test_block_list(self): - import webnotes - webnotes.conn.set_value("Employee", "_T-Employee-0001", "department", - "_Test Department with Block List") - - application = webnotes.model_wrapper(test_records[1]) - application.doc.from_date = "2013-01-01" - application.doc.to_date = "2013-01-05" - self.assertRaises(LeaveDayBlockedError, application.insert) - - if __name__=="__main__": - sys.path.extend(["app", "lib"]) +class TestLeaveApplication(unittest.TestCase): + def test_block_list(self): import webnotes - webnotes.connect() - unittest.main() - \ No newline at end of file + webnotes.conn.set_value("Employee", "_T-Employee-0001", "department", + "_Test Department with Block List") + + application = webnotes.model_wrapper(test_records[1]) + application.doc.from_date = "2013-01-01" + application.doc.to_date = "2013-01-05" + self.assertRaises(LeaveDayBlockedError, application.insert) + + webnotes.session.user = "test1@erpnext.com" + webnotes.get_obj("Profile", "test1@erpnext.com").add_role("HR User") + self.assertTrue(application.insert()) + + +test_records = [ + [{ + "doctype": "Leave Allocation", + "leave_type": "_Test Leave Type", + "fiscal_year": "_Test Fiscal Year", + "employee":"_T-Employee-0001", + "new_leaves_allocated": 15, + "docstatus": 1 + }], + [{ + "doctype": "Leave Application", + "leave_type": "_Test Leave Type", + "from_date": "2013-05-01", + "to_date": "2013-05-05", + "posting_date": "2013-01-02", + "fiscal_year": "_Test Fiscal Year", + "employee": "_T-Employee-0001" + }]] + +if __name__=="__main__": + sys.path.extend(["app", "lib"]) + import webnotes + webnotes.connect() + + from webnotes.test_runner import make_test_records + make_test_records("Leave Application") + + unittest.main() + diff --git a/public/js/toolbar.js b/public/js/toolbar.js index fd7109ad89..8fd3d98330 100644 --- a/public/js/toolbar.js +++ b/public/js/toolbar.js @@ -52,7 +52,7 @@ erpnext.toolbar.add_modules = function() { $('').prependTo('.navbar .nav:first');