From 513099d6240d253b83ca3fb993cd33f3becc4a2a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 17 May 2020 23:26:37 +0530 Subject: [PATCH 01/17] fix: Description for various fields --- .../loan_management/loan_management.json | 4 +- .../loan_application/loan_application.js | 23 ++++--- .../loan_interest_accrual.py | 65 ++++++++++--------- .../loan_repayment/loan_repayment.json | 4 +- .../loan_security_pledge.js | 23 ++++--- .../loan_security_type.json | 4 +- .../doctype/loan_type/loan_type.json | 7 +- 7 files changed, 72 insertions(+), 58 deletions(-) diff --git a/erpnext/loan_management/desk_page/loan_management/loan_management.json b/erpnext/loan_management/desk_page/loan_management/loan_management.json index f9ea978ed6e..6cabff9443c 100644 --- a/erpnext/loan_management/desk_page/loan_management/loan_management.json +++ b/erpnext/loan_management/desk_page/loan_management/loan_management.json @@ -3,7 +3,7 @@ { "hidden": 0, "label": "Loan", - "links": "[\n {\n \"description\": \"Loan Type for interest and penalty rates\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Applications from customers and employees.\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]" + "links": "[\n {\n \"description\": \"Loan Type for interest and penalty rates\",\n \"label\": \"Loan Type\",\n \"name\": \"Loan Type\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Loan Applications from customers and employees.\",\n \"label\": \"Loan Application\",\n \"name\": \"Loan Application\",\n \"type\": \"doctype\"\n },\n { \"dependencies\": [\n \"Loan Type\"\n ],\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, @@ -37,7 +37,7 @@ "idx": 0, "is_standard": 1, "label": "Loan Management", - "modified": "2020-04-02 11:28:51.380509", + "modified": "2020-05-16 08:01:27.784621", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Management", diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js index 6cf47bf85c7..b56fce1d7cb 100644 --- a/erpnext/loan_management/doctype/loan_application/loan_application.js +++ b/erpnext/loan_management/doctype/loan_application/loan_application.js @@ -112,16 +112,19 @@ frappe.ui.form.on('Loan Application', { frappe.ui.form.on("Proposed Pledge", { loan_security: function(frm, cdt, cdn) { let row = locals[cdt][cdn]; - frappe.call({ - method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", - args: { - loan_security: row.loan_security - }, - callback: function(r) { - frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); - frm.events.calculate_amounts(frm, cdt, cdn); - } - }) + + if (row.loan_security) { + frappe.call({ + method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", + args: { + loan_security: row.loan_security + }, + callback: function(r) { + frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); + frm.events.calculate_amounts(frm, cdt, cdn); + } + }) + } }, amount: function(frm, cdt, cdn) { diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py index 094b9c698c7..9b486e805d0 100644 --- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py @@ -19,8 +19,8 @@ class LoanInterestAccrual(AccountsController): if not self.posting_date: self.posting_date = nowdate() - if not self.interest_amount: - frappe.throw(_("Interest Amount is mandatory")) + if not self.interest_amount and not self.payable_principal_amount: + frappe.throw(_("Interest Amount or Principal Amount is mandatory")) def on_submit(self): @@ -38,37 +38,38 @@ class LoanInterestAccrual(AccountsController): def make_gl_entries(self, cancel=0, adv_adj=0): gle_map = [] - gle_map.append( - self.get_gl_dict({ - "account": self.loan_account, - "party_type": self.applicant_type, - "party": self.applicant, - "against": self.interest_income_account, - "debit": self.interest_amount, - "debit_in_account_currency": self.interest_amount, - "against_voucher_type": "Loan", - "against_voucher": self.loan, - "remarks": _("Against Loan:") + self.loan, - "cost_center": erpnext.get_default_cost_center(self.company), - "posting_date": self.posting_date - }) - ) + if self.interest_amount: + gle_map.append( + self.get_gl_dict({ + "account": self.loan_account, + "party_type": self.applicant_type, + "party": self.applicant, + "against": self.interest_income_account, + "debit": self.interest_amount, + "debit_in_account_currency": self.interest_amount, + "against_voucher_type": "Loan", + "against_voucher": self.loan, + "remarks": _("Against Loan:") + self.loan, + "cost_center": erpnext.get_default_cost_center(self.company), + "posting_date": self.posting_date + }) + ) - gle_map.append( - self.get_gl_dict({ - "account": self.interest_income_account, - "party_type": self.applicant_type, - "party": self.applicant, - "against": self.loan_account, - "credit": self.interest_amount, - "credit_in_account_currency": self.interest_amount, - "against_voucher_type": "Loan", - "against_voucher": self.loan, - "remarks": _("Against Loan:") + self.loan, - "cost_center": erpnext.get_default_cost_center(self.company), - "posting_date": self.posting_date - }) - ) + gle_map.append( + self.get_gl_dict({ + "account": self.interest_income_account, + "party_type": self.applicant_type, + "party": self.applicant, + "against": self.loan_account, + "credit": self.interest_amount, + "credit_in_account_currency": self.interest_amount, + "against_voucher_type": "Loan", + "against_voucher": self.loan, + "remarks": _("Against Loan:") + self.loan, + "cost_center": erpnext.get_default_cost_center(self.company), + "posting_date": self.posting_date + }) + ) if gle_map: make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj) diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json index 789c1299463..5942455919f 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json @@ -173,7 +173,7 @@ { "fieldname": "references_section", "fieldtype": "Section Break", - "label": "References" + "label": "Payment References" }, { "fieldname": "reference_number", @@ -221,7 +221,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-04-16 18:14:45.166754", + "modified": "2020-05-16 09:40:15.581165", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Repayment", diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js index 82837b3dac8..11c932ff1c1 100644 --- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js +++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js @@ -22,16 +22,19 @@ frappe.ui.form.on('Loan Security Pledge', { frappe.ui.form.on("Pledge", { loan_security: function(frm, cdt, cdn) { let row = locals[cdt][cdn]; - frappe.call({ - method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", - args: { - loan_security: row.loan_security - }, - callback: function(r) { - frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); - frm.events.calculate_amounts(frm, cdt, cdn); - } - }); + + if (row.loan_security) { + frappe.call({ + method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price", + args: { + loan_security: row.loan_security + }, + callback: function(r) { + frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message); + frm.events.calculate_amounts(frm, cdt, cdn); + } + }); + } }, qty: function(frm, cdt, cdn) { diff --git a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json index f46b88cbca6..871e82563af 100644 --- a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json +++ b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json @@ -29,6 +29,7 @@ "unique": 1 }, { + "description": "Haircut percentage is the percentage difference between market value of the Loan Security and the value ascribed to that Loan Security when used as collateral for that loan.", "fieldname": "haircut", "fieldtype": "Percent", "label": "Haircut %" @@ -46,13 +47,14 @@ "fieldtype": "Column Break" }, { + "description": "Loan To Value Ratio expresses the ratio of the loan amount to the value of the security pledged. A loan security shortfall will be triggered if this falls below the specified value for any loan ", "fieldname": "loan_to_value_ratio", "fieldtype": "Percent", "label": "Loan To Value Ratio" } ], "links": [], - "modified": "2020-04-28 14:06:49.046177", + "modified": "2020-05-16 09:38:45.988080", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Security Type", diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json index 51c5cb98a63..90ae3b01bd2 100644 --- a/erpnext/loan_management/doctype/loan_type/loan_type.json +++ b/erpnext/loan_management/doctype/loan_type/loan_type.json @@ -75,6 +75,7 @@ "reqd": 1 }, { + "description": "This account is used for booking loan repayments from the borrower and also disbursing loans to the borrower", "fieldname": "payment_account", "fieldtype": "Link", "label": "Payment Account", @@ -82,6 +83,7 @@ "reqd": 1 }, { + "description": "This account is capital account which is used to allocate capital for loan disbursal account ", "fieldname": "loan_account", "fieldtype": "Link", "label": "Loan Account", @@ -93,6 +95,7 @@ "fieldtype": "Column Break" }, { + "description": "This account will be used for booking loan interest accruals", "fieldname": "interest_income_account", "fieldtype": "Link", "label": "Interest Income Account", @@ -100,6 +103,7 @@ "reqd": 1 }, { + "description": "This account will be used for booking penalties levied due to delayed repayments", "fieldname": "penalty_income_account", "fieldtype": "Link", "label": "Penalty Income Account", @@ -108,6 +112,7 @@ }, { "default": "0", + "description": "If this is not checked the loan by default will be considered as a Demand Loan", "fieldname": "is_term_loan", "fieldtype": "Check", "label": "Is Term Loan" @@ -143,7 +148,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-04-15 00:24:43.259963", + "modified": "2020-05-16 09:08:09.029921", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Type", From 5ccefdc08a1bbbfc0ff24b8f1ca3de835a4f52a9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 17 May 2020 23:26:59 +0530 Subject: [PATCH 02/17] fix: Patch to update old loans --- erpnext/patches.txt | 1 + erpnext/patches/v13_0/update_old_loans.py | 83 +++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 erpnext/patches/v13_0/update_old_loans.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ce0e4ac4711..f3907f4b179 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -680,3 +680,4 @@ erpnext.patches.v12_0.fix_quotation_expired_status erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry erpnext.patches.v12_0.retain_permission_rules_for_video_doctype erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive +erpnext.patches.v13_0.update_old_loans diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py new file mode 100644 index 00000000000..e924f6234b2 --- /dev/null +++ b/erpnext/patches/v13_0/update_old_loans.py @@ -0,0 +1,83 @@ +from __future__ import unicode_literals +import frappe +from frappe.utils import nowdate +from erpnext.accounts.doctype.account.test_account import create_account +from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans +from erpnext.loan_management.doctype.loan.loan import make_repayment_entry + +def execute(): + + # Create a penalty account for loan types + + frappe.reload_doc('loan_management', 'doctype', 'loan_type') + frappe.reload_doc('loan_management', 'doctype', 'loan') + frappe.reload_doc('loan_management', 'doctype', 'repayment_schedule') + frappe.reload_doc('loan_management', 'doctype', 'process_loan_interest_accrual') + frappe.reload_doc('loan_management', 'doctype', 'loan_repayment') + frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail') + frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual') + frappe.reload_doc('accounts', 'doctype', 'gl_entry') + + updated_loan_types = [] + + loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment', + 'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account']) + + for loan in loans: + # Update details in Loan Types and Loan + loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company') + + parent_income = frappe.get_value('Account', {'company': loan.company, + 'is_group': 1, 'root_type': 'Income'}) + + penalty_account = create_account(company=loan.company, account_type='Income Account', + account_name='Penalty Account', parent_account=parent_income) + + if not loan_type_company: + loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type) + loan_type_doc.is_term_loan = 1 + loan_type_doc.company = loan.company + loan_type_doc.mode_of_payment = loan.mode_of_payment + loan_type_doc.payment_account = loan.payment_account + loan_type_doc.loan_account = loan.loan_account + loan_type_doc.interest_income_account = loan.interest_income_account + loan_type_doc.penalty_income_account = penalty_account + loan_type_doc.submit() + updated_loan_types.append(loan.loan_type) + + if loan.loan_type in updated_loan_types: + if loan.status == 'Fully Disbursed': + status = 'Disbursed' + elif loan.status == 'Repaid/Closed': + status = 'Closed' + else: + status = loan.status + + frappe.db.set_value('Loan', loan.name, { + 'is_term_loan': 1, + 'penalty_income_account': penalty_account, + 'status': status + }) + + process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type, + loan=loan.name) + + payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date + FROM `tabJournal Entry` j, `tabJournal Entry Account` a + WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s + and account = %s + ''', (loan.name, loan.loan_account), as_dict=1) + + for payment in payments: + repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant, + loan.loan_type, loan.company) + + repayment_entry.amount_paid = payment.debit_in_account_currency + repayment_entry.posting_date = payment.posting_date + repayment_entry.save() + repayment_entry.submit() + + jv = frappe.get_doc('Journal Entry', payment.name) + jv.flags.ignore_links = True + jv.cancel() + From 8cfa00920ed53f44bc9cb8ba05b46ca5778b376d Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Wed, 29 Jul 2020 15:24:03 +0530 Subject: [PATCH 03/17] fix: cannot submit value adjustment with custom dimension --- .../asset_value_adjustment.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 155597e8565..fd702c74c73 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -8,6 +8,7 @@ from frappe import _ from frappe.utils import flt, getdate, cint, date_diff, formatdate from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts from frappe.model.document import Document +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts class AssetValueAdjustment(Document): def validate(self): @@ -53,17 +54,33 @@ class AssetValueAdjustment(Document): je.company = self.company je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount) - je.append("accounts", { + credit_entry = { "account": accumulated_depreciation_account, "credit_in_account_currency": self.difference_amount, "cost_center": depreciation_cost_center or self.cost_center - }) + } - je.append("accounts", { + debit_entry = { "account": depreciation_expense_account, "debit_in_account_currency": self.difference_amount, "cost_center": depreciation_cost_center or self.cost_center - }) + } + + accounting_dimensions = get_checks_for_pl_and_bs_accounts() + + for dimension in accounting_dimensions: + if dimension.get('mandatory_for_bs'): + credit_entry.update({ + dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension') + }) + + if dimension.get('mandatory_for_pl'): + debit_entry.update({ + dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension') + }) + + je.append("accounts", credit_entry) + je.append("accounts", debit_entry) je.flags.ignore_permissions = True je.submit() From ab611d5fd8a4a87b0a07469e09e1efcdd97f89a7 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Aug 2020 14:47:40 +0530 Subject: [PATCH 04/17] fix: GSTR 1 report for exports without payment of Tax --- erpnext/regional/report/gstr_1/gstr_1.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py index 8885b88c2a4..282efe47901 100644 --- a/erpnext/regional/report/gstr_1/gstr_1.py +++ b/erpnext/regional/report/gstr_1/gstr_1.py @@ -131,6 +131,9 @@ class Gstr1Report(object): taxable_value += abs(net_amount) elif tax_rate: taxable_value += abs(net_amount) + elif not tax_rate and self.filters.get('type_of_business') == 'EXPORT' \ + and invoice_details.get('export_type') == "Without Payment of Tax": + taxable_value += abs(net_amount) row += [tax_rate or 0, taxable_value] From 1f3cc7553cab51571290ce1481ec43b5265cad15 Mon Sep 17 00:00:00 2001 From: Afshan Date: Fri, 7 Aug 2020 15:57:31 +0530 Subject: [PATCH 05/17] fix: grand_total assigment before reference --- erpnext/accounts/doctype/dunning/dunning.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py index 3e372affa12..1a6dbedf560 100644 --- a/erpnext/accounts/doctype/dunning/dunning.py +++ b/erpnext/accounts/doctype/dunning/dunning.py @@ -93,6 +93,7 @@ def resolve_dunning(doc, state): def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days): interest_amount = 0 + grand_total = 0 if rate_of_interest: interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100 interest_amount = (interest_per_year * cint(overdue_days)) / 365 From bad269c3549adcef9021bd4c034d370ffae87257 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Aug 2020 16:21:41 +0530 Subject: [PATCH 06/17] fix: Parent income account check --- erpnext/patches/v13_0/update_old_loans.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py index e924f6234b2..77239429c51 100644 --- a/erpnext/patches/v13_0/update_old_loans.py +++ b/erpnext/patches/v13_0/update_old_loans.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.utils import nowdate from erpnext.accounts.doctype.account.test_account import create_account from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans @@ -27,11 +28,15 @@ def execute(): # Update details in Loan Types and Loan loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company') - parent_income = frappe.get_value('Account', {'company': loan.company, - 'is_group': 1, 'root_type': 'Income'}) + group_income_account = frappe.get_value('Account', {'company': loan.company, + 'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')}) + + if not group_income_account: + group_income_account = frappe.get_value('Account', {'company': loan.company, + 'is_group': 1, 'root_type': 'Income'}) penalty_account = create_account(company=loan.company, account_type='Income Account', - account_name='Penalty Account', parent_account=parent_income) + account_name='Penalty Account', parent_account=group_income_account) if not loan_type_company: loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type) From 5ac2fd94f0fa361d496bcd2137a36c9433435261 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 8 Aug 2020 22:28:13 +0530 Subject: [PATCH 07/17] fix: Taxable value for RCM --- .../doctype/gstr_3b_report/gstr_3b_report.py | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index 2d306ba1726..fa5f5811eb4 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -234,9 +234,6 @@ class GSTR3BReport(Document): self.report_dict[supply_type][supply_category][account_map.get(account_type)] += \ flt(tax_details.get((account_name, gst_category), {}).get("amount"), 2) - for k, v in iteritems(account_map): - txval -= self.report_dict.get(supply_type, {}).get(supply_category, {}).get(v, 0) - self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2) def set_inter_state_supply(self, inter_state_supply): @@ -256,7 +253,7 @@ class GSTR3BReport(Document): def get_total_taxable_value(self, doctype, reverse_charge): return frappe._dict(frappe.db.sql(""" - select gst_category, sum(base_grand_total) as total + select gst_category, sum(net_total) as total from `tab{doctype}` where docstatus = 1 and month(posting_date) = %s and year(posting_date) = %s and reverse_charge = %s @@ -309,26 +306,27 @@ class GSTR3BReport(Document): inter_state_supply_tax_mapping.setdefault(d.name, { 'place_of_supply': d.place_of_supply, 'taxable_value': d.net_total, + 'gst_category': d.gst_category, 'camt': 0.0, 'samt': 0.0, 'iamt': 0.0, 'csamt': 0.0 }) - if d.account_head in [d.cgst_account for d in self.account_heads]: + if d.account_head in [a.cgst_account for a in self.account_heads]: inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount - if d.account_head in [d.sgst_account for d in self.account_heads]: + if d.account_head in [a.sgst_account for a in self.account_heads]: inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount - if d.account_head in [d.igst_account for d in self.account_heads]: + if d.account_head in [a.igst_account for a in self.account_heads]: inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount - if d.account_head in [d.cess_account for d in self.account_heads]: + if d.account_head in [a.cess_account for a in self.account_heads]: inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount for key, value in iteritems(inter_state_supply_tax_mapping): - if d.place_of_supply: + if value.get('place_of_supply'): osup_det = self.report_dict["sup_details"]["osup_det"] osup_det["txval"] = flt(osup_det["txval"] + value['taxable_value'], 2) osup_det["iamt"] = flt(osup_det["iamt"] + value['iamt'], 2) @@ -336,15 +334,15 @@ class GSTR3BReport(Document): osup_det["samt"] = flt(osup_det["samt"] + value['samt'], 2) osup_det["csamt"] = flt(osup_det["csamt"] + value['csamt'], 2) - if state_number != d.place_of_supply.split("-")[0]: - inter_state_supply_details.setdefault((d.gst_category, d.place_of_supply), { + if state_number != value.get('place_of_supply').split("-")[0]: + inter_state_supply_details.setdefault((value.get('gst_category'), value.get('place_of_supply')), { "txval": 0.0, "pos": d.place_of_supply.split("-")[0], "iamt": 0.0 }) - inter_state_supply_details[(d.gst_category, d.place_of_supply)]['txval'] += value['taxable_value'] - inter_state_supply_details[(d.gst_category, d.place_of_supply)]['iamt'] += value['iamt'] + inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['txval'] += value['taxable_value'] + inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['iamt'] += value['iamt'] return inter_state_supply_details From d4ecf426b713f683cfc50df55384e9c79163903b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 8 Aug 2020 22:33:18 +0530 Subject: [PATCH 08/17] fix: Place of supply fix --- erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index fa5f5811eb4..787d557e805 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -337,7 +337,7 @@ class GSTR3BReport(Document): if state_number != value.get('place_of_supply').split("-")[0]: inter_state_supply_details.setdefault((value.get('gst_category'), value.get('place_of_supply')), { "txval": 0.0, - "pos": d.place_of_supply.split("-")[0], + "pos": value.get('place_of_supply').split("-")[0], "iamt": 0.0 }) From a53f15ca35fd5c832885f975868014b7c30648e4 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sun, 9 Aug 2020 13:12:47 +0530 Subject: [PATCH 09/17] fix: remove mentions of display items in stock (#22963) --- erpnext/selling/page/point_of_sale/point_of_sale.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 9f8410f40bc..83bd71d5f32 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -14,10 +14,9 @@ from six import string_types def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None): data = dict() warehouse = "" - display_items_in_stock = 0 if pos_profile: - warehouse, display_items_in_stock = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'display_items_in_stock']) + warehouse = frappe.db.get_value('POS Profile', pos_profile, ['warehouse']) if not frappe.db.exists('Item Group', item_group): item_group = get_root_of('Item Group') @@ -85,7 +84,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p item_price = item_prices.get(item_code) or {} item_stock_qty = get_stock_availability(item_code, warehouse) - if display_items_in_stock and not item_stock_qty: + if not item_stock_qty: pass else: row = {} From bc8a281f83640ccbefa9c8d2b99b05db6b9c25b2 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 10 Aug 2020 11:00:08 +0530 Subject: [PATCH 10/17] fix: Subscripition link in Customer dashboard (#22960) Co-authored-by: Rucha Mahabal --- erpnext/selling/doctype/customer/customer_dashboard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py index 22e30e31139..09e474dc2ef 100644 --- a/erpnext/selling/doctype/customer/customer_dashboard.py +++ b/erpnext/selling/doctype/customer/customer_dashboard.py @@ -12,7 +12,8 @@ def get_data(): 'Payment Entry': 'party', 'Quotation': 'party_name', 'Opportunity': 'party_name', - 'Bank Account': 'party' + 'Bank Account': 'party', + 'Subscription': 'party' }, 'dynamic_links': { 'party_name': ['Customer', 'quotation_to'] From 5c0439f768d179f43e3169004fca14fe6e00a65d Mon Sep 17 00:00:00 2001 From: Prssanna Desai Date: Mon, 10 Aug 2020 11:12:52 +0530 Subject: [PATCH 11/17] fix: set correct default value from from date in downtime analysis report (#22903) Co-authored-by: Rucha Mahabal --- .../manufacturing/report/downtime_analysis/downtime_analysis.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js index ff32dbed98a..f6486743aa3 100644 --- a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js +++ b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js @@ -8,7 +8,7 @@ frappe.query_reports["Downtime Analysis"] = { label: __("From Date"), fieldname:"from_date", fieldtype: "Datetime", - default: frappe.datetime.add_months(frappe.datetime.now_datetime(), -1), + default: frappe.datetime.convert_to_system_tz(frappe.datetime.add_months(frappe.datetime.now_datetime(), -1)), reqd: 1 }, { From 97ecf52d6fcba8c1be5e0a6fecc011e99b44e58f Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 10 Aug 2020 12:13:35 +0530 Subject: [PATCH 12/17] fix: failing Fees test --- erpnext/education/doctype/fees/test_fees.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/education/doctype/fees/test_fees.py b/erpnext/education/doctype/fees/test_fees.py index b182992922b..eedc2ae7301 100644 --- a/erpnext/education/doctype/fees/test_fees.py +++ b/erpnext/education/doctype/fees/test_fees.py @@ -7,7 +7,7 @@ import frappe import unittest from frappe.utils import nowdate from frappe.utils.make_random import get_random - +from erpnext.education.doctype.program.test_program import make_program_and_linked_courses # test_records = frappe.get_test_records('Fees') @@ -15,6 +15,7 @@ class TestFees(unittest.TestCase): def test_fees(self): student = get_random("Student") + program = make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"]) fee = frappe.new_doc("Fees") fee.posting_date = nowdate() fee.due_date = nowdate() @@ -23,6 +24,7 @@ class TestFees(unittest.TestCase): fee.income_account = "Sales - _TC" fee.cost_center = "_Test Cost Center - _TC" fee.company = "_Test Company" + fee.program = program.name fee.extend("components", [ { From a07973cfa57f6bc0ebf367fa32af89e0ec8d4008 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 10 Aug 2020 12:39:42 +0530 Subject: [PATCH 13/17] fix: Creating opportunity from email --- erpnext/crm/doctype/opportunity/opportunity.py | 2 +- erpnext/public/js/communication.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 1b071ea1b70..efaeca0e938 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -330,7 +330,7 @@ def make_opportunity_from_communication(communication, ignore_communication_link opportunity = frappe.get_doc({ "doctype": "Opportunity", "opportunity_from": opportunity_from, - "lead": lead + "party_name": lead }).insert(ignore_permissions=True) link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links) diff --git a/erpnext/public/js/communication.js b/erpnext/public/js/communication.js index 5316eb45b5b..9432d421752 100644 --- a/erpnext/public/js/communication.js +++ b/erpnext/public/js/communication.js @@ -13,7 +13,7 @@ frappe.ui.form.on("Communication", { frappe.confirm(__(confirm_msg, [__("Issue")]), () => { frm.trigger('make_issue_from_communication'); }) - }, "Make"); + }, "Create"); } if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) { From d3d3db654ef4bedf308ee5563ccca55090fdf070 Mon Sep 17 00:00:00 2001 From: Anoop Date: Mon, 10 Aug 2020 13:21:12 +0530 Subject: [PATCH 14/17] fix: Inpatient Record - Transfer check-in time validation (#22958) * fix: inpatient transfer should not allow future checkin time * Update erpnext/healthcare/doctype/inpatient_record/inpatient_record.js Error message corrected Co-authored-by: Rucha Mahabal Co-authored-by: Rucha Mahabal --- .../doctype/inpatient_record/inpatient_record.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js index 971e166067e..60f0f9d56d6 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js @@ -134,7 +134,7 @@ let transfer_patient_dialog = function(frm) { {fieldtype: 'Link', label: 'Leave From', fieldname: 'leave_from', options: 'Healthcare Service Unit', reqd: 1, read_only:1}, {fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type', options: 'Healthcare Service Unit Type'}, {fieldtype: 'Link', label: 'Transfer To', fieldname: 'service_unit', options: 'Healthcare Service Unit', reqd: 1}, - {fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1} + {fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1, default: frappe.datetime.now_datetime()} ], primary_action_label: __('Transfer'), primary_action : function() { @@ -147,7 +147,12 @@ let transfer_patient_dialog = function(frm) { if(dialog.get_value('service_unit')){ service_unit = dialog.get_value('service_unit'); } - if(!check_in){ + if(check_in > frappe.datetime.now_datetime()){ + frappe.msgprint({ + title: __('Not Allowed'), + message: __('Check-in time cannot be greater than the current time'), + indicator: 'red' + }); return; } frappe.call({ From f1091534cd5f269f7554dde44e5e453f0f8a068c Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 10 Aug 2020 14:45:58 +0530 Subject: [PATCH 15/17] fix: [pos] minor bugs --- erpnext/accounts/doctype/pos_profile/pos_profile.js | 7 +------ erpnext/selling/page/point_of_sale/pos_controller.js | 7 ++++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js index ef431d7d41a..8ec6a536269 100755 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.js +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js @@ -31,8 +31,7 @@ frappe.ui.form.on('POS Profile', { frm.set_query("print_format", function() { return { filters: [ - ['Print Format', 'doc_type', '=', 'Sales Invoice'], - ['Print Format', 'print_format_type', '=', 'Jinja'], + ['Print Format', 'doc_type', '=', 'POS Invoice'] ] }; }); @@ -45,10 +44,6 @@ frappe.ui.form.on('POS Profile', { }; }); - frm.set_query("print_format", function() { - return { filters: { doc_type: "Sales Invoice", print_format_type: "JS"} }; - }); - frm.set_query('company_address', function(doc) { if(!doc.company) { frappe.throw(__('Please set Company')); diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 483ef78d64c..ae5471b9000 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -35,7 +35,8 @@ erpnext.PointOfSale.Controller = class { create_opening_voucher() { const table_fields = [ { fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 }, - { fieldname: "opening_amount", fieldtype: "Currency", in_list_view: 1, label: "Opening Amount", options: "company:company_currency", reqd: 1 } + { fieldname: "opening_amount", fieldtype: "Currency", default: 0, in_list_view: 1, label: "Opening Amount", + options: "company:company_currency", reqd: 1 } ]; const dialog = new frappe.ui.Dialog({ @@ -66,7 +67,7 @@ erpnext.PointOfSale.Controller = class { frappe.db.get_doc("POS Closing Entry", pos_closing_entry.name).then(({ payment_reconciliation }) => { dialog.fields_dict.balance_details.df.data = []; payment_reconciliation.forEach(pay => { - const { mode_of_payment, closing_amount } = pay; + const { mode_of_payment } = pay; dialog.fields_dict.balance_details.df.data.push({ mode_of_payment: mode_of_payment }); @@ -152,7 +153,7 @@ erpnext.PointOfSale.Controller = class { }, () => this.make_new_invoice(), () => frappe.dom.unfreeze(), - () => this.page.set_title(__('Point of Sale Beta')), + () => this.page.set_title(__('Point of Sale')), ]); } From 0fcb05a3aa399db7066637fd43576aa12f5df85c Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 10 Aug 2020 14:48:13 +0530 Subject: [PATCH 16/17] fix: Misleading filters on Item tax Template Link field (#22918) Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Co-authored-by: Rucha Mahabal --- erpnext/controllers/queries.py | 5 ++++- erpnext/public/js/controllers/transaction.js | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index babc5bdd797..37b7e31e611 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -613,9 +613,12 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters): if not taxes: return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """) else: + valid_from = filters.get('valid_from') + valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from + args = { 'item_code': filters.get('item_code'), - 'posting_date': filters.get('valid_from'), + 'posting_date': valid_from, 'tax_category': filters.get('tax_category'), 'company': filters.get('company') } diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 4e50f3d7f67..436a232a551 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1821,7 +1821,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, set_query_for_item_tax_template: function(doc, cdt, cdn) { - var item = frappe.get_doc(cdt, cdn); if(!item.item_code) { frappe.throw(__("Please enter Item Code to get item taxes")); @@ -1829,7 +1828,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ let filters = { 'item_code': item.item_code, - 'valid_from': doc.transaction_date || doc.bill_date || doc.posting_date, + 'valid_from': ["<=", doc.transaction_date || doc.bill_date || doc.posting_date], 'item_group': item.item_group, } From 0f27500197f3fa4dbcd165626f7307d094126f39 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 10 Aug 2020 15:17:58 +0530 Subject: [PATCH 17/17] fix: Susbcription in Sales Taxes and Charges Dashboard --- .../sales_taxes_and_charges_template_dashboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py index 0e9c808608b..d825c6fd325 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py @@ -8,7 +8,7 @@ def get_data(): 'fieldname': 'taxes_and_charges', 'non_standard_fieldnames': { 'Tax Rule': 'sales_tax_template', - 'Subscription': 'tax_template', + 'Subscription': 'sales_tax_template', 'Restaurant': 'default_tax_template' }, 'transactions': [