diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 69019252479..0fdf7031ab3 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.35' +__version__ = '11.1.38' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 92342f4d7c8..214cdabe3a7 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -425,8 +425,9 @@ class JournalEntry(AccountsController): pay_to_recd_from = frappe.db.get_value(d.party_type, d.party, "customer_name" if d.party_type=="Customer" else "supplier_name") - party_amount += (d.debit_in_account_currency or d.credit_in_account_currency) - party_account_currency = d.account_currency + if pay_to_recd_from and pay_to_recd_from == d.party: + party_amount += (d.debit_in_account_currency or d.credit_in_account_currency) + party_account_currency = d.account_currency elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]: bank_amount += (d.debit_in_account_currency or d.credit_in_account_currency) diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india.js b/erpnext/accounts/doctype/sales_invoice/regional/india.js index 5fec3ba6d32..c8305e325f6 100644 --- a/erpnext/accounts/doctype/sales_invoice/regional/india.js +++ b/erpnext/accounts/doctype/sales_invoice/regional/india.js @@ -21,7 +21,7 @@ frappe.ui.form.on("Sales Invoice", { if(frm.doc.docstatus == 1 && !frm.is_dirty() && !frm.doc.is_return && !frm.doc.ewaybill) { - frm.add_custom_button('Generate e-Way Bill JSON', () => { + frm.add_custom_button('e-Way Bill JSON', () => { var w = window.open( frappe.urllib.get_full_url( "/api/method/erpnext.regional.india.utils.generate_ewb_json?" diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index d7aa0c0d191..192b6d7be38 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -46,6 +46,8 @@ var range2 = report.columns[12].label; var range3 = report.columns[13].label; var range4 = report.columns[14].label; + var range5 = report.columns[15].label; + var range6 = report.columns[16].label; %} {% if(balance_row) { %} @@ -56,8 +58,10 @@ - - + + + + @@ -67,16 +71,20 @@ + + - + + + @@ -86,6 +94,8 @@ + + @@ -95,6 +105,8 @@ + + diff --git a/erpnext/accounts/report/financial_statements.html b/erpnext/accounts/report/financial_statements.html index 449fb845d74..cb853fd1dc4 100644 --- a/erpnext/accounts/report/financial_statements.html +++ b/erpnext/accounts/report/financial_statements.html @@ -39,7 +39,7 @@ - {% for(var j=0, k=data.length; j - {% for(var i=0, l=data.length; i {% if(data[i].posting_date) { %} diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 1f1f738ff00..4bea0978025 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -127,7 +127,9 @@ def get_gl_entries(filters): order_by_statement = "order by posting_date, voucher_type, voucher_no" if filters.get("group_by") == _("Group by Voucher (Consolidated)"): - group_by_statement = "group by voucher_type, voucher_no, account, cost_center" + group_by_statement = """group by voucher_type, voucher_no, account, + cost_center, against_voucher_type, against_voucher, posting_date""" + select_fields = """, sum(debit) as debit, sum(credit) as credit, sum(debit_in_account_currency) as debit_in_account_currency, sum(credit_in_account_currency) as credit_in_account_currency""" diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index e8b19b40249..5d3253a552d 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -102,7 +102,9 @@ def get_conditions(filters): ("customer", " and `tabSales Invoice`.customer = %(customer)s"), ("item_code", " and `tabSales Invoice Item`.item_code = %(item_code)s"), ("from_date", " and `tabSales Invoice`.posting_date>=%(from_date)s"), - ("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s")): + ("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s"), + ("company_gstin", " and `tabSales Invoice`.company_gstin = %(company_gstin)s"), + ("invoice_type", " and `tabSales Invoice`.invoice_type = %(invoice_type)s")): if filters.get(opts[0]): conditions += opts[1] diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py index b0bd4c6a680..86094896154 100644 --- a/erpnext/healthcare/doctype/lab_test/lab_test.py +++ b/erpnext/healthcare/doctype/lab_test/lab_test.py @@ -300,11 +300,15 @@ def insert_lab_test_to_medical_record(doc): elif doc.special_test_items: item = doc.special_test_items[0] - table_row = item.lab_test_particulars +" "+ item.result_value + + if item.lab_test_particulars and item.result_value: + table_row = item.lab_test_particulars +" "+ item.result_value elif doc.sensitivity_test_items: item = doc.sensitivity_test_items[0] - table_row = item.antibiotic +" "+ item.antibiotic_sensitivity + + if item.antibiotic and item.antibiotic_sensitivity: + table_row = item.antibiotic +" "+ item.antibiotic_sensitivity if table_row: subject += "
"+table_row diff --git a/erpnext/hooks.py b/erpnext/hooks.py index fb24aa93892..9b18e5e1f3a 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -13,8 +13,6 @@ source_link = "https://github.com/frappe/erpnext" develop_version = '12.x.x-develop' -error_report_email = "support@erpnext.com" - app_include_js = "assets/js/erpnext.min.js" app_include_css = "assets/css/erpnext.css" web_include_js = "assets/js/erpnext-web.min.js" diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index ca49ceac006..c9dfe4c56f8 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -122,11 +122,42 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "1", - "depends_on": "eval:doc.type == \"Earning\"", "fetch_if_empty": 0, - "fieldname": "is_tax_applicable", - "fieldtype": "Check", + "fieldname": "description", + "fieldtype": "Small Text", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Description", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_4", + "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -134,7 +165,6 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Is Tax Applicable", "length": 0, "no_copy": 0, "permlevel": 0, @@ -225,8 +255,10 @@ "bold": 0, "collapsible": 0, "columns": 0, + "default": "1", + "depends_on": "eval:doc.type == \"Earning\"", "fetch_if_empty": 0, - "fieldname": "do_not_include_in_total", + "fieldname": "is_tax_applicable", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, @@ -235,7 +267,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Do not include in total", + "label": "Is Tax Applicable", "length": 0, "no_copy": 0, "permlevel": 0, @@ -258,6 +290,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "is_tax_applicable", "fetch_if_empty": 0, "fieldname": "deduct_full_tax_on_selected_payroll_date", "fieldtype": "Check", @@ -292,39 +325,7 @@ "collapsible": 0, "columns": 0, "fetch_if_empty": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "disabled", + "fieldname": "round_to_the_nearest_integer", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, @@ -333,40 +334,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Disabled", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "description", - "fieldtype": "Small Text", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Description", + "label": "Round to the Nearest Integer", "length": 0, "no_copy": 0, "permlevel": 0, @@ -416,6 +384,72 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "do_not_include_in_total", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Do Not Include in Total", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "disabled", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Disabled", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -854,6 +888,40 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.amount_based_on_formula!==1", + "fetch_if_empty": 0, + "fieldname": "amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -895,7 +963,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:doc.amount_based_on_formula!==0", + "depends_on": "amount_based_on_formula", "fetch_if_empty": 0, "fieldname": "formula", "fieldtype": "Code", @@ -922,40 +990,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.amount_based_on_formula!==1", - "fetch_if_empty": 0, - "fieldname": "amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1034,7 +1068,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-05-13 12:55:55.424370", + "modified": "2019-06-05 11:19:15.926608", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index cd423499b79..ffd786836a5 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -443,7 +443,7 @@ class SalarySlip(TransactionBase): else: component_row.additional_amount = amount - if not overwrite: + if not overwrite and component_row.default_amount: amount += component_row.default_amount component_row.amount = amount @@ -616,6 +616,10 @@ class SalarySlip(TransactionBase): elif not row.amount: amount = row.default_amount + row.additional_amount + # apply rounding + if frappe.get_cached_value("Salary Component", row.salary_component, "round_to_the_nearest_integer"): + amount, additional_amount = rounded(amount), rounded(additional_amount) + return amount, additional_amount def calculate_unclaimed_taxable_benefits(self, payroll_period): diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py index b333f4f49e4..16a75f473f4 100644 --- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py @@ -211,7 +211,7 @@ class TestSalarySlip(unittest.TestCase): tax_paid = get_tax_paid_in_period(employee) # total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200 - annual_tax = 113567.79 + annual_tax = 113568 try: self.assertEqual(tax_paid, annual_tax) except AssertionError: @@ -250,7 +250,7 @@ class TestSalarySlip(unittest.TestCase): # total taxable income 416000, 166000 @ 5% ie. 8300 try: - self.assertEqual(tax_paid, 88607.79) + self.assertEqual(tax_paid, 88608) except AssertionError: print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n") raise @@ -265,7 +265,7 @@ class TestSalarySlip(unittest.TestCase): # total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200 tax_paid = get_tax_paid_in_period(employee) try: - self.assertEqual(tax_paid, 121211.48) + self.assertEqual(tax_paid, 121211) except AssertionError: print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n") raise @@ -443,7 +443,8 @@ def make_deduction_salary_component(setup=False, test_tax=False): "type": "Deduction", "amount_based_on_formula": 1, "depends_on_payment_days": 0, - "variable_based_on_taxable_salary": 1 + "variable_based_on_taxable_salary": 1, + "round_to_the_nearest_integer": 1 } ] if not test_tax: @@ -453,7 +454,8 @@ def make_deduction_salary_component(setup=False, test_tax=False): "condition": 'employment_type=="Intern"', "formula": 'base*.1', "type": "Deduction", - "amount_based_on_formula": 1 + "amount_based_on_formula": 1, + "round_to_the_nearest_integer": 1 }) if setup or test_tax: make_salary_component(data, test_tax) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 9b5cc7f0ab0..b6083ef44c0 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -600,4 +600,5 @@ erpnext.patches.v11_1.set_missing_title_for_quotation execute:frappe.delete_doc("Report", "Inactive Items") erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v11_1.update_bank_transaction_status -erpnext.patches.v11_1.renamed_delayed_item_report \ No newline at end of file +erpnext.patches.v11_1.renamed_delayed_item_report +erpnext.patches.v11_1.set_missing_opportunity_from \ No newline at end of file diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py index 992454ac7c1..51358e95458 100644 --- a/erpnext/patches/v11_0/update_total_qty_field.py +++ b/erpnext/patches/v11_0/update_total_qty_field.py @@ -40,7 +40,7 @@ def execute(): # This is probably never used anywhere else as of now, but should be values = [] for d in batch_transactions: - values.append("('{}', {})".format(d.parent, d.qty)) + values.append("('{}', {})".format(frappe.db.escape(d.parent), d.qty)) conditions = ",".join(values) frappe.db.sql(""" INSERT INTO `tab{}` (name, total_qty) VALUES {} diff --git a/erpnext/patches/v11_1/set_missing_opportunity_from.py b/erpnext/patches/v11_1/set_missing_opportunity_from.py new file mode 100644 index 00000000000..cb444b2e5dd --- /dev/null +++ b/erpnext/patches/v11_1/set_missing_opportunity_from.py @@ -0,0 +1,17 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + + frappe.reload_doctype("Opportunity") + if frappe.db.has_column("Opportunity", "enquiry_from"): + frappe.db.sql(""" UPDATE `tabOpportunity` set opportunity_from = enquiry_from + where ifnull(opportunity_from, '') = '' and ifnull(enquiry_from, '') != ''""") + + if frappe.db.has_column("Opportunity", "lead") and frappe.db.has_column("Opportunity", "enquiry_from"): + frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = lead + where enquiry_from = 'Lead' and ifnull(party_name, '') = '' and ifnull(lead, '') != ''""") + + if frappe.db.has_column("Opportunity", "customer") and frappe.db.has_column("Opportunity", "enquiry_from"): + frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = customer + where enquiry_from = 'Customer' and ifnull(party_name, '') = '' and ifnull(customer, '') != ''""") diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js index c1a9c448b41..a4733b93207 100644 --- a/erpnext/projects/doctype/task/task.js +++ b/erpnext/projects/doctype/task/task.js @@ -19,43 +19,38 @@ frappe.ui.form.on("Task", { }, refresh: function(frm) { - frm.fields_dict['parent_task'].get_query = function() { + frm.fields_dict['parent_task'].get_query = function () { return { filters: { "is_group": 1, } } } - if(!frm.is_group){ - var doc = frm.doc; - if(doc.__islocal) { - if(!frm.doc.exp_end_date) { - frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7)); - } - } - if(!doc.__islocal) { - if(frappe.model.can_read("Timesheet")) { - frm.add_custom_button(__("Timesheet"), function() { - frappe.route_options = {"project": doc.project, "task": doc.name} + if (!frm.doc.is_group) { + if (!frm.is_new()) { + if (frappe.model.can_read("Timesheet")) { + frm.add_custom_button(__("Timesheet"), () => { + frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name } frappe.set_route("List", "Timesheet"); }, __("View"), true); } - if(frappe.model.can_read("Expense Claim")) { - frm.add_custom_button(__("Expense Claims"), function() { - frappe.route_options = {"project": doc.project, "task": doc.name} + + if (frappe.model.can_read("Expense Claim")) { + frm.add_custom_button(__("Expense Claims"), () => { + frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name } frappe.set_route("List", "Expense Claim"); }, __("View"), true); } - if(frm.perm[0].write) { - if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") { - frm.add_custom_button(__("Close"), function() { + if (frm.perm[0].write) { + if (!["Closed", "Cancelled"].includes(frm.doc.status)) { + frm.add_custom_button(__("Close"), () => { frm.set_value("status", "Closed"); frm.save(); }); } else { - frm.add_custom_button(__("Reopen"), function() { + frm.add_custom_button(__("Reopen"), () => { frm.set_value("status", "Open"); frm.save(); }); diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 9077b79b78c..015aefb8b35 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -367,6 +367,20 @@ def generate_ewb_json(dt, dn): frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(doc_name, frappe.utils.random_string(5)) +@frappe.whitelist() +def get_gstins_for_company(company): + company_gstins =[] + if company: + company_gstins = frappe.db.sql("""select + distinct `tabAddress`.gstin + from + `tabAddress`, `tabDynamic Link` + where + `tabDynamic Link`.parent = `tabAddress`.name and + `tabDynamic Link`.parenttype = 'Address' and + `tabDynamic Link`.link_doctype = 'Company' and + `tabDynamic Link`.link_name = '{0}'""".format(company)) + return company_gstins def get_address_details(data, doc, company_address, billing_address): data.fromPincode = validate_pincode(company_address.pincode, 'Company Address') diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml index b725b964f2e..9a588d1666b 100644 --- a/erpnext/regional/italy/e-invoice.xml +++ b/erpnext/regional/italy/e-invoice.xml @@ -118,7 +118,7 @@ {{ doc.type_of_document }} - EUR + {{ doc.currency }} {{ doc.posting_date }} {{ doc.unamended_name }} {%- if doc.stamp_duty %} diff --git a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js index 1ece14b713b..3a0f0c966d6 100644 --- a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js +++ b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.js @@ -3,5 +3,31 @@ /* eslint-disable */ {% include "erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js" %} +{% include "erpnext/regional/report/india_gst_common/india_gst_common.js" %} -frappe.query_reports["GST Itemised Sales Register"] = frappe.query_reports["Item-wise Sales Register"] \ No newline at end of file +let filters = frappe.query_reports["Item-wise Sales Register"]["filters"]; + +// Add GSTIN filter +filters = filters.concat({ + "fieldname":"company_gstin", + "label": __("Company GSTIN"), + "fieldtype": "Select", + "placeholder":"Company GSTIN", + "options": [""], + "width": "80" +}, { + "fieldname":"invoice_type", + "label": __("Invoice Type"), + "fieldtype": "Select", + "placeholder":"Invoice Type", + "options": ["", "Regular", "SEZ", "Export", "Deemed Export"] +}); + +// Handle company on change +for (var i = 0; i < filters.length; ++i) { + if (filters[i].fieldname === 'company') { + filters[i].on_change = fetch_gstins; + } +} + +frappe.query_reports["GST Itemised Sales Register"] = { "filters": filters, "onload": fetch_gstins }; diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js index df0ef253158..dcb81cb087e 100644 --- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js +++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js @@ -2,6 +2,8 @@ // For license information, please see license.txt /* eslint-disable */ +{% include "erpnext/regional/report/india_gst_common/india_gst_common.js" %} + frappe.query_reports["HSN-wise-summary of outward supplies"] = { "filters": [ { @@ -10,7 +12,8 @@ frappe.query_reports["HSN-wise-summary of outward supplies"] = { "fieldtype": "Link", "options": "Company", "reqd": 1, - "default": frappe.defaults.get_user_default("Company") + "default": frappe.defaults.get_user_default("Company"), + "on_change": fetch_gstins }, { "fieldname":"gst_hsn_code", @@ -18,6 +21,17 @@ frappe.query_reports["HSN-wise-summary of outward supplies"] = { "fieldtype": "Link", "options": "GST HSN Code", "width": "80" + }, + { + "fieldname":"company_gstin", + "label": __("Company GSTIN"), + "fieldtype": "Select", + "placeholder":"Company GSTIN", + "options": [""], + "width": "80" } - ] -} + ], + onload: (report) => { + fetch_gstins(report); + } +}; diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py index 165458c4d5a..e938e29c440 100644 --- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py +++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py @@ -87,7 +87,8 @@ def get_conditions(filters): conditions = "" for opts in (("company", " and company=%(company)s"), - ("gst_hsn_code", " and gst_hsn_code=%(gst_hsn_code)s")): + ("gst_hsn_code", " and gst_hsn_code=%(gst_hsn_code)s"), + ("company_gstin", " and company_gstin=%(company_gstin)s")): if filters.get(opts[0]): conditions += opts[1] @@ -193,7 +194,7 @@ def get_merged_data(columns, data): add_column_index.append(i) for row in data: - if merged_hsn_dict.has_key(row[0]): + if row[0] in merged_hsn_dict: to_add_row = merged_hsn_dict.get(row[0]) # add columns from the add_column_index table diff --git a/erpnext/regional/report/india_gst_common/india_gst_common.js b/erpnext/regional/report/india_gst_common/india_gst_common.js new file mode 100644 index 00000000000..49606013946 --- /dev/null +++ b/erpnext/regional/report/india_gst_common/india_gst_common.js @@ -0,0 +1,21 @@ +function fetch_gstins(report) { + var company_gstins = report.get_filter('company_gstin'); + var company = report.get_filter_value('company'); + if (company) { + frappe.call({ + method:'erpnext.regional.india.utils.get_gstins_for_company', + async: false, + args: { + company: company + }, + callback: function(r) { + r.message.unshift(""); + company_gstins.df.options = r.message; + company_gstins.refresh(); + } + }); + } else { + company_gstins.df.options = [""]; + company_gstins.refresh(); + } +} \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index d1cc22aa2a6..3150d2ba87f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -652,35 +652,36 @@ class StockEntry(StockController): ret = frappe._dict({ 'uom' : item.stock_uom, - 'stock_uom' : item.stock_uom, + 'stock_uom' : item.stock_uom, 'description' : item.description, - 'image' : item.image, + 'image' : item.image, 'item_name' : item.item_name, - 'expense_account' : args.get("expense_account"), - 'cost_center' : get_default_cost_center(args, item, item_group_defaults), - 'qty' : args.get("qty"), + 'cost_center' : get_default_cost_center(args, item, item_group_defaults, self.company), + 'qty' : args.get("qty"), 'transfer_qty' : args.get('qty'), 'conversion_factor' : 1, - 'batch_no' : '', + 'batch_no' : '', 'actual_qty' : 0, 'basic_rate' : 0, - 'serial_no' : '', + 'serial_no' : '', 'has_serial_no' : item.has_serial_no, 'has_batch_no' : item.has_batch_no, 'sample_quantity' : item.sample_quantity }) - for d in [["Account", "expense_account", "default_expense_account"], - ["Cost Center", "cost_center", "cost_center"]]: - company = frappe.db.get_value(d[0], ret.get(d[1]), "company") - if not ret[d[1]] or (company and self.company != company): - ret[d[1]] = frappe.get_cached_value('Company', self.company, d[2]) if d[2] else None # update uom if args.get("uom") and for_update: ret.update(get_uom_details(args.get('item_code'), args.get('uom'), args.get('qty'))) - if not ret["expense_account"]: - ret["expense_account"] = frappe.get_cached_value('Company', self.company, "stock_adjustment_account") + if self.purpose == 'Material Issue': + ret["expense_account"] = (item.get("expense_account") or + item_group_defaults.get("expense_account") or + frappe.get_cached_value('Company', self.company, "default_expense_account")) + + for company_field, field in {'stock_adjustment_account': 'expense_account', + 'cost_center': 'cost_center'}.items(): + if not ret.get(field): + ret[field] = frappe.get_cached_value('Company', self.company, company_field) args['posting_date'] = self.posting_date args['posting_time'] = self.posting_time @@ -1036,8 +1037,7 @@ class StockEntry(StockController): return item_dict def add_to_stock_entry_detail(self, item_dict, bom_no=None): - expense_account, cost_center = frappe.db.get_values("Company", self.company, \ - ["default_expense_account", "cost_center"])[0] + cost_center = frappe.db.get_value("Company", self.company, 'cost_center') for d in item_dict: stock_uom = item_dict[d].get("stock_uom") or frappe.db.get_value("Item", d, "stock_uom") @@ -1051,7 +1051,7 @@ class StockEntry(StockController): se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom se_child.stock_uom = stock_uom se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty")) - se_child.expense_account = item_dict[d].get("expense_account") or expense_account + se_child.expense_account = item_dict[d].get("expense_account") se_child.cost_center = item_dict[d].get("cost_center") or cost_center se_child.allow_alternative_item = item_dict[d].get("allow_alternative_item", 0) se_child.subcontracted_item = item_dict[d].get("main_item_code") diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index d251e49c0a6..851088be948 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -366,7 +366,7 @@ def get_default_deferred_account(args, item, fieldname=None): else: return None -def get_default_cost_center(args, item, item_group): +def get_default_cost_center(args, item, item_group, company=None): cost_center = None if args.get('project'): cost_center = frappe.db.get_value("Project", args.get("project"), "cost_center", cache=True) @@ -377,7 +377,13 @@ def get_default_cost_center(args, item, item_group): else: cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center') - return cost_center or args.get("cost_center") + cost_center = cost_center or args.get("cost_center") + + if (company and cost_center + and frappe.get_cached_value("Cost Center", cost_center, "company") != company): + return None + + return cost_center def get_default_supplier(args, item, item_group): return (item.get("default_supplier")
{%= __(range2) %} {%= __(range3) %} {%= __(range4) %}{%= __(range5) %}{%= __(range6) %} {%= __("Total") %}
{%= __("Total Outstanding") %}{%= format_currency(balance_row[range1]) %}{%= format_number(balance_row[range1], null, 2) %} {%= format_currency(balance_row[range2]) %} {%= format_currency(balance_row[range3]) %} {%= format_currency(balance_row[range4]) %}{%= format_currency(balance_row[range5]) %}{%= format_currency(balance_row[range6]) %} {%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %} {%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %} {%= format_currency(flt(balance_row[("outstanding_amount")]-balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
{%= frappe.datetime.str_to_user(data[i].posting_date) %}