diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index 9876246c47b..e1f1b9b4dfc 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -322,7 +322,9 @@ def apply_internal_priority(pricing_rules, field_set, args):
filtered_rules = []
for field in field_set:
if args.get(field):
- filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
+ # filter function always returns a filter object even if empty
+ # list conversion is necessary to check for an empty result
+ filtered_rules = list(filter(lambda x: x.get(field)==args.get(field), pricing_rules))
if filtered_rules: break
return filtered_rules or pricing_rules
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 58c521f0ffe..7a32c2f63a2 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -413,6 +413,8 @@ class PurchaseInvoice(BuyingController):
self.make_tax_gl_entries(gl_entries)
+ gl_entries = make_regional_gl_entries(gl_entries, self)
+
gl_entries = merge_similar_entries(gl_entries)
self.make_payment_gl_entries(gl_entries)
@@ -1026,6 +1028,10 @@ def get_list_context(context=None):
})
return list_context
+@erpnext.allow_regional
+def make_regional_gl_entries(gl_entries, doc):
+ return gl_entries
+
@frappe.whitelist()
def make_debit_note(source_name, target_doc=None):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index ce26a258fb6..f2eeb327b42 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1105,7 +1105,10 @@ class SalesInvoice(SellingController):
expiry_date=self.posting_date, include_expired_entry=True)
if lp_details and getdate(lp_details.from_date) <= getdate(self.posting_date) and \
(not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)):
- points_earned = cint(eligible_amount/lp_details.collection_factor)
+
+ collection_factor = lp_details.collection_factor if lp_details.collection_factor else 1.0
+ points_earned = cint(eligible_amount/collection_factor)
+
doc = frappe.get_doc({
"doctype": "Loyalty Point Entry",
"company": self.company,
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 7e96b9e237b..58117b68c52 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -8,6 +8,7 @@ from __future__ import unicode_literals
import re
from past.builtins import cmp
import functools
+import math
import frappe, erpnext
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
@@ -42,7 +43,7 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_v
start_date = year_start_date
months = get_months(year_start_date, year_end_date)
- for i in range(months // months_to_add):
+ for i in range(math.ceil(months / months_to_add)):
period = frappe._dict({
"from_date": start_date
})
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index fa4c76f364f..bd2ecfe7c04 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -123,14 +123,14 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
}
if(doc.status != "Closed") {
if (doc.status != "On Hold") {
- if(flt(doc.per_received, 2) < 100 && allow_receipt) {
+ if(flt(doc.per_received) < 100 && allow_receipt) {
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) {
cur_frm.add_custom_button(__('Material to Supplier'),
function() { me.make_stock_entry(); }, __("Transfer"));
}
}
- if(flt(doc.per_billed, 2) < 100)
+ if(flt(doc.per_billed) < 100)
cur_frm.add_custom_button(__('Invoice'),
this.make_purchase_invoice, __('Create'));
diff --git a/erpnext/healthcare/setup.py b/erpnext/healthcare/setup.py
index 2087f49f32f..4813d9d07c8 100644
--- a/erpnext/healthcare/setup.py
+++ b/erpnext/healthcare/setup.py
@@ -195,10 +195,21 @@ def create_sensitivity():
def add_healthcare_service_unit_tree_root():
record = [
- {
- "doctype": "Healthcare Service Unit",
- "healthcare_service_unit_name": "All Healthcare Service Units",
- "is_group": 1
- }
+ {
+ "doctype": "Healthcare Service Unit",
+ "healthcare_service_unit_name": "All Healthcare Service Units",
+ "is_group": 1,
+ "company": get_company()
+ }
]
insert_record(record)
+
+def get_company():
+ company = frappe.defaults.get_defaults().company
+ if company:
+ return company
+ else:
+ company = frappe.get_list("Company", limit=1)
+ if company:
+ return company[0].name
+ return None
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 5de2af51694..5270e7beea2 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -245,7 +245,7 @@ doc_events = {
"on_trash": "erpnext.regional.check_deletion_permission"
},
"Purchase Invoice": {
- "on_submit": "erpnext.regional.india.utils.make_reverse_charge_entries"
+ "validate": "erpnext.regional.india.utils.update_grand_total_for_rcm"
},
"Payment Entry": {
"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status"],
@@ -356,7 +356,8 @@ regional_overrides = {
'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_data': 'erpnext.regional.india.utils.get_itemised_tax_breakup_data',
'erpnext.accounts.party.get_regional_address_details': 'erpnext.regional.india.utils.get_regional_address_details',
'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption',
- 'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period'
+ 'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period',
+ 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.india.utils.make_regional_gl_entries'
},
'United Arab Emirates': {
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data'
diff --git a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json
index a094f8a1971..2a56013e78d 100644
--- a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json
+++ b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json
@@ -1,232 +1,234 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-04-13 17:42:13.516032",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-04-13 17:42:13.516032",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "from_amount",
- "fieldtype": "Currency",
- "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": "From 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "fieldname": "from_amount",
+ "fieldtype": "Currency",
+ "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": "From 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": 1,
+ "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,
- "fieldname": "to_amount",
- "fieldtype": "Currency",
- "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": "To 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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "to_amount",
+ "fieldtype": "Currency",
+ "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": "To 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,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "percent_deduction",
- "fieldtype": "Percent",
- "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": "Percent Deduction",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "default": "0",
+ "fieldname": "percent_deduction",
+ "fieldtype": "Percent",
+ "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": "Percent Deduction",
+ "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": 1,
+ "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,
- "fieldname": "condition",
- "fieldtype": "Code",
- "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": "Condition",
- "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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "condition",
+ "fieldtype": "Code",
+ "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": "Condition",
+ "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,
- "fieldname": "column_break_5",
- "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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_5",
+ "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,
- "fieldname": "html_6",
- "fieldtype": "HTML",
- "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,
- "options": "
Condition Examples
\n\n- Applying tax if employee born between 31-12-1937 and 01-01-1958 (Employees aged 60 to 80)
\nCondition: date_of_birth>date(1937, 12, 31) and date_of_birth<date(1958, 01, 01)
- Applying tax by employee gender
\nCondition: gender==\"Male\"
\n- Applying tax by Salary Component
\nCondition: base > 10000
",
- "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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "html_6",
+ "fieldtype": "HTML",
+ "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,
+ "options": "Condition Examples
\n\n- Applying tax if employee born between 31-12-1937 and 01-01-1958 (Employees aged 60 to 80)
\nCondition: date_of_birth>date(1937, 12, 31) and date_of_birth<date(1958, 01, 01)
- Applying tax by employee gender
\nCondition: gender==\"Male\"
\n- Applying tax by Salary Component
\nCondition: base > 10000
",
+ "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
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-06-19 10:10:23.732132",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Taxable Salary Slab",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2020-06-22 18:16:07.596493",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Taxable Salary Slab",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
"track_seen": 0
}
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index b817ad8d67a..e4a58482bd9 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -1,7 +1,7 @@
from __future__ import unicode_literals
import frappe, re, json
from frappe import _
-from frappe.utils import cstr, flt, date_diff, nowdate
+from frappe.utils import cstr, flt, date_diff, nowdate, round_based_on_smallest_currency_fraction, money_in_words
from erpnext.regional.india import states, state_numbers
from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
from erpnext.controllers.accounts_controller import get_taxes_and_charges
@@ -443,19 +443,23 @@ def generate_ewb_json(dt, dn):
@frappe.whitelist()
def download_ewb_json():
- data = frappe._dict(frappe.local.form_dict)
-
- frappe.local.response.filecontent = json.dumps(data['data'], indent=4, sort_keys=True)
+ data = json.loads(frappe.local.form_dict.data)
+ frappe.local.response.filecontent = json.dumps(data, indent=4, sort_keys=True)
frappe.local.response.type = 'download'
- billList = json.loads(data['data'])['billLists']
+ filename_prefix = 'Bulk'
+ docname = frappe.local.form_dict.docname
+ if docname:
+ if docname.startswith('['):
+ docname = json.loads(docname)
+ if len(docname) == 1:
+ docname = docname[0]
- if len(billList) > 1:
- doc_name = 'Bulk'
- else:
- doc_name = data['docname']
+ if not isinstance(docname, list):
+ # removes characters not allowed in a filename (https://stackoverflow.com/a/38766141/4767738)
+ filename_prefix = re.sub('[^\w_.)( -]', '', docname)
- frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(doc_name, frappe.utils.random_string(5))
+ frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(filename_prefix, frappe.utils.random_string(5))
@frappe.whitelist()
def get_gstins_for_company(company):
@@ -629,6 +633,7 @@ def validate_state_code(state_code, address):
else:
return int(state_code)
+@frappe.whitelist()
def get_gst_accounts(company, account_wise=False):
gst_accounts = frappe._dict()
gst_settings_accounts = frappe.get_all("GST Account",
@@ -647,14 +652,54 @@ def get_gst_accounts(company, account_wise=False):
return gst_accounts
-def make_reverse_charge_entries(doc, method):
+def update_grand_total_for_rcm(doc, method):
+ country = frappe.get_cached_value('Company', doc.company, 'country')
+
+ if country != 'India':
+ return
+
+ if doc.reverse_charge == 'Y':
+ gst_accounts = get_gst_accounts(doc.company)
+ gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
+ + gst_accounts.get('igst_account')
+
+ gst_tax = 0
+ for tax in doc.get('taxes'):
+ if tax.category not in ("Total", "Valuation and Total"):
+ continue
+
+ if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
+ gst_tax += tax.base_tax_amount_after_discount_amount
+
+ doc.taxes_and_charges_added -= gst_tax
+ doc.total_taxes_and_charges -= gst_tax
+
+ update_totals(gst_tax, doc)
+
+def update_totals(gst_tax, doc):
+ doc.grand_total -= gst_tax
+
+ if doc.meta.get_field("rounded_total"):
+ if doc.is_rounded_total_disabled():
+ doc.outstanding_amount = doc.grand_total
+ else:
+ doc.rounded_total = round_based_on_smallest_currency_fraction(doc.grand_total,
+ doc.currency, doc.precision("rounded_total"))
+
+ doc.rounding_adjustment += flt(doc.rounded_total - doc.grand_total,
+ doc.precision("rounding_adjustment"))
+
+ doc.outstanding_amount = doc.base_rounded_total
+
+ doc.in_words = money_in_words(doc.grand_total, doc.currency)
+
+def make_regional_gl_entries(gl_entries, doc):
country = frappe.get_cached_value('Company', doc.company, 'country')
if country != 'India':
return
if doc.reverse_charge == 'Y':
- gl_entries = []
gst_accounts = get_gst_accounts(doc.company)
gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
+ gst_accounts.get('igst_account')
@@ -679,19 +724,4 @@ def make_reverse_charge_entries(doc, method):
}, account_currency, item=tax)
)
- gl_entries.append(doc.get_gl_dict(
- {
- "account": doc.credit_to if doc.doctype == 'Purchase Invoice' else doc.debit_to,
- "cost_center": doc.cost_center,
- "posting_date": doc.posting_date,
- "party_type": 'Supplier',
- "party": doc.supplier,
- "against": tax.account_head,
- "debit": tax.base_tax_amount_after_discount_amount,
- "debit_in_account_currency": tax.base_tax_amount_after_discount_amount \
- if account_currency==doc.company_currency \
- else tax.tax_amount_after_discount_amount
- }, account_currency, item=doc)
- )
-
- make_gl_entries(gl_entries)
\ No newline at end of file
+ return gl_entries
\ No newline at end of file
diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js
index 802c0ba641d..f425acf180a 100644
--- a/erpnext/selling/doctype/quotation/quotation_list.js
+++ b/erpnext/selling/doctype/quotation/quotation_list.js
@@ -3,13 +3,15 @@ frappe.listview_settings['Quotation'] = {
"company", "currency", 'valid_till'],
onload: function(listview) {
- listview.page.fields_dict.quotation_to.get_query = function() {
- return {
- "filters": {
- "name": ["in", ["Customer", "Lead"]],
- }
+ if (listview.page.fields_dict.quotation_to) {
+ listview.page.fields_dict.quotation_to.get_query = function() {
+ return {
+ "filters": {
+ "name": ["in", ["Customer", "Lead"]],
+ }
+ };
};
- };
+ }
},
get_indicator: function(doc) {
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index be736d2d9d1..14cacf37bb6 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -202,8 +202,6 @@ cur_frm.cscript.change_abbr = function() {
if(r.exc) {
frappe.msgprint(__("There were errors."));
return;
- } else {
- cur_frm.set_value("abbr", args.new_abbr);
}
dialog.hide();
cur_frm.refresh();
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index bc27f40f560..335cad3598b 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -400,8 +400,6 @@ def replace_abbr(company, old, new):
for dt in ["Warehouse", "Account", "Cost Center", "Department",
"Sales Taxes and Charges Template", "Purchase Taxes and Charges Template"]:
_rename_records(dt)
- frappe.db.commit()
-
def get_name_with_abbr(name, company):
company_abbr = frappe.get_cached_value('Company', company, "abbr")
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index a091ac7fae9..c8424f13e12 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -143,7 +143,7 @@ class Batch(Document):
@frappe.whitelist()
-def get_batch_qty(batch_no=None, warehouse=None, item_code=None):
+def get_batch_qty(batch_no=None, warehouse=None, item_code=None, posting_date=None, posting_time=None):
"""Returns batch actual qty if warehouse is passed,
or returns dict of qty by warehouse if warehouse is None
@@ -155,9 +155,14 @@ def get_batch_qty(batch_no=None, warehouse=None, item_code=None):
out = 0
if batch_no and warehouse:
+ cond = ""
+ if posting_date and posting_time:
+ cond = " and timestamp(posting_date, posting_time) <= timestamp('{0}', '{1}')".format(posting_date,
+ posting_time)
+
out = float(frappe.db.sql("""select sum(actual_qty)
from `tabStock Ledger Entry`
- where warehouse=%s and batch_no=%s""",
+ where warehouse=%s and batch_no=%s {0}""".format(cond),
(warehouse, batch_no))[0][0] or 0)
if batch_no and not warehouse:
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 889d7326e90..243f2c82ce9 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -102,6 +102,7 @@
"bill_no",
"bill_date",
"more_info",
+ "project",
"status",
"amended_from",
"range",
@@ -1059,13 +1060,20 @@
"fieldname": "scan_barcode",
"fieldtype": "Data",
"label": "Scan Barcode"
+ },
+ {
+ "description": "Track this Purchase Receipt against any Project",
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "options": "Project"
}
],
"icon": "fa fa-truck",
"idx": 261,
"is_submittable": 1,
"links": [],
- "modified": "2020-04-17 13:06:26.970288",
+ "modified": "2020-07-15 12:49:42.095297",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 1791978a068..0475ea7a2ec 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -74,6 +74,20 @@ frappe.ui.form.on("Stock Reconciliation", {
, __("Get Items"), __("Update"));
},
+ posting_date: function(frm) {
+ frm.trigger("set_valuation_rate_and_qty_for_all_items");
+ },
+
+ posting_time: function(frm) {
+ frm.trigger("set_valuation_rate_and_qty_for_all_items");
+ },
+
+ set_valuation_rate_and_qty_for_all_items: function(frm) {
+ frm.doc.items.forEach(row => {
+ frm.events.set_valuation_rate_and_qty(frm, row.doctype, row.name);
+ });
+ },
+
set_valuation_rate_and_qty: function(frm, cdt, cdn) {
var d = frappe.model.get_doc(cdt, cdn);
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index d62aac9300f..0dc87767dde 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -184,8 +184,12 @@ class StockReconciliation(StockController):
sl_entries = []
has_serial_no = False
+ has_batch_no = False
for row in self.items:
item = frappe.get_doc("Item", row.item_code)
+ if item.has_batch_no:
+ has_batch_no = True
+
if item.has_serial_no or item.has_batch_no:
has_serial_no = True
self.get_sle_for_serialized_items(row, sl_entries)
@@ -221,7 +225,11 @@ class StockReconciliation(StockController):
if has_serial_no:
sl_entries = self.merge_similar_item_serial_nos(sl_entries)
- self.make_sl_entries(sl_entries)
+ allow_negative_stock = False
+ if has_batch_no:
+ allow_negative_stock = True
+
+ self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
if has_serial_no and sl_entries:
self.update_valuation_rate_for_serial_no()
@@ -507,7 +515,7 @@ def get_stock_balance_for(item_code, warehouse,
qty, rate = data
if item_dict.get("has_batch_no"):
- qty = get_batch_qty(batch_no, warehouse) or 0
+ qty = get_batch_qty(batch_no, warehouse, posting_date=posting_date, posting_time=posting_time) or 0
return {
'qty': qty,
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 74a4f6ef142..042087a4a77 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -2,7 +2,7 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
from frappe import _
from frappe.utils import flt, cint, getdate, now, date_diff
from erpnext.stock.utils import add_additional_uom_columns
@@ -20,6 +20,11 @@ def execute(filters=None):
from_date = filters.get('from_date')
to_date = filters.get('to_date')
+ if filters.get("company"):
+ company_currency = erpnext.get_company_currency(filters.get("company"))
+ else:
+ company_currency = frappe.db.get_single_value("Global Defaults", "default_currency")
+
include_uom = filters.get("include_uom")
columns = get_columns(filters)
items = get_items(filters)
@@ -52,6 +57,7 @@ def execute(filters=None):
item_reorder_qty = item_reorder_detail_map[item + warehouse]["warehouse_reorder_qty"]
report_data = {
+ 'currency': company_currency,
'item_code': item,
'warehouse': warehouse,
'company': company,
@@ -89,7 +95,6 @@ def execute(filters=None):
def get_columns(filters):
"""return columns"""
-
columns = [
{"label": _("Item"), "fieldname": "item_code", "fieldtype": "Link", "options": "Item", "width": 100},
{"label": _("Item Name"), "fieldname": "item_name", "width": 150},
@@ -97,14 +102,14 @@ def get_columns(filters):
{"label": _("Warehouse"), "fieldname": "warehouse", "fieldtype": "Link", "options": "Warehouse", "width": 100},
{"label": _("Stock UOM"), "fieldname": "stock_uom", "fieldtype": "Link", "options": "UOM", "width": 90},
{"label": _("Balance Qty"), "fieldname": "bal_qty", "fieldtype": "Float", "width": 100, "convertible": "qty"},
- {"label": _("Balance Value"), "fieldname": "bal_val", "fieldtype": "Currency", "width": 100},
+ {"label": _("Balance Value"), "fieldname": "bal_val", "fieldtype": "Currency", "width": 100, "options": "currency"},
{"label": _("Opening Qty"), "fieldname": "opening_qty", "fieldtype": "Float", "width": 100, "convertible": "qty"},
- {"label": _("Opening Value"), "fieldname": "opening_val", "fieldtype": "Float", "width": 110},
+ {"label": _("Opening Value"), "fieldname": "opening_val", "fieldtype": "Currency", "width": 110, "options": "currency"},
{"label": _("In Qty"), "fieldname": "in_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
{"label": _("In Value"), "fieldname": "in_val", "fieldtype": "Float", "width": 80},
{"label": _("Out Qty"), "fieldname": "out_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
{"label": _("Out Value"), "fieldname": "out_val", "fieldtype": "Float", "width": 80},
- {"label": _("Valuation Rate"), "fieldname": "val_rate", "fieldtype": "Currency", "width": 90, "convertible": "rate"},
+ {"label": _("Valuation Rate"), "fieldname": "val_rate", "fieldtype": "Currency", "width": 90, "convertible": "rate", "options": "currency"},
{"label": _("Reorder Level"), "fieldname": "reorder_level", "fieldtype": "Float", "width": 80, "convertible": "qty"},
{"label": _("Reorder Qty"), "fieldname": "reorder_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 100}
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index d757ecb293d..6a265ec4cc5 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
+from frappe.utils import cint, flt
from erpnext.stock.utils import update_included_uom_in_report
def execute(filters=None):
@@ -13,6 +14,7 @@ def execute(filters=None):
sl_entries = get_stock_ledger_entries(filters, items)
item_details = get_item_details(items, sl_entries, include_uom)
opening_row = get_opening_balance(filters, columns)
+ precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
data = []
conversion_factors = []
@@ -27,10 +29,10 @@ def execute(filters=None):
sle.update(item_detail)
if filters.get("batch_no"):
- actual_qty += sle.actual_qty
+ actual_qty += flt(sle.actual_qty, precision)
stock_value += sle.stock_value_difference
- if sle.voucher_type == 'Stock Reconciliation':
+ if sle.voucher_type == 'Stock Reconciliation' and not sle.actual_qty:
actual_qty = sle.qty_after_transaction
stock_value = sle.stock_value
diff --git a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py
index 6a86889aa3d..5873a7a3008 100644
--- a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py
+++ b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py
@@ -21,7 +21,7 @@ def execute(filters=None):
for cd in consumed_details.get(item_code):
if (cd.voucher_no not in material_transfer_vouchers):
- if cd.voucher_type=="Delivery Note":
+ if cd.voucher_type in ["Delivery Note", "Sales Invoice"]:
delivered_qty += abs(flt(cd.actual_qty))
delivered_amount += abs(flt(cd.stock_value_difference))
elif cd.voucher_type!="Delivery Note":