From e5b57ec965101a6183b3f8f2d74b2645cb1ecdbe Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 15 Sep 2021 19:15:31 +0200
Subject: [PATCH 001/107] feat: Overdue Payments table
---
.../doctype/overdue_payments/__init__.py | 0
.../overdue_payments/overdue_payments.json | 171 ++++++++++++++++++
.../overdue_payments/overdue_payments.py | 8 +
3 files changed, 179 insertions(+)
create mode 100644 erpnext/accounts/doctype/overdue_payments/__init__.py
create mode 100644 erpnext/accounts/doctype/overdue_payments/overdue_payments.json
create mode 100644 erpnext/accounts/doctype/overdue_payments/overdue_payments.py
diff --git a/erpnext/accounts/doctype/overdue_payments/__init__.py b/erpnext/accounts/doctype/overdue_payments/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/accounts/doctype/overdue_payments/overdue_payments.json b/erpnext/accounts/doctype/overdue_payments/overdue_payments.json
new file mode 100644
index 0000000000..57104c186c
--- /dev/null
+++ b/erpnext/accounts/doctype/overdue_payments/overdue_payments.json
@@ -0,0 +1,171 @@
+{
+ "actions": [],
+ "creation": "2021-09-15 18:34:27.172906",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "sales_invoice",
+ "payment_schedule",
+ "payment_term",
+ "section_break_15",
+ "description",
+ "section_break_4",
+ "due_date",
+ "overdue_days",
+ "mode_of_payment",
+ "column_break_5",
+ "invoice_portion",
+ "section_break_9",
+ "payment_amount",
+ "outstanding",
+ "paid_amount",
+ "discounted_amount",
+ "column_break_3",
+ "base_payment_amount",
+ "interest_amount"
+ ],
+ "fields": [
+ {
+ "columns": 2,
+ "fieldname": "payment_term",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Payment Term",
+ "options": "Payment Term",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "section_break_15",
+ "fieldtype": "Section Break",
+ "label": "Description"
+ },
+ {
+ "columns": 2,
+ "fetch_from": "payment_term.description",
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description",
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
+ {
+ "columns": 2,
+ "fieldname": "due_date",
+ "fieldtype": "Date",
+ "label": "Due Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "mode_of_payment",
+ "fieldtype": "Link",
+ "label": "Mode of Payment",
+ "options": "Mode of Payment",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
+ {
+ "columns": 2,
+ "fieldname": "invoice_portion",
+ "fieldtype": "Percent",
+ "label": "Invoice Portion",
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break"
+ },
+ {
+ "columns": 2,
+ "fieldname": "payment_amount",
+ "fieldtype": "Currency",
+ "label": "Payment Amount",
+ "options": "currency",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "payment_amount",
+ "fieldname": "outstanding",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Outstanding",
+ "options": "currency",
+ "read_only": 1
+ },
+ {
+ "depends_on": "paid_amount",
+ "fieldname": "paid_amount",
+ "fieldtype": "Currency",
+ "label": "Paid Amount",
+ "options": "currency"
+ },
+ {
+ "default": "0",
+ "depends_on": "discounted_amount",
+ "fieldname": "discounted_amount",
+ "fieldtype": "Currency",
+ "label": "Discounted Amount",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "base_payment_amount",
+ "fieldtype": "Currency",
+ "label": "Payment Amount (Company Currency)",
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "sales_invoice",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Sales Invoice",
+ "options": "Sales Invoice",
+ "reqd": 1
+ },
+ {
+ "fieldname": "payment_schedule",
+ "fieldtype": "Data",
+ "label": "Payment Schedule",
+ "read_only": 1
+ },
+ {
+ "fieldname": "overdue_days",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Overdue Days",
+ "read_only": 1
+ },
+ {
+ "fieldname": "interest_amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Interest Amount",
+ "read_only": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-09-15 19:04:54.082880",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Overdue Payments",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/overdue_payments/overdue_payments.py b/erpnext/accounts/doctype/overdue_payments/overdue_payments.py
new file mode 100644
index 0000000000..844f8ecdbd
--- /dev/null
+++ b/erpnext/accounts/doctype/overdue_payments/overdue_payments.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+class OverduePayments(Document):
+ pass
From e7705327f003858b99215210869dbc1c24eff0b2 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 15 Sep 2021 19:15:53 +0200
Subject: [PATCH 002/107] feat: filter invoices
---
erpnext/accounts/doctype/dunning/dunning.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 9909c6c2ab..2f997ba02e 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -3,11 +3,12 @@
frappe.ui.form.on("Dunning", {
setup: function (frm) {
- frm.set_query("sales_invoice", () => {
+ frm.set_query("sales_invoice", "overdue_payments", () => {
return {
filters: {
docstatus: 1,
company: frm.doc.company,
+ customer: frm.doc.customer,
outstanding_amount: [">", 0],
status: "Overdue"
},
From 487c6018bfe6514972f4788584f2d6c83b2ce2b8 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 15 Sep 2021 19:16:09 +0200
Subject: [PATCH 003/107] feat: restructure dunning doctype
---
erpnext/accounts/doctype/dunning/dunning.json | 108 +++++++++---------
1 file changed, 53 insertions(+), 55 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index 2a32b99f42..a0ddf04b6c 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -8,20 +8,19 @@
"field_order": [
"title",
"naming_series",
- "sales_invoice",
"customer",
"customer_name",
- "outstanding_amount",
"currency",
"conversion_rate",
"column_break_3",
"company",
"posting_date",
"posting_time",
- "due_date",
- "overdue_days",
+ "status",
"address_and_contact_section",
+ "customer_address",
"address_display",
+ "contact_person",
"contact_display",
"contact_mobile",
"contact_email",
@@ -29,16 +28,17 @@
"company_address_display",
"section_break_6",
"dunning_type",
- "dunning_fee",
"column_break_8",
"rate_of_interest",
- "interest_amount",
"section_break_12",
- "dunning_amount",
+ "overdue_payments",
+ "section_break_28",
+ "column_break_17",
+ "total_interest",
+ "total_outstanding",
+ "dunning_fee",
"grand_total",
"income_account",
- "column_break_17",
- "status",
"printing_setting_section",
"language",
"body_text",
@@ -62,15 +62,6 @@
"label": "Series",
"options": "DUNN-.MM.-.YY.-"
},
- {
- "fieldname": "sales_invoice",
- "fieldtype": "Link",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Sales Invoice",
- "options": "Sales Invoice",
- "reqd": 1
- },
{
"fetch_from": "sales_invoice.customer_name",
"fieldname": "customer_name",
@@ -79,13 +70,6 @@
"label": "Customer Name",
"read_only": 1
},
- {
- "fetch_from": "sales_invoice.outstanding_amount",
- "fieldname": "outstanding_amount",
- "fieldtype": "Currency",
- "label": "Outstanding Amount",
- "read_only": 1
- },
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
@@ -94,13 +78,8 @@
"default": "Today",
"fieldname": "posting_date",
"fieldtype": "Date",
- "label": "Date"
- },
- {
- "fieldname": "overdue_days",
- "fieldtype": "Int",
- "label": "Overdue Days",
- "read_only": 1
+ "label": "Date",
+ "reqd": 1
},
{
"fieldname": "section_break_6",
@@ -115,14 +94,6 @@
"options": "Dunning Type",
"reqd": 1
},
- {
- "default": "0",
- "fieldname": "interest_amount",
- "fieldtype": "Currency",
- "label": "Interest Amount",
- "precision": "2",
- "read_only": 1
- },
{
"fieldname": "column_break_8",
"fieldtype": "Column Break"
@@ -134,6 +105,7 @@
"fieldname": "dunning_fee",
"fieldtype": "Currency",
"label": "Dunning Fee",
+ "options": "currency",
"precision": "2"
},
{
@@ -201,13 +173,6 @@
"fieldtype": "Text Editor",
"label": "Closing Text"
},
- {
- "fetch_from": "sales_invoice.due_date",
- "fieldname": "due_date",
- "fieldtype": "Date",
- "label": "Due Date",
- "read_only": 1
- },
{
"fieldname": "posting_time",
"fieldtype": "Time",
@@ -222,6 +187,7 @@
"label": "Rate of Interest (%) Yearly"
},
{
+ "collapsible": 1,
"fieldname": "address_and_contact_section",
"fieldtype": "Section Break",
"label": "Address and Contact"
@@ -273,13 +239,14 @@
"fieldtype": "Link",
"label": "Customer",
"options": "Customer",
- "read_only": 1
+ "reqd": 1
},
{
"default": "0",
"fieldname": "grand_total",
"fieldtype": "Currency",
"label": "Grand Total",
+ "options": "currency",
"precision": "2",
"read_only": 1
},
@@ -292,13 +259,6 @@
"label": "Status",
"options": "Draft\nResolved\nUnresolved\nCancelled"
},
- {
- "fieldname": "dunning_amount",
- "fieldtype": "Currency",
- "hidden": 1,
- "label": "Dunning Amount",
- "read_only": 1
- },
{
"fieldname": "income_account",
"fieldtype": "Link",
@@ -312,6 +272,44 @@
"hidden": 1,
"label": "Conversion Rate",
"read_only": 1
+ },
+ {
+ "fieldname": "overdue_payments",
+ "fieldtype": "Table",
+ "label": "Overdue Payments",
+ "options": "Overdue Payments"
+ },
+ {
+ "fieldname": "section_break_28",
+ "fieldtype": "Section Break"
+ },
+ {
+ "default": "0",
+ "fieldname": "total_interest",
+ "fieldtype": "Currency",
+ "label": "Total Interest",
+ "options": "currency",
+ "precision": "2",
+ "read_only": 1
+ },
+ {
+ "fieldname": "total_outstanding",
+ "fieldtype": "Currency",
+ "label": "Total Outstanding",
+ "options": "currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "customer_address",
+ "fieldtype": "Link",
+ "label": "Customer Address",
+ "options": "Address"
+ },
+ {
+ "fieldname": "contact_person",
+ "fieldtype": "Link",
+ "label": "Contact Person",
+ "options": "Contact"
}
],
"is_submittable": 1,
From 86a8b0b30f6ac29fed1b3a635e4b5103e008f628 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 14:09:32 +0200
Subject: [PATCH 004/107] refactor: doctype naming
Overdue Payments -> Overdue Payment
---
erpnext/accounts/doctype/dunning/dunning.json | 2 +-
.../doctype/{overdue_payments => overdue_payment}/__init__.py | 0
.../overdue_payment.json} | 2 +-
.../overdue_payments.py => overdue_payment/overdue_payment.py} | 2 +-
4 files changed, 3 insertions(+), 3 deletions(-)
rename erpnext/accounts/doctype/{overdue_payments => overdue_payment}/__init__.py (100%)
rename erpnext/accounts/doctype/{overdue_payments/overdue_payments.json => overdue_payment/overdue_payment.json} (99%)
rename erpnext/accounts/doctype/{overdue_payments/overdue_payments.py => overdue_payment/overdue_payment.py} (84%)
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index a0ddf04b6c..b609a5ce14 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -277,7 +277,7 @@
"fieldname": "overdue_payments",
"fieldtype": "Table",
"label": "Overdue Payments",
- "options": "Overdue Payments"
+ "options": "Overdue Payment"
},
{
"fieldname": "section_break_28",
diff --git a/erpnext/accounts/doctype/overdue_payments/__init__.py b/erpnext/accounts/doctype/overdue_payment/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/overdue_payments/__init__.py
rename to erpnext/accounts/doctype/overdue_payment/__init__.py
diff --git a/erpnext/accounts/doctype/overdue_payments/overdue_payments.json b/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
similarity index 99%
rename from erpnext/accounts/doctype/overdue_payments/overdue_payments.json
rename to erpnext/accounts/doctype/overdue_payment/overdue_payment.json
index 57104c186c..e5253bd12f 100644
--- a/erpnext/accounts/doctype/overdue_payments/overdue_payments.json
+++ b/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
@@ -161,7 +161,7 @@
"modified": "2021-09-15 19:04:54.082880",
"modified_by": "Administrator",
"module": "Accounts",
- "name": "Overdue Payments",
+ "name": "Overdue Payment",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
diff --git a/erpnext/accounts/doctype/overdue_payments/overdue_payments.py b/erpnext/accounts/doctype/overdue_payment/overdue_payment.py
similarity index 84%
rename from erpnext/accounts/doctype/overdue_payments/overdue_payments.py
rename to erpnext/accounts/doctype/overdue_payment/overdue_payment.py
index 844f8ecdbd..e3820d74e0 100644
--- a/erpnext/accounts/doctype/overdue_payments/overdue_payments.py
+++ b/erpnext/accounts/doctype/overdue_payment/overdue_payment.py
@@ -4,5 +4,5 @@
# import frappe
from frappe.model.document import Document
-class OverduePayments(Document):
+class OverduePayment(Document):
pass
From 8976e94a1d697a2a9a8930a3fe9274a0443dc176 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 16:38:36 +0200
Subject: [PATCH 005/107] feat: rework doctypes
---
erpnext/accounts/doctype/dunning/dunning.json | 80 ++++++++++++++-----
.../doctype/dunning_type/dunning_type.json | 33 +++-----
2 files changed, 67 insertions(+), 46 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index b609a5ce14..a0e3c150fd 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -6,7 +6,6 @@
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
- "title",
"naming_series",
"customer",
"customer_name",
@@ -33,18 +32,24 @@
"section_break_12",
"overdue_payments",
"section_break_28",
- "column_break_17",
"total_interest",
- "total_outstanding",
"dunning_fee",
+ "column_break_17",
+ "dunning_amount",
+ "section_break_32",
+ "spacer",
+ "column_break_33",
+ "total_outstanding",
"grand_total",
- "income_account",
- "printing_setting_section",
+ "printing_settings_section",
"language",
"body_text",
"column_break_22",
"letter_head",
"closing_text",
+ "accounting_details_section",
+ "cost_center",
+ "income_account",
"amended_from"
],
"fields": [
@@ -60,7 +65,8 @@
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
- "options": "DUNN-.MM.-.YY.-"
+ "options": "DUNN-.MM.-.YY.-",
+ "print_hide": 1
},
{
"fetch_from": "sales_invoice.customer_name",
@@ -91,8 +97,7 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Dunning Type",
- "options": "Dunning Type",
- "reqd": 1
+ "options": "Dunning Type"
},
{
"fieldname": "column_break_8",
@@ -116,11 +121,6 @@
"fieldname": "column_break_17",
"fieldtype": "Column Break"
},
- {
- "fieldname": "printing_setting_section",
- "fieldtype": "Section Break",
- "label": "Printing Setting"
- },
{
"fieldname": "language",
"fieldtype": "Link",
@@ -155,14 +155,6 @@
"print_hide": 1,
"read_only": 1
},
- {
- "allow_on_submit": 1,
- "default": "{customer_name}",
- "fieldname": "title",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Title"
- },
{
"fieldname": "body_text",
"fieldtype": "Text Editor",
@@ -260,10 +252,12 @@
"options": "Draft\nResolved\nUnresolved\nCancelled"
},
{
+ "description": "For dunning fee and interest",
"fieldname": "income_account",
"fieldtype": "Link",
"label": "Income Account",
- "options": "Account"
+ "options": "Account",
+ "print_hide": 1
},
{
"fetch_from": "sales_invoice.conversion_rate",
@@ -310,6 +304,48 @@
"fieldtype": "Link",
"label": "Contact Person",
"options": "Contact"
+ },
+ {
+ "fieldname": "dunning_amount",
+ "fieldtype": "Currency",
+ "label": "Dunning Amount",
+ "options": "currency",
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "accounting_details_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Details"
+ },
+ {
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "label": "Cost Center",
+ "options": "Cost Center"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "printing_settings_section",
+ "fieldtype": "Section Break",
+ "label": "Printing Settings"
+ },
+ {
+ "fieldname": "section_break_32",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_33",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "spacer",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Spacer",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
}
],
"is_submittable": 1,
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.json b/erpnext/accounts/doctype/dunning_type/dunning_type.json
index da43664472..ca33ce58a9 100644
--- a/erpnext/accounts/doctype/dunning_type/dunning_type.json
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.json
@@ -8,10 +8,7 @@
"engine": "InnoDB",
"field_order": [
"dunning_type",
- "overdue_interval_section",
- "start_day",
- "column_break_4",
- "end_day",
+ "is_default",
"section_break_6",
"dunning_fee",
"column_break_8",
@@ -45,10 +42,6 @@
"fieldtype": "Table",
"options": "Dunning Letter Text"
},
- {
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- },
{
"fieldname": "section_break_6",
"fieldtype": "Section Break"
@@ -57,33 +50,25 @@
"fieldname": "column_break_8",
"fieldtype": "Column Break"
},
- {
- "fieldname": "overdue_interval_section",
- "fieldtype": "Section Break",
- "label": "Overdue Interval"
- },
- {
- "fieldname": "start_day",
- "fieldtype": "Int",
- "label": "Start Day"
- },
- {
- "fieldname": "end_day",
- "fieldtype": "Int",
- "label": "End Day"
- },
{
"fieldname": "rate_of_interest",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Rate of Interest (%) Yearly"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "label": "Is Default"
}
],
"links": [],
- "modified": "2020-07-15 17:14:17.835074",
+ "modified": "2021-09-16 15:00:02.610605",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning Type",
+ "naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
From 2ee919220a44dc0390162b46e2b539e3cbc991d2 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 16:42:22 +0200
Subject: [PATCH 006/107] feat: rework dunning frontend
---
erpnext/accounts/doctype/dunning/dunning.js | 109 +++++++++++---------
1 file changed, 58 insertions(+), 51 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 2f997ba02e..5158cc2b7f 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -23,14 +23,12 @@ frappe.ui.form.on("Dunning", {
}
};
});
+
+ // cannot add rows manually, only via button "Fetch Overdue Payments"
+ frm.set_df_property("overdue_payments", "cannot_add_rows", true);
},
refresh: function (frm) {
frm.set_df_property("company", "read_only", frm.doc.__islocal ? 0 : 1);
- frm.set_df_property(
- "sales_invoice",
- "read_only",
- frm.doc.__islocal ? 0 : 1
- );
if (frm.doc.docstatus === 1 && frm.doc.status === "Unresolved") {
frm.add_custom_button(__("Resolve"), () => {
frm.set_value("status", "Resolved");
@@ -58,25 +56,27 @@ frappe.ui.form.on("Dunning", {
frappe.set_route("query-report", "General Ledger");
}, __('View'));
}
- },
- overdue_days: function (frm) {
- frappe.db.get_value(
- "Dunning Type",
- {
- start_day: ["<", frm.doc.overdue_days],
- end_day: [">=", frm.doc.overdue_days],
- },
- "dunning_type",
- (r) => {
- if (r) {
- frm.set_value("dunning_type", r.dunning_type);
- } else {
- frm.set_value("dunning_type", "");
- frm.set_value("rate_of_interest", "");
- frm.set_value("dunning_fee", "");
- }
- }
- );
+
+ if(frm.doc.docstatus === 0) {
+ frm.add_custom_button(__("Fetch Overdue Payments"), function() {
+ erpnext.utils.map_current_doc({
+ method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
+ source_doctype: "Sales Invoice",
+ target: frm,
+ setters: {
+ customer: frm.doc.customer || undefined,
+ },
+ get_query_filters: {
+ docstatus: 1,
+ status: "Overdue",
+ company: frm.doc.company
+ },
+ allow_child_item_selection: true,
+ child_fielname: "payment_schedule",
+ child_columns: ["due_date", "outstanding"]
+ });
+ });
+ }
},
dunning_type: function (frm) {
frm.trigger("get_dunning_letter_text");
@@ -107,42 +107,43 @@ frappe.ui.form.on("Dunning", {
});
}
},
- due_date: function (frm) {
- frm.trigger("calculate_overdue_days");
- },
posting_date: function (frm) {
frm.trigger("calculate_overdue_days");
},
rate_of_interest: function (frm) {
- frm.trigger("calculate_interest_and_amount");
- },
- outstanding_amount: function (frm) {
- frm.trigger("calculate_interest_and_amount");
- },
- interest_amount: function (frm) {
- frm.trigger("calculate_interest_and_amount");
+ frm.trigger("calculate_interest_amount");
},
dunning_fee: function (frm) {
- frm.trigger("calculate_interest_and_amount");
- },
- sales_invoice: function (frm) {
- frm.trigger("calculate_overdue_days");
+ frm.trigger("calculate_totals");
},
calculate_overdue_days: function (frm) {
- if (frm.doc.posting_date && frm.doc.due_date) {
- const overdue_days = moment(frm.doc.posting_date).diff(
- frm.doc.due_date,
- "days"
- );
- frm.set_value("overdue_days", overdue_days);
- }
+ frm.doc.overdue_payments.forEach((row) => {
+ if (frm.doc.posting_date && row.due_date) {
+ const overdue_days = moment(frm.doc.posting_date).diff(
+ row.due_date,
+ "days"
+ );
+ frappe.model.set_value(row.doctype, row.name, "overdue_days", overdue_days);
+ }
+ });
},
- calculate_interest_and_amount: function (frm) {
- const interest_per_year = frm.doc.outstanding_amount * frm.doc.rate_of_interest / 100;
- const interest_amount = flt((interest_per_year * cint(frm.doc.overdue_days)) / 365 || 0, precision('interest_amount'));
- const dunning_amount = flt(interest_amount + frm.doc.dunning_fee, precision('dunning_amount'));
- const grand_total = flt(frm.doc.outstanding_amount + dunning_amount, precision('grand_total'));
- frm.set_value("interest_amount", interest_amount);
+ calculate_interest_amount: function (frm) {
+ frm.doc.overdue_payments.forEach((row) => {
+ const interest_per_year = row.outstanding * frm.doc.rate_of_interest / 100;
+ const interest_amount = flt((interest_per_year * cint(row.overdue_days)) / 365 || 0, precision("interest_amount"));
+ frappe.model.set_value(row.doctype, row.name, "interest_amount", interest_amount);
+ });
+ },
+ calculate_totals: function (frm) {
+ const total_interest = frm.doc.overdue_payments
+ .reduce((prev, cur) => prev + cur.interest_amount, 0);
+ const total_outstanding = frm.doc.overdue_payments
+ .reduce((prev, cur) => prev + cur.outstanding, 0);
+ const dunning_amount = flt(total_interest + frm.doc.dunning_fee, precision('dunning_amount'));
+ const grand_total = flt(total_outstanding + dunning_amount, precision('grand_total'));
+
+ frm.set_value("total_outstanding", total_outstanding);
+ frm.set_value("total_interest", total_interest);
frm.set_value("dunning_amount", dunning_amount);
frm.set_value("grand_total", grand_total);
},
@@ -161,3 +162,9 @@ frappe.ui.form.on("Dunning", {
});
},
});
+
+frappe.ui.form.on("Overdue Payment", {
+ interest_amount: function(frm, cdt, cdn) {
+ frm.trigger("calculate_totals");
+ }
+});
\ No newline at end of file
From 2d0dadd9acc370b9559f8d3e70578b6aa29cdf0d Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 16:42:51 +0200
Subject: [PATCH 007/107] feat: rework dunning backend
---
erpnext/accounts/doctype/dunning/dunning.py | 51 ++++++-------
.../doctype/sales_invoice/sales_invoice.py | 75 ++++++++++---------
2 files changed, 62 insertions(+), 64 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index b4df0a5270..56d49df4be 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -15,25 +15,34 @@ from erpnext.controllers.accounts_controller import AccountsController
class Dunning(AccountsController):
+
def validate(self):
- self.validate_overdue_days()
- self.validate_amount()
+ self.validate_overdue_payments()
+ self.validate_totals()
+
if not self.income_account:
self.income_account = frappe.get_cached_value("Company", self.company, "default_income_account")
- def validate_overdue_days(self):
- self.overdue_days = (getdate(self.posting_date) - getdate(self.due_date)).days or 0
+ def validate_overdue_payments(self):
+ for row in self.overdue_payments:
+ row.overdue_days = (getdate(self.posting_date) - getdate(row.due_date)).days or 0
+ interest_per_year = flt(row.outstanding) * flt(self.rate_of_interest) / 100
+ row.interest_amount = (interest_per_year * cint(row.overdue_days)) / 365
- def validate_amount(self):
- amounts = calculate_interest_and_amount(
- self.outstanding_amount, self.rate_of_interest, self.dunning_fee, self.overdue_days
- )
- if self.interest_amount != amounts.get("interest_amount"):
- self.interest_amount = flt(amounts.get("interest_amount"), self.precision("interest_amount"))
- if self.dunning_amount != amounts.get("dunning_amount"):
- self.dunning_amount = flt(amounts.get("dunning_amount"), self.precision("dunning_amount"))
- if self.grand_total != amounts.get("grand_total"):
- self.grand_total = flt(amounts.get("grand_total"), self.precision("grand_total"))
+ def validate_totals(self):
+ total_outstanding = sum(row.outstanding for row in self.overdue_payments)
+ total_interest = sum(row.interest_amount for row in self.overdue_payments)
+ dunning_amount = flt(total_interest) + flt(self.dunning_fee)
+ grand_total = flt(total_outstanding) + flt(dunning_amount)
+
+ if self.total_outstanding != total_outstanding:
+ self.total_outstanding = flt(total_outstanding, self.precision('total_outstanding'))
+ if self.total_interest != total_interest:
+ self.total_interest = flt(total_interest, self.precision('total_interest'))
+ if self.dunning_amount != dunning_amount:
+ self.dunning_amount = flt(dunning_amount, self.precision('dunning_amount'))
+ if self.grand_total != grand_total:
+ self.grand_total = flt(grand_total, self.precision('grand_total'))
def on_submit(self):
self.make_gl_entries()
@@ -113,20 +122,6 @@ def resolve_dunning(doc, state):
frappe.db.set_value("Dunning", dunning.name, "status", "Resolved")
-def calculate_interest_and_amount(outstanding_amount, rate_of_interest, dunning_fee, overdue_days):
- interest_amount = 0
- grand_total = flt(outstanding_amount) + flt(dunning_fee)
- if rate_of_interest:
- interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100
- interest_amount = (interest_per_year * cint(overdue_days)) / 365
- grand_total += flt(interest_amount)
- dunning_amount = flt(interest_amount) + flt(dunning_fee)
- return {
- "interest_amount": interest_amount,
- "grand_total": grand_total,
- "dunning_amount": dunning_amount,
- }
-
@frappe.whitelist()
def get_dunning_letter_text(dunning_type, doc, language=None):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 2075d57a35..0aa6eab862 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2510,55 +2510,58 @@ def get_mode_of_payment_info(mode_of_payment, company):
@frappe.whitelist()
-def create_dunning(source_name, target_doc=None):
+def create_dunning(source_name, target_doc=None, ignore_permissions=False):
from frappe.model.mapper import get_mapped_doc
- from erpnext.accounts.doctype.dunning.dunning import (
- calculate_interest_and_amount,
- get_dunning_letter_text,
- )
+ def postprocess_dunning(source, target):
+ from erpnext.accounts.doctype.dunning.dunning import get_dunning_letter_text
- def set_missing_values(source, target):
- target.sales_invoice = source_name
- target.outstanding_amount = source.outstanding_amount
- overdue_days = (getdate(target.posting_date) - getdate(source.due_date)).days
- target.overdue_days = overdue_days
- if frappe.db.exists(
- "Dunning Type", {"start_day": ["<", overdue_days], "end_day": [">=", overdue_days]}
- ):
- dunning_type = frappe.get_doc(
- "Dunning Type", {"start_day": ["<", overdue_days], "end_day": [">=", overdue_days]}
- )
+ dunning_type = frappe.db.exists('Dunning Type', {'is_default': 1})
+ if dunning_type:
+ dunning_type = frappe.get_doc("Dunning Type", dunning_type)
target.dunning_type = dunning_type.name
target.rate_of_interest = dunning_type.rate_of_interest
target.dunning_fee = dunning_type.dunning_fee
- letter_text = get_dunning_letter_text(dunning_type=dunning_type.name, doc=target.as_dict())
- if letter_text:
- target.body_text = letter_text.get("body_text")
- target.closing_text = letter_text.get("closing_text")
- target.language = letter_text.get("language")
- amounts = calculate_interest_and_amount(
- target.outstanding_amount,
- target.rate_of_interest,
- target.dunning_fee,
- target.overdue_days,
+ letter_text = get_dunning_letter_text(
+ dunning_type=dunning_type.name,
+ doc=target.as_dict(),
+ language=source.language
)
- target.interest_amount = amounts.get("interest_amount")
- target.dunning_amount = amounts.get("dunning_amount")
- target.grand_total = amounts.get("grand_total")
- doclist = get_mapped_doc(
- "Sales Invoice",
- source_name,
- {
+ if letter_text:
+ target.body_text = letter_text.get('body_text')
+ target.closing_text = letter_text.get('closing_text')
+ target.language = letter_text.get('language')
+
+ def postprocess_overdue_payment(source, target, source_parent):
+ target.overdue_days = (getdate(nowdate()) - getdate(source.due_date)).days
+
+ return get_mapped_doc(
+ from_doctype="Sales Invoice",
+ from_docname=source_name,
+ table_maps={
"Sales Invoice": {
"doctype": "Dunning",
+ "field_map": {
+ "customer_address": "customer_address",
+ "parent": "sales_invoice"
+ },
+ },
+ "Payment Schedule": {
+ "doctype": "Overdue Payment",
+ "field_map": {
+ "name": "payment_schedule",
+ "parent": "sales_invoice"
+ },
+ "condition": lambda doc: doc.outstanding > 0,
+ "postprocess": postprocess_overdue_payment
}
},
- target_doc,
- set_missing_values,
+ target_doc=target_doc,
+ postprocess=postprocess_dunning,
+ ignore_permissions=ignore_permissions
)
- return doclist
+
def check_if_return_invoice_linked_with_payment_entry(self):
From 4f51dfe4c53d83d53fc80b8929bf2c35713111df Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 17:21:25 +0200
Subject: [PATCH 008/107] refactor: remove unnecessary code
---
erpnext/accounts/doctype/dunning/dunning.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 5158cc2b7f..7bc79e78fb 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -71,9 +71,6 @@ frappe.ui.form.on("Dunning", {
status: "Overdue",
company: frm.doc.company
},
- allow_child_item_selection: true,
- child_fielname: "payment_schedule",
- child_columns: ["due_date", "outstanding"]
});
});
}
From db47e1b69c5a2e35633c2017555a92271bd3bf76 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 17:21:52 +0200
Subject: [PATCH 009/107] feat: address and contact queries
---
erpnext/accounts/doctype/dunning/dunning.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 7bc79e78fb..73ed9c4261 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -24,6 +24,9 @@ frappe.ui.form.on("Dunning", {
};
});
+ frm.set_query('contact_person', erpnext.queries.contact_query);
+ frm.set_query('customer_address', erpnext.queries.address_query);
+
// cannot add rows manually, only via button "Fetch Overdue Payments"
frm.set_df_property("overdue_payments", "cannot_add_rows", true);
},
From b186f8e9d7b12ef599ba96db275c7733dcc0f504 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 17:22:25 +0200
Subject: [PATCH 010/107] feat: address display
---
erpnext/accounts/doctype/dunning/dunning.js | 6 ++++++
erpnext/accounts/doctype/dunning/dunning.json | 21 ++++++++++++-------
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 73ed9c4261..5777583dee 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -78,6 +78,12 @@ frappe.ui.form.on("Dunning", {
});
}
},
+ customer_address: function (frm) {
+ erpnext.utils.get_address_display(frm, "customer_address");
+ },
+ company_address: function (frm) {
+ erpnext.utils.get_address_display(frm, "company_address");
+ },
dunning_type: function (frm) {
frm.trigger("get_dunning_letter_text");
},
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index a0e3c150fd..85c73a8a74 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -21,10 +21,11 @@
"address_display",
"contact_person",
"contact_display",
+ "column_break_16",
+ "company_address",
+ "company_address_display",
"contact_mobile",
"contact_email",
- "column_break_18",
- "company_address_display",
"section_break_6",
"dunning_type",
"column_break_8",
@@ -206,15 +207,11 @@
"options": "Phone",
"read_only": 1
},
- {
- "fieldname": "column_break_18",
- "fieldtype": "Column Break"
- },
{
"fetch_from": "sales_invoice.company_address_display",
"fieldname": "company_address_display",
"fieldtype": "Small Text",
- "label": "Company Address",
+ "label": "Company Address Display",
"read_only": 1
},
{
@@ -346,6 +343,16 @@
"print_hide": 1,
"read_only": 1,
"report_hide": 1
+ },
+ {
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "company_address",
+ "fieldtype": "Link",
+ "label": "Company Address",
+ "options": "Address"
}
],
"is_submittable": 1,
From b07620aacf8fe4e003e8f78bc445b161f27cefc0 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 16 Sep 2021 17:22:46 +0200
Subject: [PATCH 011/107] feat: child table triggers calculation of totals
---
erpnext/accounts/doctype/dunning/dunning.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 5777583dee..ede5cf44b1 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -122,6 +122,12 @@ frappe.ui.form.on("Dunning", {
dunning_fee: function (frm) {
frm.trigger("calculate_totals");
},
+ overdue_payments_add: function(frm) {
+ frm.trigger("calculate_totals");
+ },
+ overdue_payments_remove: function (frm) {
+ frm.trigger("calculate_totals");
+ },
calculate_overdue_days: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
if (frm.doc.posting_date && row.due_date) {
From 9016baddcaaeb89c7bc4246bd28aef2a40a5b819 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 17 Sep 2021 11:43:09 +0200
Subject: [PATCH 012/107] feat: company address query + style
---
erpnext/accounts/doctype/dunning/dunning.js | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index ede5cf44b1..2ddfe80e61 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -24,8 +24,9 @@ frappe.ui.form.on("Dunning", {
};
});
- frm.set_query('contact_person', erpnext.queries.contact_query);
- frm.set_query('customer_address', erpnext.queries.address_query);
+ frm.set_query("contact_person", erpnext.queries.contact_query);
+ frm.set_query("customer_address", erpnext.queries.address_query);
+ frm.set_query("company_address", erpnext.queries.company_address_query);
// cannot add rows manually, only via button "Fetch Overdue Payments"
frm.set_df_property("overdue_payments", "cannot_add_rows", true);
@@ -48,7 +49,7 @@ frappe.ui.form.on("Dunning", {
}
if(frm.doc.docstatus > 0) {
- frm.add_custom_button(__('Ledger'), function() {
+ frm.add_custom_button(__("Ledger"), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
@@ -57,7 +58,7 @@ frappe.ui.form.on("Dunning", {
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
- }, __('View'));
+ }, __("View"));
}
if(frm.doc.docstatus === 0) {
@@ -151,8 +152,8 @@ frappe.ui.form.on("Dunning", {
.reduce((prev, cur) => prev + cur.interest_amount, 0);
const total_outstanding = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.outstanding, 0);
- const dunning_amount = flt(total_interest + frm.doc.dunning_fee, precision('dunning_amount'));
- const grand_total = flt(total_outstanding + dunning_amount, precision('grand_total'));
+ const dunning_amount = flt(total_interest + frm.doc.dunning_fee, precision("dunning_amount"));
+ const grand_total = flt(total_outstanding + dunning_amount, precision("grand_total"));
frm.set_value("total_outstanding", total_outstanding);
frm.set_value("total_interest", total_interest);
From 938f7d2266bde259c40c889014a0139c31e3138f Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 17 Sep 2021 11:58:24 +0200
Subject: [PATCH 013/107] reafctor: validate instead of postprocess
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 0aa6eab862..f240fe9b19 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2533,8 +2533,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
target.closing_text = letter_text.get('closing_text')
target.language = letter_text.get('language')
- def postprocess_overdue_payment(source, target, source_parent):
- target.overdue_days = (getdate(nowdate()) - getdate(source.due_date)).days
+ target.validate()
return get_mapped_doc(
from_doctype="Sales Invoice",
@@ -2553,8 +2552,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
"name": "payment_schedule",
"parent": "sales_invoice"
},
- "condition": lambda doc: doc.outstanding > 0,
- "postprocess": postprocess_overdue_payment
+ "condition": lambda doc: doc.outstanding > 0
}
},
target_doc=target_doc,
From 043066a2c8deabd1df2525e86f6558b6566528dd Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 17 Sep 2021 12:03:02 +0200
Subject: [PATCH 014/107] style: use double quotes
---
erpnext/accounts/doctype/dunning/dunning.py | 10 +++++-----
.../accounts/doctype/sales_invoice/sales_invoice.py | 8 ++++----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 56d49df4be..79de03cc71 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -21,7 +21,7 @@ class Dunning(AccountsController):
self.validate_totals()
if not self.income_account:
- self.income_account = frappe.get_cached_value("Company", self.company, "default_income_account")
+ self.income_account = frappe.db.get_value("Company", self.company, "default_income_account")
def validate_overdue_payments(self):
for row in self.overdue_payments:
@@ -36,13 +36,13 @@ class Dunning(AccountsController):
grand_total = flt(total_outstanding) + flt(dunning_amount)
if self.total_outstanding != total_outstanding:
- self.total_outstanding = flt(total_outstanding, self.precision('total_outstanding'))
+ self.total_outstanding = flt(total_outstanding, self.precision("total_outstanding"))
if self.total_interest != total_interest:
- self.total_interest = flt(total_interest, self.precision('total_interest'))
+ self.total_interest = flt(total_interest, self.precision("total_interest"))
if self.dunning_amount != dunning_amount:
- self.dunning_amount = flt(dunning_amount, self.precision('dunning_amount'))
+ self.dunning_amount = flt(dunning_amount, self.precision("dunning_amount"))
if self.grand_total != grand_total:
- self.grand_total = flt(grand_total, self.precision('grand_total'))
+ self.grand_total = flt(grand_total, self.precision("grand_total"))
def on_submit(self):
self.make_gl_entries()
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index f240fe9b19..05f8638794 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2516,7 +2516,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
def postprocess_dunning(source, target):
from erpnext.accounts.doctype.dunning.dunning import get_dunning_letter_text
- dunning_type = frappe.db.exists('Dunning Type', {'is_default': 1})
+ dunning_type = frappe.db.exists("Dunning Type", {"is_default": 1})
if dunning_type:
dunning_type = frappe.get_doc("Dunning Type", dunning_type)
target.dunning_type = dunning_type.name
@@ -2529,9 +2529,9 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
)
if letter_text:
- target.body_text = letter_text.get('body_text')
- target.closing_text = letter_text.get('closing_text')
- target.language = letter_text.get('language')
+ target.body_text = letter_text.get("body_text")
+ target.closing_text = letter_text.get("closing_text")
+ target.language = letter_text.get("language")
target.validate()
From 676ed6b881fcd02f10cb7e207e46119189ed55ca Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 17 Sep 2021 12:16:23 +0200
Subject: [PATCH 015/107] feat: hide fields in print
---
erpnext/accounts/doctype/dunning/dunning.json | 18 ++++++++++++------
.../overdue_payment/overdue_payment.json | 5 ++++-
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index 85c73a8a74..2f880d115d 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -126,13 +126,15 @@
"fieldname": "language",
"fieldtype": "Link",
"label": "Print Language",
- "options": "Language"
+ "options": "Language",
+ "print_hide": 1
},
{
"fieldname": "letter_head",
"fieldtype": "Link",
"label": "Letter Head",
- "options": "Letter Head"
+ "options": "Letter Head",
+ "print_hide": 1
},
{
"fieldname": "column_break_22",
@@ -294,13 +296,15 @@
"fieldname": "customer_address",
"fieldtype": "Link",
"label": "Customer Address",
- "options": "Address"
+ "options": "Address",
+ "print_hide": 1
},
{
"fieldname": "contact_person",
"fieldtype": "Link",
"label": "Contact Person",
- "options": "Contact"
+ "options": "Contact",
+ "print_hide": 1
},
{
"fieldname": "dunning_amount",
@@ -319,7 +323,8 @@
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
- "options": "Cost Center"
+ "options": "Cost Center",
+ "print_hide": 1
},
{
"collapsible": 1,
@@ -352,7 +357,8 @@
"fieldname": "company_address",
"fieldtype": "Link",
"label": "Company Address",
- "options": "Address"
+ "options": "Address",
+ "print_hide": 1
}
],
"is_submittable": 1,
diff --git a/erpnext/accounts/doctype/overdue_payment/overdue_payment.json b/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
index e5253bd12f..bc351d835a 100644
--- a/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
+++ b/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
@@ -113,6 +113,7 @@
"fieldname": "discounted_amount",
"fieldtype": "Currency",
"label": "Discounted Amount",
+ "print_hide": 1,
"read_only": 1
},
{
@@ -124,6 +125,7 @@
"fieldtype": "Currency",
"label": "Payment Amount (Company Currency)",
"options": "Company:company:default_currency",
+ "print_hide": 1,
"read_only": 1
},
{
@@ -138,6 +140,7 @@
"fieldname": "payment_schedule",
"fieldtype": "Data",
"label": "Payment Schedule",
+ "print_hide": 1,
"read_only": 1
},
{
@@ -158,7 +161,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-09-15 19:04:54.082880",
+ "modified": "2021-09-17 12:10:42.278923",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Overdue Payment",
From f143fe7dccc940c6d5b73d4eb3369089d4bfc1dc Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 17 Sep 2021 20:34:09 +0200
Subject: [PATCH 016/107] refactor: tests
---
.../accounts/doctype/dunning/test_dunning.py | 133 +++++++-----------
1 file changed, 50 insertions(+), 83 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index e1fd1e984f..956b1cfdbe 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -6,7 +6,7 @@ import unittest
import frappe
from frappe.utils import add_days, nowdate, today
-from erpnext.accounts.doctype.dunning.dunning import calculate_interest_and_amount
+from erpnext.accounts.doctype.sales_invoice.sales_invoice import create_dunning as create_dunning_from_sales_invoice
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
unlink_payment_on_cancel_of_invoice,
@@ -19,34 +19,34 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
class TestDunning(unittest.TestCase):
@classmethod
def setUpClass(self):
- create_dunning_type()
- create_dunning_type_with_zero_interest_rate()
+ create_dunning_type("First Notice", fee=0.0, interest=0.0, is_default=1)
+ create_dunning_type("Second Notice", fee=10.0, interest=10.0, is_default=0)
unlink_payment_on_cancel_of_invoice()
@classmethod
def tearDownClass(self):
unlink_payment_on_cancel_of_invoice(0)
- def test_dunning(self):
- dunning = create_dunning()
- amounts = calculate_interest_and_amount(
- dunning.outstanding_amount, dunning.rate_of_interest, dunning.dunning_fee, dunning.overdue_days
- )
- self.assertEqual(round(amounts.get("interest_amount"), 2), 0.44)
- self.assertEqual(round(amounts.get("dunning_amount"), 2), 20.44)
- self.assertEqual(round(amounts.get("grand_total"), 2), 120.44)
+ def test_first_dunning(self):
+ dunning = create_first_dunning()
- def test_dunning_with_zero_interest_rate(self):
- dunning = create_dunning_with_zero_interest_rate()
- amounts = calculate_interest_and_amount(
- dunning.outstanding_amount, dunning.rate_of_interest, dunning.dunning_fee, dunning.overdue_days
- )
- self.assertEqual(round(amounts.get("interest_amount"), 2), 0)
- self.assertEqual(round(amounts.get("dunning_amount"), 2), 20)
- self.assertEqual(round(amounts.get("grand_total"), 2), 120)
+ self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
+ self.assertEqual(round(dunning.total_interest, 2), 0.00)
+ self.assertEqual(round(dunning.dunning_fee, 2), 0.00)
+ self.assertEqual(round(dunning.dunning_amount, 2), 0.00)
+ self.assertEqual(round(dunning.grand_total, 2), 100.00)
+
+ def test_second_dunning(self):
+ dunning = create_second_dunning()
+
+ self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
+ self.assertEqual(round(dunning.total_interest, 2), 0.41)
+ self.assertEqual(round(dunning.dunning_fee, 2), 10.00)
+ self.assertEqual(round(dunning.dunning_amount, 2), 10.41)
+ self.assertEqual(round(dunning.grand_total, 2), 110.41)
def test_gl_entries(self):
- dunning = create_dunning()
+ dunning = create_second_dunning()
dunning.submit()
gl_entries = frappe.db.sql(
"""select account, debit, credit
@@ -56,16 +56,17 @@ class TestDunning(unittest.TestCase):
as_dict=1,
)
self.assertTrue(gl_entries)
- expected_values = dict(
- (d[0], d) for d in [["Debtors - _TC", 20.44, 0.0], ["Sales - _TC", 0.0, 20.44]]
- )
+ expected_values = dict((d[0], d) for d in [
+ ['Debtors - _TC', 10.41, 0.0],
+ ['Sales - _TC', 0.0, 10.41]
+ ])
for gle in gl_entries:
self.assertEqual(expected_values[gle.account][0], gle.account)
self.assertEqual(expected_values[gle.account][1], gle.debit)
self.assertEqual(expected_values[gle.account][2], gle.credit)
def test_payment_entry(self):
- dunning = create_dunning()
+ dunning = create_second_dunning()
dunning.submit()
pe = get_payment_entry("Dunning", dunning.name)
pe.reference_no = "1"
@@ -80,83 +81,49 @@ class TestDunning(unittest.TestCase):
self.assertEqual(si_doc.outstanding_amount, 0)
-def create_dunning():
+def create_first_dunning():
posting_date = add_days(today(), -20)
due_date = add_days(today(), -15)
sales_invoice = create_sales_invoice_against_cost_center(
- posting_date=posting_date, due_date=due_date, status="Overdue"
- )
- dunning_type = frappe.get_doc("Dunning Type", "First Notice")
- dunning = frappe.new_doc("Dunning")
- dunning.sales_invoice = sales_invoice.name
- dunning.customer_name = sales_invoice.customer_name
- dunning.outstanding_amount = sales_invoice.outstanding_amount
- dunning.debit_to = sales_invoice.debit_to
- dunning.currency = sales_invoice.currency
- dunning.company = sales_invoice.company
- dunning.posting_date = nowdate()
- dunning.due_date = sales_invoice.due_date
- dunning.dunning_type = "First Notice"
- dunning.rate_of_interest = dunning_type.rate_of_interest
- dunning.dunning_fee = dunning_type.dunning_fee
+ posting_date=posting_date, due_date=due_date, qty=1, rate=100)
+ dunning = create_dunning_from_sales_invoice(sales_invoice.name)
dunning.save()
+
return dunning
-def create_dunning_with_zero_interest_rate():
+def create_second_dunning():
posting_date = add_days(today(), -20)
due_date = add_days(today(), -15)
sales_invoice = create_sales_invoice_against_cost_center(
- posting_date=posting_date, due_date=due_date, status="Overdue"
- )
- dunning_type = frappe.get_doc("Dunning Type", "First Notice with 0% Rate of Interest")
- dunning = frappe.new_doc("Dunning")
- dunning.sales_invoice = sales_invoice.name
- dunning.customer_name = sales_invoice.customer_name
- dunning.outstanding_amount = sales_invoice.outstanding_amount
- dunning.debit_to = sales_invoice.debit_to
- dunning.currency = sales_invoice.currency
- dunning.company = sales_invoice.company
- dunning.posting_date = nowdate()
- dunning.due_date = sales_invoice.due_date
- dunning.dunning_type = "First Notice with 0% Rate of Interest"
+ posting_date=posting_date, due_date=due_date, qty=1, rate=100)
+ dunning = create_dunning_from_sales_invoice(sales_invoice.name)
+ dunning_type = frappe.get_doc("Dunning Type", "Second Notice")
+
+ dunning.dunning_type = dunning_type.name
dunning.rate_of_interest = dunning_type.rate_of_interest
dunning.dunning_fee = dunning_type.dunning_fee
dunning.save()
+
return dunning
-def create_dunning_type():
+def create_dunning_type(title, fee, interest, is_default):
+ existing = frappe.db.exists("Dunning Type", title)
+ if existing:
+ return frappe.get_doc("Dunning Type", existing)
+
dunning_type = frappe.new_doc("Dunning Type")
- dunning_type.dunning_type = "First Notice"
- dunning_type.start_day = 10
- dunning_type.end_day = 20
- dunning_type.dunning_fee = 20
- dunning_type.rate_of_interest = 8
+ dunning_type.dunning_type = title
+ dunning_type.is_default = is_default
+ dunning_type.dunning_fee = fee
+ dunning_type.rate_of_interest = interest
dunning_type.append(
- "dunning_letter_text",
- {
+ "dunning_letter_text", {
"language": "en",
- "body_text": "We have still not received payment for our invoice ",
- "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees.",
- },
- )
- dunning_type.save()
-
-
-def create_dunning_type_with_zero_interest_rate():
- dunning_type = frappe.new_doc("Dunning Type")
- dunning_type.dunning_type = "First Notice with 0% Rate of Interest"
- dunning_type.start_day = 10
- dunning_type.end_day = 20
- dunning_type.dunning_fee = 20
- dunning_type.rate_of_interest = 0
- dunning_type.append(
- "dunning_letter_text",
- {
- "language": "en",
- "body_text": "We have still not received payment for our invoice ",
- "closing_text": "We kindly request that you pay the outstanding amount immediately, and late fees.",
- },
+ "body_text": "We have still not received payment for our invoice",
+ "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
+ }
)
dunning_type.save()
+ return dunning_type
From 24e7a218392111ca3bbed85412adf935f9cd4496 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 17 Sep 2021 20:34:28 +0200
Subject: [PATCH 017/107] refactor: remove redndant argument
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 05f8638794..f8f7c3666a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2555,7 +2555,6 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
"condition": lambda doc: doc.outstanding > 0
}
},
- target_doc=target_doc,
postprocess=postprocess_dunning,
ignore_permissions=ignore_permissions
)
From df840cca75d3350c54230c6d67734f9b9e707073 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 23 Sep 2021 20:04:34 +0200
Subject: [PATCH 018/107] refactor: validate totals
---
erpnext/accounts/doctype/dunning/dunning.py | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 79de03cc71..e4b502a166 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -30,19 +30,10 @@ class Dunning(AccountsController):
row.interest_amount = (interest_per_year * cint(row.overdue_days)) / 365
def validate_totals(self):
- total_outstanding = sum(row.outstanding for row in self.overdue_payments)
- total_interest = sum(row.interest_amount for row in self.overdue_payments)
- dunning_amount = flt(total_interest) + flt(self.dunning_fee)
- grand_total = flt(total_outstanding) + flt(dunning_amount)
-
- if self.total_outstanding != total_outstanding:
- self.total_outstanding = flt(total_outstanding, self.precision("total_outstanding"))
- if self.total_interest != total_interest:
- self.total_interest = flt(total_interest, self.precision("total_interest"))
- if self.dunning_amount != dunning_amount:
- self.dunning_amount = flt(dunning_amount, self.precision("dunning_amount"))
- if self.grand_total != grand_total:
- self.grand_total = flt(grand_total, self.precision("grand_total"))
+ self.total_outstanding = sum(row.outstanding for row in self.overdue_payments)
+ self.total_interest = sum(row.interest for row in self.overdue_payments)
+ self.dunning_amount = self.total_interest + self.dunning_fee
+ self.grand_total = self.total_outstanding + self.dunning_amount
def on_submit(self):
self.make_gl_entries()
From be5fb94837a8fb894c2e649d18d33c4674545474 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 23 Sep 2021 20:09:53 +0200
Subject: [PATCH 019/107] feat: currency section , debit_to,
base_dunning_amount
---
erpnext/accounts/doctype/dunning/dunning.js | 117 +++++++++++++++++-
erpnext/accounts/doctype/dunning/dunning.json | 65 +++++++---
2 files changed, 156 insertions(+), 26 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 2ddfe80e61..45fcc4356d 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -23,7 +23,15 @@ frappe.ui.form.on("Dunning", {
}
};
});
-
+ frm.set_query("debit_to", () => {
+ return {
+ filters: {
+ "account_type": "Receivable",
+ "is_group": 0,
+ "company": frm.doc.company
+ }
+ }
+ });
frm.set_query("contact_person", erpnext.queries.contact_query);
frm.set_query("customer_address", erpnext.queries.address_query);
frm.set_query("company_address", erpnext.queries.company_address_query);
@@ -43,13 +51,13 @@ frappe.ui.form.on("Dunning", {
__("Payment"),
function () {
frm.events.make_payment_entry(frm);
- },__("Create")
+ }, __("Create")
);
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
- if(frm.doc.docstatus > 0) {
- frm.add_custom_button(__("Ledger"), function() {
+ if (frm.doc.docstatus > 0) {
+ frm.add_custom_button(__("Ledger"), function () {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
@@ -61,8 +69,8 @@ frappe.ui.form.on("Dunning", {
}, __("View"));
}
- if(frm.doc.docstatus === 0) {
- frm.add_custom_button(__("Fetch Overdue Payments"), function() {
+ if (frm.doc.docstatus === 0) {
+ frm.add_custom_button(__("Fetch Overdue Payments"), function () {
erpnext.utils.map_current_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
source_doctype: "Sales Invoice",
@@ -78,6 +86,103 @@ frappe.ui.form.on("Dunning", {
});
});
}
+
+ frappe.dynamic_link = { doc: frm.doc, fieldname: 'customer', doctype: 'Customer' }
+
+ frm.toggle_display("customer_name", (frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer));
+ },
+ // When multiple companies are set up. in case company name is changed set default company address
+ company: function (frm) {
+ if (frm.doc.company) {
+ frappe.call({
+ method: "erpnext.setup.doctype.company.company.get_default_company_address",
+ args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" },
+ debounce: 2000,
+ callback: function (r) {
+ if (r.message) {
+ frm.set_value("company_address", r.message)
+ }
+ else {
+ frm.set_value("company_address", "")
+ }
+ }
+ });
+
+ if (frm.fields_dict.currency) {
+ var company_currency = erpnext.get_currency(frm.doc.company);
+
+ if (!frm.doc.currency) {
+ frm.set_value("currency", company_currency);
+ }
+
+ if (frm.doc.currency == company_currency) {
+ frm.set_value("conversion_rate", 1.0);
+ }
+ }
+
+ var company_doc = frappe.get_doc(":Company", frm.doc.company);
+ if (company_doc.default_letter_head) {
+ if (frm.fields_dict.letter_head) {
+ frm.set_value("letter_head", company_doc.default_letter_head);
+ }
+ }
+ }
+ frm.trigger("set_debit_to");
+ },
+ set_debit_to: function(frm) {
+ if (frm.doc.customer && frm.doc.company) {
+ return frappe.call({
+ method: "erpnext.accounts.party.get_party_account",
+ args: {
+ company: frm.doc.company,
+ party_type: "Customer",
+ party: frm.doc.customer,
+ currency: erpnext.get_currency(frm.doc.company)
+ },
+ callback: function (r) {
+ if (!r.exc && r.message) {
+ frm.set_value("debit_to", r.message);
+ }
+ }
+ });
+ }
+ },
+ customer: function (frm) {
+ frm.trigger("set_debit_to");
+ },
+ currency: function (frm) {
+ // this.set_dynamic_labels();
+ var company_currency = erpnext.get_currency(frm.doc.company);
+ // Added `ignore_pricing_rule` to determine if document is loading after mapping from another doc
+ if(frm.doc.currency && frm.doc.currency !== company_currency) {
+ frappe.call({
+ method: "erpnext.setup.utils.get_exchange_rate",
+ args: {
+ transaction_date: transaction_date,
+ from_currency: frm.doc.currency,
+ to_currency: company_currency,
+ args: "for_selling"
+ },
+ freeze: true,
+ freeze_message: __("Fetching exchange rates ..."),
+ callback: function(r) {
+ const exchange_rate = flt(r.message);
+ if(exchange_rate != frm.doc.conversion_rate) {
+ frm.set_value("conversion_rate", exchange_rate);
+ }
+ }
+ });
+ } else {
+ frm.trigger("conversion_rate");
+ }
+ },
+ conversion_rate: function (frm) {
+ if(frm.doc.currency === erpnext.get_currency(frm.doc.company)) {
+ frm.set_value("conversion_rate", 1.0);
+ }
+
+ // Make read only if Accounts Settings doesn't allow stale rates
+ frm.set_df_property("conversion_rate", "read_only", erpnext.stale_rate_allowed() ? 0 : 1);
},
customer_address: function (frm) {
erpnext.utils.get_address_display(frm, "customer_address");
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index 2f880d115d..1dd05b77fa 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -9,13 +9,15 @@
"naming_series",
"customer",
"customer_name",
- "currency",
- "conversion_rate",
"column_break_3",
"company",
"posting_date",
"posting_time",
"status",
+ "section_break_9",
+ "currency",
+ "column_break_11",
+ "conversion_rate",
"address_and_contact_section",
"customer_address",
"address_display",
@@ -37,6 +39,7 @@
"dunning_fee",
"column_break_17",
"dunning_amount",
+ "base_dunning_amount",
"section_break_32",
"spacer",
"column_break_33",
@@ -51,6 +54,7 @@
"accounting_details_section",
"cost_center",
"income_account",
+ "debit_to",
"amended_from"
],
"fields": [
@@ -140,15 +144,6 @@
"fieldname": "column_break_22",
"fieldtype": "Column Break"
},
- {
- "fetch_from": "sales_invoice.currency",
- "fieldname": "currency",
- "fieldtype": "Link",
- "hidden": 1,
- "label": "Currency",
- "options": "Currency",
- "read_only": 1
- },
{
"fieldname": "amended_from",
"fieldtype": "Link",
@@ -248,7 +243,8 @@
"fieldtype": "Select",
"in_standard_filter": 1,
"label": "Status",
- "options": "Draft\nResolved\nUnresolved\nCancelled"
+ "options": "Draft\nResolved\nUnresolved\nCancelled",
+ "read_only": 1
},
{
"description": "For dunning fee and interest",
@@ -258,14 +254,6 @@
"options": "Account",
"print_hide": 1
},
- {
- "fetch_from": "sales_invoice.conversion_rate",
- "fieldname": "conversion_rate",
- "fieldtype": "Float",
- "hidden": 1,
- "label": "Conversion Rate",
- "read_only": 1
- },
{
"fieldname": "overdue_payments",
"fieldtype": "Table",
@@ -307,6 +295,7 @@
"print_hide": 1
},
{
+ "default": "0",
"fieldname": "dunning_amount",
"fieldtype": "Currency",
"label": "Dunning Amount",
@@ -359,6 +348,42 @@
"label": "Company Address",
"options": "Address",
"print_hide": 1
+ },
+ {
+ "fieldname": "debit_to",
+ "fieldtype": "Link",
+ "label": "Debit To",
+ "options": "Account",
+ "print_hide": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break",
+ "label": "Currency"
+ },
+ {
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "options": "Currency"
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "conversion_rate",
+ "fieldtype": "Float",
+ "label": "Conversion Rate"
+ },
+ {
+ "default": "0",
+ "fieldname": "base_dunning_amount",
+ "fieldtype": "Currency",
+ "label": "Dunning Amount (Company Currency)",
+ "options": "Company:company:default_currency",
+ "read_only": 1
}
],
"is_submittable": 1,
From bc40f3f425804595c50121aac2f9422dd014d0c1 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 23 Sep 2021 20:13:52 +0200
Subject: [PATCH 020/107] refactor: rename interest_amount to interest,
dunning_level
---
erpnext/accounts/doctype/dunning/dunning.js | 20 ++++-----
erpnext/accounts/doctype/dunning/dunning.py | 5 ++-
.../overdue_payment/overdue_payment.json | 44 +++++++++----------
3 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 45fcc4356d..98462b89db 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -200,7 +200,7 @@ frappe.ui.form.on("Dunning", {
if (frm.doc.dunning_type) {
frappe.call({
method:
- "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
+ "erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
args: {
dunning_type: frm.doc.dunning_type,
language: frm.doc.language,
@@ -223,12 +223,12 @@ frappe.ui.form.on("Dunning", {
frm.trigger("calculate_overdue_days");
},
rate_of_interest: function (frm) {
- frm.trigger("calculate_interest_amount");
+ frm.trigger("calculate_interest");
},
dunning_fee: function (frm) {
frm.trigger("calculate_totals");
},
- overdue_payments_add: function(frm) {
+ overdue_payments_add: function (frm) {
frm.trigger("calculate_totals");
},
overdue_payments_remove: function (frm) {
@@ -245,16 +245,16 @@ frappe.ui.form.on("Dunning", {
}
});
},
- calculate_interest_amount: function (frm) {
+ calculate_interest: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
- const interest_per_year = row.outstanding * frm.doc.rate_of_interest / 100;
- const interest_amount = flt((interest_per_year * cint(row.overdue_days)) / 365 || 0, precision("interest_amount"));
- frappe.model.set_value(row.doctype, row.name, "interest_amount", interest_amount);
+ const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
+ const interest = flt((interest_per_day * row.outstanding * cint(row.overdue_days)) / 365 || 0, precision("interest"));
+ frappe.model.set_value(row.doctype, row.name, "interest", interest);
});
},
calculate_totals: function (frm) {
const total_interest = frm.doc.overdue_payments
- .reduce((prev, cur) => prev + cur.interest_amount, 0);
+ .reduce((prev, cur) => prev + cur.interest, 0);
const total_outstanding = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.outstanding, 0);
const dunning_amount = flt(total_interest + frm.doc.dunning_fee, precision("dunning_amount"));
@@ -268,7 +268,7 @@ frappe.ui.form.on("Dunning", {
make_payment_entry: function (frm) {
return frappe.call({
method:
- "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
+ "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
@@ -282,7 +282,7 @@ frappe.ui.form.on("Dunning", {
});
frappe.ui.form.on("Overdue Payment", {
- interest_amount: function(frm, cdt, cdn) {
+ interest: function (frm, cdt, cdn) {
frm.trigger("calculate_totals");
}
});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index e4b502a166..f1283ae06f 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -24,10 +24,11 @@ class Dunning(AccountsController):
self.income_account = frappe.db.get_value("Company", self.company, "default_income_account")
def validate_overdue_payments(self):
+ daily_interest = self.rate_of_interest / 100 / 365
+
for row in self.overdue_payments:
row.overdue_days = (getdate(self.posting_date) - getdate(row.due_date)).days or 0
- interest_per_year = flt(row.outstanding) * flt(self.rate_of_interest) / 100
- row.interest_amount = (interest_per_year * cint(row.overdue_days)) / 365
+ row.interest = row.outstanding * daily_interest * row.overdue_days
def validate_totals(self):
self.total_outstanding = sum(row.outstanding for row in self.overdue_payments)
diff --git a/erpnext/accounts/doctype/overdue_payment/overdue_payment.json b/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
index bc351d835a..99e16469d0 100644
--- a/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
+++ b/erpnext/accounts/doctype/overdue_payment/overdue_payment.json
@@ -7,6 +7,7 @@
"field_order": [
"sales_invoice",
"payment_schedule",
+ "dunning_level",
"payment_term",
"section_break_15",
"description",
@@ -16,21 +17,18 @@
"mode_of_payment",
"column_break_5",
"invoice_portion",
- "section_break_9",
+ "section_break_16",
"payment_amount",
"outstanding",
"paid_amount",
"discounted_amount",
- "column_break_3",
- "base_payment_amount",
- "interest_amount"
+ "interest"
],
"fields": [
{
"columns": 2,
"fieldname": "payment_term",
"fieldtype": "Link",
- "in_list_view": 1,
"label": "Payment Term",
"options": "Payment Term",
"print_hide": 1,
@@ -79,10 +77,6 @@
"label": "Invoice Portion",
"read_only": 1
},
- {
- "fieldname": "section_break_9",
- "fieldtype": "Section Break"
- },
{
"columns": 2,
"fieldname": "payment_amount",
@@ -116,24 +110,13 @@
"print_hide": 1,
"read_only": 1
},
- {
- "fieldname": "column_break_3",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "base_payment_amount",
- "fieldtype": "Currency",
- "label": "Payment Amount (Company Currency)",
- "options": "Company:company:default_currency",
- "print_hide": 1,
- "read_only": 1
- },
{
"fieldname": "sales_invoice",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Sales Invoice",
"options": "Sales Invoice",
+ "read_only": 1,
"reqd": 1
},
{
@@ -151,17 +134,30 @@
"read_only": 1
},
{
- "fieldname": "interest_amount",
+ "default": "1",
+ "fieldname": "dunning_level",
+ "fieldtype": "Int",
+ "in_list_view": 1,
+ "label": "Dunning Level",
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_16",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "interest",
"fieldtype": "Currency",
"in_list_view": 1,
- "label": "Interest Amount",
+ "label": "Interest",
+ "options": "currency",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-09-17 12:10:42.278923",
+ "modified": "2021-09-23 13:48:27.898830",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Overdue Payment",
From 3895c03ba9305e02806272c7793430559d1d699f Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 23 Sep 2021 20:14:45 +0200
Subject: [PATCH 021/107] feat: change make_gl_entries to work with new data
structure
---
erpnext/accounts/doctype/dunning/dunning.py | 62 ++++++---------------
1 file changed, 18 insertions(+), 44 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index f1283ae06f..5194090743 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -5,11 +5,8 @@
import json
import frappe
-from frappe.utils import cint, flt, getdate
+from frappe.utils import getdate
-from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
- get_accounting_dimensions,
-)
from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
from erpnext.controllers.accounts_controller import AccountsController
@@ -47,57 +44,34 @@ class Dunning(AccountsController):
def make_gl_entries(self):
if not self.dunning_amount:
return
- gl_entries = []
- invoice_fields = [
- "project",
- "cost_center",
- "debit_to",
- "party_account_currency",
- "conversion_rate",
- "cost_center",
- ]
- inv = frappe.db.get_value("Sales Invoice", self.sales_invoice, invoice_fields, as_dict=1)
- accounting_dimensions = get_accounting_dimensions()
- invoice_fields.extend(accounting_dimensions)
+ cost_center = self.cost_center or frappe.get_cached_value("Company", self.company, "cost_center")
- dunning_in_company_currency = flt(self.dunning_amount * inv.conversion_rate)
- default_cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
-
- gl_entries.append(
- self.get_gl_dict(
- {
- "account": inv.debit_to,
+ make_gl_entries(
+ [
+ self.get_gl_dict({
+ "account": self.debit_to,
"party_type": "Customer",
"party": self.customer,
"due_date": self.due_date,
"against": self.income_account,
- "debit": dunning_in_company_currency,
+ "debit": self.dunning_amount,
"debit_in_account_currency": self.dunning_amount,
"against_voucher": self.name,
"against_voucher_type": "Dunning",
- "cost_center": inv.cost_center or default_cost_center,
- "project": inv.project,
- },
- inv.party_account_currency,
- item=inv,
- )
- )
- gl_entries.append(
- self.get_gl_dict(
- {
+ "cost_center": cost_center
+ }),
+ self.get_gl_dict({
"account": self.income_account,
"against": self.customer,
- "credit": dunning_in_company_currency,
- "cost_center": inv.cost_center or default_cost_center,
- "credit_in_account_currency": self.dunning_amount,
- "project": inv.project,
- },
- item=inv,
- )
- )
- make_gl_entries(
- gl_entries, cancel=(self.docstatus == 2), update_outstanding="No", merge_entries=False
+ "credit": self.dunning_amount,
+ "cost_center": cost_center,
+ "credit_in_account_currency": self.dunning_amount
+ })
+ ],
+ cancel=(self.docstatus == 2),
+ update_outstanding="No",
+ merge_entries=False
)
From 603117eb6bcd4319fc371f562bec0e96f2fbddbb Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 30 Sep 2021 16:23:18 +0200
Subject: [PATCH 022/107] feat: change print format to reflect doctype changes
---
.../accounts/print_format/dunning_letter/dunning_letter.json | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/print_format/dunning_letter/dunning_letter.json b/erpnext/accounts/print_format/dunning_letter/dunning_letter.json
index a7eac70b65..c48e1cf35b 100644
--- a/erpnext/accounts/print_format/dunning_letter/dunning_letter.json
+++ b/erpnext/accounts/print_format/dunning_letter/dunning_letter.json
@@ -1,4 +1,5 @@
{
+ "absolute_value": 0,
"align_labels_right": 0,
"creation": "2019-12-11 04:37:14.012805",
"css": ".print-format th {\n background-color: transparent !important;\n border-bottom: 1px solid !important;\n border-top: none !important;\n}\n.print-format .ql-editor {\n padding-left: 0px;\n padding-right: 0px;\n}\n\n.print-format table {\n margin-bottom: 0px;\n }\n.print-format .table-data tr:last-child { \n border-bottom: 1px solid !important;\n}\n\n.print-format .table-inner tr:last-child {\n border-bottom:none !important;\n}\n.print-format .table-inner {\n margin: 0px 0px;\n}\n\n.print-format .table-data ul li { \n color:#787878 !important;\n}\n\n.no-top-border {\n border-top:none !important;\n}\n\n.table-inner td {\n padding-left: 0px !important; \n padding-top: 1px !important;\n padding-bottom: 1px !important;\n color:#787878 !important;\n}\n\n.total {\n background-color: lightgrey !important;\n padding-top: 4px !important;\n padding-bottom: 4px !important;\n}\n",
@@ -9,10 +10,10 @@
"docstatus": 0,
"doctype": "Print Format",
"font": "Arial",
- "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"{{doc.customer_name}}
\\n{{doc.address_display}}\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n
{{_(doc.dunning_type)}}
\\n
{{ doc.name }}
\\n
\"}, {\"fieldname\": \"posting_date\", \"print_hide\": 0, \"label\": \"Date\"}, {\"fieldname\": \"sales_invoice\", \"print_hide\": 0, \"label\": \"Sales Invoice\"}, {\"fieldname\": \"due_date\", \"print_hide\": 0, \"label\": \"Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"body_text\", \"print_hide\": 0, \"label\": \"Body Text\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n \\n \\n {{_(\\\"Description\\\")}} | \\n\\t {{_(\\\"Amount\\\")}} | \\n
\\n \\n \\n {{_(\\\"Outstanding Amount\\\")}}\\n | \\n \\n {{doc.get_formatted(\\\"outstanding_amount\\\")}}\\n | \\n
\\n {%if doc.rate_of_interest > 0%}\\n \\n \\n {{_(\\\"Interest \\\")}} {{doc.rate_of_interest}}% p.a. ({{doc.overdue_days}} {{_(\\\"days\\\")}})\\n | \\n \\n {{doc.get_formatted(\\\"interest_amount\\\")}}\\n | \\n
\\n {% endif %}\\n {%if doc.dunning_fee > 0%}\\n \\n \\n {{_(\\\"Dunning Fee\\\")}}\\n | \\n \\n {{doc.get_formatted(\\\"dunning_fee\\\")}}\\n | \\n
\\n {% endif %}\\n \\n
\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n\\n\\t\\t
\\n\\t\\t\\t{{_(\\\"Grand Total\\\")}}
\\n\\t\\t
\\n\\t\\t\\t{{doc.get_formatted(\\\"grand_total\\\")}}\\n\\t\\t
\\n
\\n\\n\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"closing_text\", \"print_hide\": 0, \"label\": \"Closing Text\"}]",
+ "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"{{doc.customer_name}}
\\n{{doc.address_display}}\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n
{{_(doc.dunning_type)}}
\\n
{{ doc.name }}
\\n
\"}, {\"fieldname\": \"posting_date\", \"print_hide\": 0, \"label\": \"Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"body_text\", \"print_hide\": 0, \"label\": \"Body Text\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"overdue_payments\", \"print_hide\": 0, \"label\": \"Overdue Payments\", \"visible_columns\": [{\"fieldname\": \"sales_invoice\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"dunning_level\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"due_date\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"overdue_days\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"invoice_portion\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"outstanding\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"interest\", \"print_width\": \"\", \"print_hide\": 0}]}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"total_outstanding\", \"print_hide\": 0, \"label\": \"Total Outstanding\"}, {\"fieldname\": \"dunning_fee\", \"print_hide\": 0, \"label\": \"Dunning Fee\"}, {\"fieldname\": \"total_interest\", \"print_hide\": 0, \"label\": \"Total Interest\"}, {\"fieldname\": \"grand_total\", \"print_hide\": 0, \"label\": \"Grand Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"closing_text\", \"print_hide\": 0, \"label\": \"Closing Text\"}]",
"idx": 0,
"line_breaks": 0,
- "modified": "2020-07-14 18:25:44.348207",
+ "modified": "2021-09-30 10:22:02.603871",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning Letter",
From 16a23d9f0f69ce532ea406dee2b8421b9803c456 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 30 Sep 2021 17:37:35 +0200
Subject: [PATCH 023/107] refactor: dunning
---
erpnext/accounts/doctype/dunning/dunning.js | 35 ++++----
erpnext/accounts/doctype/dunning/dunning.py | 80 +++++++++----------
.../doctype/payment_entry/payment_entry.py | 36 +++------
3 files changed, 65 insertions(+), 86 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 98462b89db..5cee711950 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -56,19 +56,6 @@ frappe.ui.form.on("Dunning", {
frm.page.set_inner_btn_group_as_primary(__("Create"));
}
- if (frm.doc.docstatus > 0) {
- frm.add_custom_button(__("Ledger"), function () {
- frappe.route_options = {
- "voucher_no": frm.doc.name,
- "from_date": frm.doc.posting_date,
- "to_date": frm.doc.posting_date,
- "company": frm.doc.company,
- "show_cancelled_entries": frm.doc.docstatus === 2
- };
- frappe.set_route("query-report", "General Ledger");
- }, __("View"));
- }
-
if (frm.doc.docstatus === 0) {
frm.add_custom_button(__("Fetch Overdue Payments"), function () {
erpnext.utils.map_current_doc({
@@ -248,22 +235,29 @@ frappe.ui.form.on("Dunning", {
calculate_interest: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
- const interest = flt((interest_per_day * row.outstanding * cint(row.overdue_days)) / 365 || 0, precision("interest"));
+ const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest"));
frappe.model.set_value(row.doctype, row.name, "interest", interest);
});
},
calculate_totals: function (frm) {
+ debugger;
const total_interest = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.interest, 0);
const total_outstanding = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.outstanding, 0);
- const dunning_amount = flt(total_interest + frm.doc.dunning_fee, precision("dunning_amount"));
- const grand_total = flt(total_outstanding + dunning_amount, precision("grand_total"));
+ const dunning_amount = total_interest + frm.doc.dunning_fee;
+ const base_dunning_amount = dunning_amount * frm.doc.conversion_rate;
+ const grand_total = total_outstanding + dunning_amount;
- frm.set_value("total_outstanding", total_outstanding);
- frm.set_value("total_interest", total_interest);
- frm.set_value("dunning_amount", dunning_amount);
- frm.set_value("grand_total", grand_total);
+ function setWithPrecison(field, value) {
+ frm.set_value(field, flt(value, precision(field)));
+ }
+
+ setWithPrecison("total_outstanding", total_outstanding);
+ setWithPrecison("total_interest", total_interest);
+ setWithPrecison("dunning_amount", dunning_amount);
+ setWithPrecison("base_dunning_amount", base_dunning_amount);
+ setWithPrecison("grand_total", grand_total);
},
make_payment_entry: function (frm) {
return frappe.call({
@@ -283,6 +277,7 @@ frappe.ui.form.on("Dunning", {
frappe.ui.form.on("Overdue Payment", {
interest: function (frm, cdt, cdn) {
+ debugger;
frm.trigger("calculate_totals");
}
});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 5194090743..ec116f3061 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -1,24 +1,44 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
+"""
+# Accounting
+1. Payment of outstanding invoices with dunning amount
+
+ - Debit full amount to bank
+ - Credit invoiced amount to receivables
+ - Credit dunning amount to interest and similar revenue
+
+ -> Resolves dunning automatically
+"""
+from __future__ import unicode_literals
import json
import frappe
+
+from frappe import _
from frappe.utils import getdate
-from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
from erpnext.controllers.accounts_controller import AccountsController
class Dunning(AccountsController):
def validate(self):
+ self.validate_same_currency()
self.validate_overdue_payments()
self.validate_totals()
+ self.set_dunning_level()
- if not self.income_account:
- self.income_account = frappe.db.get_value("Company", self.company, "default_income_account")
+ def validate_same_currency(self):
+ """
+ Throw an error if invoice currency differs from dunning currency.
+ """
+ for row in self.overdue_payments:
+ invoice_currency = frappe.get_value("Sales Invoice", row.sales_invoice, "currency")
+ if invoice_currency != self.currency:
+ frappe.throw(_("The currency of invoice {} ({}) is different from the currency of this dunning ({}).").format(row.sales_invoice, invoice_currency, self.currency))
def validate_overdue_payments(self):
daily_interest = self.rate_of_interest / 100 / 365
@@ -31,51 +51,25 @@ class Dunning(AccountsController):
self.total_outstanding = sum(row.outstanding for row in self.overdue_payments)
self.total_interest = sum(row.interest for row in self.overdue_payments)
self.dunning_amount = self.total_interest + self.dunning_fee
+ self.base_dunning_amount = self.dunning_amount * self.conversion_rate
self.grand_total = self.total_outstanding + self.dunning_amount
- def on_submit(self):
- self.make_gl_entries()
-
- def on_cancel(self):
- if self.dunning_amount:
- self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
- make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
-
- def make_gl_entries(self):
- if not self.dunning_amount:
- return
-
- cost_center = self.cost_center or frappe.get_cached_value("Company", self.company, "cost_center")
-
- make_gl_entries(
- [
- self.get_gl_dict({
- "account": self.debit_to,
- "party_type": "Customer",
- "party": self.customer,
- "due_date": self.due_date,
- "against": self.income_account,
- "debit": self.dunning_amount,
- "debit_in_account_currency": self.dunning_amount,
- "against_voucher": self.name,
- "against_voucher_type": "Dunning",
- "cost_center": cost_center
- }),
- self.get_gl_dict({
- "account": self.income_account,
- "against": self.customer,
- "credit": self.dunning_amount,
- "cost_center": cost_center,
- "credit_in_account_currency": self.dunning_amount
- })
- ],
- cancel=(self.docstatus == 2),
- update_outstanding="No",
- merge_entries=False
- )
+ def set_dunning_level(self):
+ for row in self.overdue_payments:
+ past_dunnings = frappe.get_all("Overdue Payment",
+ filters={
+ "payment_schedule": row.payment_schedule,
+ "parent": ("!=", row.parent),
+ "docstatus": 1
+ }
+ )
+ row.dunning_level = len(past_dunnings) + 1
def resolve_dunning(doc, state):
+ """
+ Todo: refactor
+ """
for reference in doc.references:
if reference.reference_doctype == "Sales Invoice" and reference.outstanding_amount <= 0:
dunnings = frappe.get_list(
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index b6d3e5a30e..397e998f0b 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1849,30 +1849,20 @@ def get_payment_entry(
pe.append("references", reference)
else:
if dt == "Dunning":
- pe.append(
- "references",
- {
+ for overdue_payment in doc.overdue_payments:
+ pe.append("references", {
"reference_doctype": "Sales Invoice",
- "reference_name": doc.get("sales_invoice"),
- "bill_no": doc.get("bill_no"),
- "due_date": doc.get("due_date"),
- "total_amount": doc.get("outstanding_amount"),
- "outstanding_amount": doc.get("outstanding_amount"),
- "allocated_amount": doc.get("outstanding_amount"),
- },
- )
- pe.append(
- "references",
- {
- "reference_doctype": dt,
- "reference_name": dn,
- "bill_no": doc.get("bill_no"),
- "due_date": doc.get("due_date"),
- "total_amount": doc.get("dunning_amount"),
- "outstanding_amount": doc.get("dunning_amount"),
- "allocated_amount": doc.get("dunning_amount"),
- },
- )
+ "reference_name": overdue_payment.sales_invoice,
+ "payment_term": overdue_payment.payment_term,
+ "due_date": overdue_payment.due_date,
+ "total_amount": overdue_payment.outstanding,
+ "outstanding_amount": overdue_payment.outstanding,
+ "allocated_amount": overdue_payment.outstanding
+ })
+
+ pe.append("deductions", {
+ "amount": doc.dunning_amount
+ })
else:
pe.append(
"references",
From ff7ec977e6d75ff72d629ff3dabf5f6de0b2868f Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 5 Oct 2021 18:06:13 +0200
Subject: [PATCH 024/107] feat: more info for payment deductions
---
erpnext/accounts/doctype/payment_entry/payment_entry.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 397e998f0b..5793ecfe9a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1861,7 +1861,10 @@ def get_payment_entry(
})
pe.append("deductions", {
- "amount": doc.dunning_amount
+ "account": doc.income_account,
+ "cost_center": doc.cost_center,
+ "amount": doc.dunning_amount,
+ "description": _("Interest and/or dunning fee")
})
else:
pe.append(
From 6b6f4dd017790ef47384c984f5ada4ae7c9634dd Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 5 Oct 2021 18:18:23 +0200
Subject: [PATCH 025/107] refactor: run pre-commit
---
erpnext/accounts/doctype/dunning/dunning.py | 1 -
erpnext/accounts/doctype/dunning/test_dunning.py | 4 +++-
erpnext/accounts/doctype/overdue_payment/overdue_payment.py | 1 +
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index ec116f3061..81ec408344 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -16,7 +16,6 @@ from __future__ import unicode_literals
import json
import frappe
-
from frappe import _
from frappe.utils import getdate
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index 956b1cfdbe..499a03b591 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -6,11 +6,13 @@ import unittest
import frappe
from frappe.utils import add_days, nowdate, today
-from erpnext.accounts.doctype.sales_invoice.sales_invoice import create_dunning as create_dunning_from_sales_invoice
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
unlink_payment_on_cancel_of_invoice,
)
+from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
+ create_dunning as create_dunning_from_sales_invoice,
+)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
create_sales_invoice_against_cost_center,
)
diff --git a/erpnext/accounts/doctype/overdue_payment/overdue_payment.py b/erpnext/accounts/doctype/overdue_payment/overdue_payment.py
index e3820d74e0..6a543ad467 100644
--- a/erpnext/accounts/doctype/overdue_payment/overdue_payment.py
+++ b/erpnext/accounts/doctype/overdue_payment/overdue_payment.py
@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
+
class OverduePayment(Document):
pass
From 270040303ce490a0156078927168616e1662e8ec Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 5 Oct 2021 18:24:03 +0200
Subject: [PATCH 026/107] refactor: make sider happy
---
erpnext/accounts/doctype/dunning/dunning.js | 23 +++++++++------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 5cee711950..e5a5e1f8a4 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -30,7 +30,7 @@ frappe.ui.form.on("Dunning", {
"is_group": 0,
"company": frm.doc.company
}
- }
+ };
});
frm.set_query("contact_person", erpnext.queries.contact_query);
frm.set_query("customer_address", erpnext.queries.address_query);
@@ -74,7 +74,7 @@ frappe.ui.form.on("Dunning", {
});
}
- frappe.dynamic_link = { doc: frm.doc, fieldname: 'customer', doctype: 'Customer' }
+ frappe.dynamic_link = { doc: frm.doc, fieldname: 'customer', doctype: 'Customer' };
frm.toggle_display("customer_name", (frm.doc.customer_name && frm.doc.customer_name !== frm.doc.customer));
},
@@ -87,10 +87,9 @@ frappe.ui.form.on("Dunning", {
debounce: 2000,
callback: function (r) {
if (r.message) {
- frm.set_value("company_address", r.message)
- }
- else {
- frm.set_value("company_address", "")
+ frm.set_value("company_address", r.message);
+ } else {
+ frm.set_value("company_address", "");
}
}
});
@@ -141,11 +140,11 @@ frappe.ui.form.on("Dunning", {
// this.set_dynamic_labels();
var company_currency = erpnext.get_currency(frm.doc.company);
// Added `ignore_pricing_rule` to determine if document is loading after mapping from another doc
- if(frm.doc.currency && frm.doc.currency !== company_currency) {
+ if (frm.doc.currency && frm.doc.currency !== company_currency) {
frappe.call({
method: "erpnext.setup.utils.get_exchange_rate",
args: {
- transaction_date: transaction_date,
+ transaction_date: frm.doc.posting_date,
from_currency: frm.doc.currency,
to_currency: company_currency,
args: "for_selling"
@@ -154,7 +153,7 @@ frappe.ui.form.on("Dunning", {
freeze_message: __("Fetching exchange rates ..."),
callback: function(r) {
const exchange_rate = flt(r.message);
- if(exchange_rate != frm.doc.conversion_rate) {
+ if (exchange_rate != frm.doc.conversion_rate) {
frm.set_value("conversion_rate", exchange_rate);
}
}
@@ -164,7 +163,7 @@ frappe.ui.form.on("Dunning", {
}
},
conversion_rate: function (frm) {
- if(frm.doc.currency === erpnext.get_currency(frm.doc.company)) {
+ if (frm.doc.currency === erpnext.get_currency(frm.doc.company)) {
frm.set_value("conversion_rate", 1.0);
}
@@ -240,7 +239,6 @@ frappe.ui.form.on("Dunning", {
});
},
calculate_totals: function (frm) {
- debugger;
const total_interest = frm.doc.overdue_payments
.reduce((prev, cur) => prev + cur.interest, 0);
const total_outstanding = frm.doc.overdue_payments
@@ -276,8 +274,7 @@ frappe.ui.form.on("Dunning", {
});
frappe.ui.form.on("Overdue Payment", {
- interest: function (frm, cdt, cdn) {
- debugger;
+ interest: function (frm) {
frm.trigger("calculate_totals");
}
});
\ No newline at end of file
From ac8b6bba5ce8f8bddfe8094f1bb22b1c028a1d47 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 7 Oct 2021 13:04:09 +0200
Subject: [PATCH 027/107] feat: resolve dunning on payment entry
---
erpnext/accounts/doctype/dunning/dunning.py | 26 +++++++++++++++------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 81ec408344..941a91df5f 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -67,18 +67,30 @@ class Dunning(AccountsController):
def resolve_dunning(doc, state):
"""
- Todo: refactor
+ Check if all payments have been made and resolve dunning, if yes. Called
+ when a Payment Entry is submitted.
"""
for reference in doc.references:
if reference.reference_doctype == "Sales Invoice" and reference.outstanding_amount <= 0:
- dunnings = frappe.get_list(
- "Dunning",
- filters={"sales_invoice": reference.reference_name, "status": ("!=", "Resolved")},
- ignore_permissions=True,
+ unresolved_dunnings = frappe.get_all("Dunning",
+ filters={
+ "sales_invoice": reference.reference_name,
+ "status": ("!=", "Resolved")
+ },
+ pluck="name"
)
- for dunning in dunnings:
- frappe.db.set_value("Dunning", dunning.name, "status", "Resolved")
+ for dunning_name in unresolved_dunnings:
+ resolve = True
+ dunning = frappe.get_doc("Dunning", dunning_name)
+ for overdue_payment in dunning.overdue_payments:
+ outstanding = frappe.get_value("Payment Schedule", overdue_payment.payment_schedule, "outstanding")
+ if outstanding >= 0:
+ resolve = False
+
+ if resolve:
+ dunning.status = "Resolved"
+ dunning.save()
From c142d8995200e8e4d76ca36d1e4409e2d4abdd0d Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 7 Oct 2021 13:08:52 +0200
Subject: [PATCH 028/107] tests: remove obsolete test
---
.../accounts/doctype/dunning/test_dunning.py | 20 -------------------
1 file changed, 20 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index 499a03b591..f8acc6c025 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -47,26 +47,6 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.dunning_amount, 2), 10.41)
self.assertEqual(round(dunning.grand_total, 2), 110.41)
- def test_gl_entries(self):
- dunning = create_second_dunning()
- dunning.submit()
- gl_entries = frappe.db.sql(
- """select account, debit, credit
- from `tabGL Entry` where voucher_type='Dunning' and voucher_no=%s
- order by account asc""",
- dunning.name,
- as_dict=1,
- )
- self.assertTrue(gl_entries)
- expected_values = dict((d[0], d) for d in [
- ['Debtors - _TC', 10.41, 0.0],
- ['Sales - _TC', 0.0, 10.41]
- ])
- for gle in gl_entries:
- self.assertEqual(expected_values[gle.account][0], gle.account)
- self.assertEqual(expected_values[gle.account][1], gle.debit)
- self.assertEqual(expected_values[gle.account][2], gle.credit)
-
def test_payment_entry(self):
dunning = create_second_dunning()
dunning.submit()
From fd7be5da99a134a8dec426fd25a1e3fc503cf77a Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 7 Oct 2021 13:44:33 +0200
Subject: [PATCH 029/107] feat: remove obsolete "debit_to" field
---
erpnext/accounts/doctype/dunning/dunning.js | 32 +------------------
erpnext/accounts/doctype/dunning/dunning.json | 9 ------
2 files changed, 1 insertion(+), 40 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index e5a5e1f8a4..99b408a7a1 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -23,15 +23,7 @@ frappe.ui.form.on("Dunning", {
}
};
});
- frm.set_query("debit_to", () => {
- return {
- filters: {
- "account_type": "Receivable",
- "is_group": 0,
- "company": frm.doc.company
- }
- };
- });
+
frm.set_query("contact_person", erpnext.queries.contact_query);
frm.set_query("customer_address", erpnext.queries.address_query);
frm.set_query("company_address", erpnext.queries.company_address_query);
@@ -113,28 +105,6 @@ frappe.ui.form.on("Dunning", {
}
}
}
- frm.trigger("set_debit_to");
- },
- set_debit_to: function(frm) {
- if (frm.doc.customer && frm.doc.company) {
- return frappe.call({
- method: "erpnext.accounts.party.get_party_account",
- args: {
- company: frm.doc.company,
- party_type: "Customer",
- party: frm.doc.customer,
- currency: erpnext.get_currency(frm.doc.company)
- },
- callback: function (r) {
- if (!r.exc && r.message) {
- frm.set_value("debit_to", r.message);
- }
- }
- });
- }
- },
- customer: function (frm) {
- frm.trigger("set_debit_to");
},
currency: function (frm) {
// this.set_dynamic_labels();
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index 1dd05b77fa..fc2ccc7e5d 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -54,7 +54,6 @@
"accounting_details_section",
"cost_center",
"income_account",
- "debit_to",
"amended_from"
],
"fields": [
@@ -349,14 +348,6 @@
"options": "Address",
"print_hide": 1
},
- {
- "fieldname": "debit_to",
- "fieldtype": "Link",
- "label": "Debit To",
- "options": "Account",
- "print_hide": 1,
- "reqd": 1
- },
{
"fieldname": "section_break_9",
"fieldtype": "Section Break",
From 0990011e743119f251b99714ce546b6a96a24b05 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 7 Oct 2021 19:05:35 +0200
Subject: [PATCH 030/107] feat: add patch for dunning
---
erpnext/patches.txt | 1 +
.../patches/v14_0/single_to_multi_dunning.py | 46 +++++++++++++++++++
2 files changed, 47 insertions(+)
create mode 100644 erpnext/patches/v14_0/single_to_multi_dunning.py
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 18bd10f45f..03ef5de06e 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -339,3 +339,4 @@ execute:frappe.delete_doc('DocType', 'Cash Flow Mapper', ignore_missing=True)
execute:frappe.delete_doc('DocType', 'Cash Flow Mapping Template', ignore_missing=True)
execute:frappe.delete_doc('DocType', 'Cash Flow Mapping Accounts', ignore_missing=True)
erpnext.patches.v14_0.cleanup_workspaces
+erpnext.patches.v14_0.single_to_multi_dunning
diff --git a/erpnext/patches/v14_0/single_to_multi_dunning.py b/erpnext/patches/v14_0/single_to_multi_dunning.py
new file mode 100644
index 0000000000..40fba041ef
--- /dev/null
+++ b/erpnext/patches/v14_0/single_to_multi_dunning.py
@@ -0,0 +1,46 @@
+import frappe
+from erpnext.accounts.general_ledger import make_reverse_gl_entries
+
+def execute():
+ frappe.reload_doc("accounts", "doctype", "overdue_payment")
+ frappe.reload_doc("accounts", "doctype", "dunning")
+
+ all_dunnings = frappe.get_all("Dunning", pluck="name")
+ for dunning_name in all_dunnings:
+ dunning = frappe.get_doc("Dunning", dunning_name)
+ if not dunning.sales_invoice:
+ # nothing we can do
+ continue
+
+ if dunning.overdue_payments:
+ # something's already here, doesn't need patching
+ continue
+
+ payment_schedules = frappe.get_all("Payment Schedule",
+ filters={"parent": dunning.sales_invoice},
+ fields=[
+ "parent as sales_invoice",
+ "name as payment_schedule",
+ "payment_term",
+ "due_date",
+ "invoice_portion",
+ "payment_amount",
+ # at the time of creating this dunning, the full amount was outstanding
+ "payment_amount as outstanding",
+ "'0' as paid_amount",
+ "discounted_amount"
+ ]
+ )
+
+ dunning.extend("overdue_payments", payment_schedules)
+ dunning.validate()
+
+ dunning.flags.ignore_validate_update_after_submit = True
+ dunning.save()
+
+ if dunning.status != "Resolved":
+ # With the new logic, dunning amount gets recorded as additional income
+ # at time of payment. We don't want to record the dunning amount twice,
+ # so we reverse previous GL Entries that recorded the dunning amount at
+ # time of submission of the Dunning.
+ make_reverse_gl_entries(voucher_type="Dunning", voucher_no=dunning.name)
From 1250e56dd6fb5132385fa4e6c74276b436a02f23 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 12 Oct 2021 17:30:11 +0200
Subject: [PATCH 031/107] feat: add Dunning to Dunning Type's dashboard
---
.../accounts/doctype/dunning_type/dunning_type.json | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.json b/erpnext/accounts/doctype/dunning_type/dunning_type.json
index ca33ce58a9..b80a8b6666 100644
--- a/erpnext/accounts/doctype/dunning_type/dunning_type.json
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.json
@@ -63,8 +63,14 @@
"label": "Is Default"
}
],
- "links": [],
- "modified": "2021-09-16 15:00:02.610605",
+ "links": [
+ {
+ "link_doctype": "Dunning",
+ "link_fieldname": "dunning_type"
+ }
+ ],
+ "migration_hash": "3a2c71ceb1a15469ffe1eca6053656a0",
+ "modified": "2021-10-12 17:26:48.080519",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning Type",
From 24f400b12363e1804ea7e7dacfb522a849ccf247 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 12 Oct 2021 17:30:46 +0200
Subject: [PATCH 032/107] feat: remove Dunning dashboard as there are no
incoming links
---
.../accounts/doctype/dunning/dunning_dashboard.py | 12 ------------
1 file changed, 12 deletions(-)
delete mode 100644 erpnext/accounts/doctype/dunning/dunning_dashboard.py
diff --git a/erpnext/accounts/doctype/dunning/dunning_dashboard.py b/erpnext/accounts/doctype/dunning/dunning_dashboard.py
deleted file mode 100644
index d1d4031410..0000000000
--- a/erpnext/accounts/doctype/dunning/dunning_dashboard.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from frappe import _
-
-
-def get_data():
- return {
- "fieldname": "dunning",
- "non_standard_fieldnames": {
- "Journal Entry": "reference_name",
- "Payment Entry": "reference_name",
- },
- "transactions": [{"label": _("Payment"), "items": ["Payment Entry", "Journal Entry"]}],
- }
From c17ccb455d1507351ff89cf5d410a23d74901e27 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 12 Oct 2021 17:48:54 +0200
Subject: [PATCH 033/107] refactor: run pre-commit
---
erpnext/patches/v14_0/single_to_multi_dunning.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/erpnext/patches/v14_0/single_to_multi_dunning.py b/erpnext/patches/v14_0/single_to_multi_dunning.py
index 40fba041ef..af83ef7096 100644
--- a/erpnext/patches/v14_0/single_to_multi_dunning.py
+++ b/erpnext/patches/v14_0/single_to_multi_dunning.py
@@ -1,6 +1,8 @@
import frappe
+
from erpnext.accounts.general_ledger import make_reverse_gl_entries
+
def execute():
frappe.reload_doc("accounts", "doctype", "overdue_payment")
frappe.reload_doc("accounts", "doctype", "dunning")
@@ -39,7 +41,7 @@ def execute():
dunning.save()
if dunning.status != "Resolved":
- # With the new logic, dunning amount gets recorded as additional income
+ # With the new logic, dunning amount gets recorded as additional income
# at time of payment. We don't want to record the dunning amount twice,
# so we reverse previous GL Entries that recorded the dunning amount at
# time of submission of the Dunning.
From 9eeaac0c3efa480b1d45651f905756eb8a053b69 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 12 Oct 2021 18:35:02 +0200
Subject: [PATCH 034/107] feat: remove dunning as possible reference from
payment entry
---
.../doctype/payment_entry/payment_entry.py | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 5793ecfe9a..5da89a39db 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -386,7 +386,7 @@ class PaymentEntry(AccountsController):
def get_valid_reference_doctypes(self):
if self.party_type == "Customer":
- return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
+ return ("Sales Order", "Sales Invoice", "Journal Entry")
elif self.party_type == "Supplier":
return ("Purchase Order", "Purchase Invoice", "Journal Entry")
elif self.party_type == "Shareholder":
@@ -1693,11 +1693,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
ref_doc.company
)
- if reference_doctype == "Dunning":
- total_amount = outstanding_amount = ref_doc.get("dunning_amount")
- exchange_rate = 1
-
- elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1:
+ if reference_doctype == "Journal Entry" and ref_doc.docstatus == 1:
total_amount = ref_doc.get("total_amount")
if ref_doc.multi_currency:
exchange_rate = get_exchange_rate(
@@ -1930,7 +1926,7 @@ def get_bank_cash_account(doc, bank_account):
def set_party_type(dt):
- if dt in ("Sales Invoice", "Sales Order", "Dunning"):
+ if dt in ("Sales Invoice", "Sales Order"):
party_type = "Customer"
elif dt in ("Purchase Invoice", "Purchase Order"):
party_type = "Supplier"
@@ -1957,7 +1953,7 @@ def set_party_account_currency(dt, party_account, doc):
def set_payment_type(dt, doc):
if (
- dt == "Sales Order" or (dt in ("Sales Invoice", "Dunning") and doc.outstanding_amount > 0)
+ dt == "Sales Order" or (dt == "Sales Invoice" and doc.outstanding_amount > 0)
) or (dt == "Purchase Invoice" and doc.outstanding_amount < 0):
payment_type = "Receive"
else:
@@ -1975,9 +1971,6 @@ def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_curre
else:
grand_total = doc.rounded_total or doc.grand_total
outstanding_amount = doc.outstanding_amount
- elif dt == "Dunning":
- grand_total = doc.grand_total
- outstanding_amount = doc.grand_total
else:
if party_account_currency == doc.company_currency:
grand_total = flt(doc.get("base_rounded_total") or doc.get("base_grand_total"))
From 8652331d1c8c9a5f3d3d923b9be1b9e8ea1d5afe Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 21 Oct 2021 19:10:13 +0200
Subject: [PATCH 035/107] Revert "feat: remove dunning as possible reference
from payment entry"
This reverts commit b774d8d0e3c1e5a53b3422591b3f2d52ca959645.
---
.../doctype/payment_entry/payment_entry.py | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 5da89a39db..5793ecfe9a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -386,7 +386,7 @@ class PaymentEntry(AccountsController):
def get_valid_reference_doctypes(self):
if self.party_type == "Customer":
- return ("Sales Order", "Sales Invoice", "Journal Entry")
+ return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
elif self.party_type == "Supplier":
return ("Purchase Order", "Purchase Invoice", "Journal Entry")
elif self.party_type == "Shareholder":
@@ -1693,7 +1693,11 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
ref_doc.company
)
- if reference_doctype == "Journal Entry" and ref_doc.docstatus == 1:
+ if reference_doctype == "Dunning":
+ total_amount = outstanding_amount = ref_doc.get("dunning_amount")
+ exchange_rate = 1
+
+ elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1:
total_amount = ref_doc.get("total_amount")
if ref_doc.multi_currency:
exchange_rate = get_exchange_rate(
@@ -1926,7 +1930,7 @@ def get_bank_cash_account(doc, bank_account):
def set_party_type(dt):
- if dt in ("Sales Invoice", "Sales Order"):
+ if dt in ("Sales Invoice", "Sales Order", "Dunning"):
party_type = "Customer"
elif dt in ("Purchase Invoice", "Purchase Order"):
party_type = "Supplier"
@@ -1953,7 +1957,7 @@ def set_party_account_currency(dt, party_account, doc):
def set_payment_type(dt, doc):
if (
- dt == "Sales Order" or (dt == "Sales Invoice" and doc.outstanding_amount > 0)
+ dt == "Sales Order" or (dt in ("Sales Invoice", "Dunning") and doc.outstanding_amount > 0)
) or (dt == "Purchase Invoice" and doc.outstanding_amount < 0):
payment_type = "Receive"
else:
@@ -1971,6 +1975,9 @@ def set_grand_total_and_outstanding_amount(party_amount, dt, party_account_curre
else:
grand_total = doc.rounded_total or doc.grand_total
outstanding_amount = doc.outstanding_amount
+ elif dt == "Dunning":
+ grand_total = doc.grand_total
+ outstanding_amount = doc.grand_total
else:
if party_account_currency == doc.company_currency:
grand_total = flt(doc.get("base_rounded_total") or doc.get("base_grand_total"))
From e37f98267bb4691ef108fa81546335e741f56639 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 21 Oct 2021 20:53:26 +0200
Subject: [PATCH 036/107] fix: resolve dunning
---
erpnext/accounts/doctype/dunning/dunning.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 941a91df5f..0a55ff5f5f 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -84,8 +84,9 @@ def resolve_dunning(doc, state):
resolve = True
dunning = frappe.get_doc("Dunning", dunning_name)
for overdue_payment in dunning.overdue_payments:
- outstanding = frappe.get_value("Payment Schedule", overdue_payment.payment_schedule, "outstanding")
- if outstanding >= 0:
+ outstanding_inv = frappe.get_value("Sales Invoice", overdue_payment.sales_invoice, "outstanding_amount")
+ outstanding_ps = frappe.get_value("Payment Schedule", overdue_payment.payment_schedule, "outstanding")
+ if outstanding_ps > 0 and outstanding_inv > 0:
resolve = False
if resolve:
From 84459c719662e0cd04255f5d8273e65eb6c6bb5b Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 21 Oct 2021 20:55:22 +0200
Subject: [PATCH 037/107] fix: create payment entry
---
erpnext/accounts/doctype/payment_entry/payment_entry.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 5793ecfe9a..090308f6fd 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1863,7 +1863,7 @@ def get_payment_entry(
pe.append("deductions", {
"account": doc.income_account,
"cost_center": doc.cost_center,
- "amount": doc.dunning_amount,
+ "amount": -1 * doc.dunning_amount,
"description": _("Interest and/or dunning fee")
})
else:
@@ -1957,8 +1957,8 @@ def set_party_account_currency(dt, party_account, doc):
def set_payment_type(dt, doc):
if (
- dt == "Sales Order" or (dt in ("Sales Invoice", "Dunning") and doc.outstanding_amount > 0)
- ) or (dt == "Purchase Invoice" and doc.outstanding_amount < 0):
+ dt == "Sales Order" or (dt == "Sales Invoice" and doc.outstanding_amount > 0)
+ ) or (dt == "Purchase Invoice" and doc.outstanding_amount < 0) or dt == "Dunning":
payment_type = "Receive"
else:
payment_type = "Pay"
From d55c59f2985e8ef5dbaca91fc67e89af1112efe9 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 21 Oct 2021 20:57:23 +0200
Subject: [PATCH 038/107] test: make failing tests work
---
.../accounts/doctype/dunning/test_dunning.py | 34 +++++++++++--------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index f8acc6c025..b114fcec39 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -53,38 +53,43 @@ class TestDunning(unittest.TestCase):
pe = get_payment_entry("Dunning", dunning.name)
pe.reference_no = "1"
pe.reference_date = nowdate()
- pe.paid_from_account_currency = dunning.currency
- pe.paid_to_account_currency = dunning.currency
- pe.source_exchange_rate = 1
- pe.target_exchange_rate = 1
pe.insert()
pe.submit()
- si_doc = frappe.get_doc("Sales Invoice", dunning.sales_invoice)
- self.assertEqual(si_doc.outstanding_amount, 0)
+
+ for overdue_payment in dunning.overdue_payments:
+ outstanding_amount = frappe.get_value(
+ "Sales Invoice", overdue_payment.sales_invoice, "outstanding_amount"
+ )
+ self.assertEqual(outstanding_amount, 0)
+
+ dunning.reload()
+ self.assertEqual(dunning.status, "Resolved")
def create_first_dunning():
posting_date = add_days(today(), -20)
- due_date = add_days(today(), -15)
sales_invoice = create_sales_invoice_against_cost_center(
- posting_date=posting_date, due_date=due_date, qty=1, rate=100)
+ posting_date=posting_date, qty=1, rate=100
+ )
dunning = create_dunning_from_sales_invoice(sales_invoice.name)
+ dunning.income_account = "Interest Income Account - _TC"
dunning.save()
return dunning
def create_second_dunning():
- posting_date = add_days(today(), -20)
- due_date = add_days(today(), -15)
+ posting_date = add_days(today(), -15)
sales_invoice = create_sales_invoice_against_cost_center(
- posting_date=posting_date, due_date=due_date, qty=1, rate=100)
+ posting_date=posting_date, qty=1, rate=100
+ )
dunning = create_dunning_from_sales_invoice(sales_invoice.name)
dunning_type = frappe.get_doc("Dunning Type", "Second Notice")
dunning.dunning_type = dunning_type.name
dunning.rate_of_interest = dunning_type.rate_of_interest
dunning.dunning_fee = dunning_type.dunning_fee
+ dunning.income_account = "Interest Income Account - _TC"
dunning.save()
return dunning
@@ -101,11 +106,12 @@ def create_dunning_type(title, fee, interest, is_default):
dunning_type.dunning_fee = fee
dunning_type.rate_of_interest = interest
dunning_type.append(
- "dunning_letter_text", {
+ "dunning_letter_text",
+ {
"language": "en",
"body_text": "We have still not received payment for our invoice",
- "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
- }
+ "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees.",
+ },
)
dunning_type.save()
return dunning_type
From 0a06241e7c005f9a595f5a93b5f69dbe58cc54ab Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 22 Oct 2021 12:05:45 +0200
Subject: [PATCH 039/107] test: refactor, fix missing income account
---
.../accounts/doctype/dunning/test_dunning.py | 45 ++++++++++---------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index b114fcec39..4048f2a846 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -30,7 +30,7 @@ class TestDunning(unittest.TestCase):
unlink_payment_on_cancel_of_invoice(0)
def test_first_dunning(self):
- dunning = create_first_dunning()
+ dunning = create_dunning(overdue_days=20)
self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
self.assertEqual(round(dunning.total_interest, 2), 0.00)
@@ -39,7 +39,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.grand_total, 2), 100.00)
def test_second_dunning(self):
- dunning = create_second_dunning()
+ dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice")
self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
self.assertEqual(round(dunning.total_interest, 2), 0.41)
@@ -48,7 +48,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.grand_total, 2), 110.41)
def test_payment_entry(self):
- dunning = create_second_dunning()
+ dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice")
dunning.submit()
pe = get_payment_entry("Dunning", dunning.name)
pe.reference_no = "1"
@@ -66,30 +66,20 @@ class TestDunning(unittest.TestCase):
self.assertEqual(dunning.status, "Resolved")
-def create_first_dunning():
- posting_date = add_days(today(), -20)
+def create_dunning(overdue_days, dunning_type_name=None):
+ posting_date = add_days(today(), -1 * overdue_days)
sales_invoice = create_sales_invoice_against_cost_center(
posting_date=posting_date, qty=1, rate=100
)
dunning = create_dunning_from_sales_invoice(sales_invoice.name)
- dunning.income_account = "Interest Income Account - _TC"
- dunning.save()
- return dunning
+ if dunning_type_name:
+ dunning_type = frappe.get_doc("Dunning Type", dunning_type_name)
+ dunning.dunning_type = dunning_type.name
+ dunning.rate_of_interest = dunning_type.rate_of_interest
+ dunning.dunning_fee = dunning_type.dunning_fee
-
-def create_second_dunning():
- posting_date = add_days(today(), -15)
- sales_invoice = create_sales_invoice_against_cost_center(
- posting_date=posting_date, qty=1, rate=100
- )
- dunning = create_dunning_from_sales_invoice(sales_invoice.name)
- dunning_type = frappe.get_doc("Dunning Type", "Second Notice")
-
- dunning.dunning_type = dunning_type.name
- dunning.rate_of_interest = dunning_type.rate_of_interest
- dunning.dunning_fee = dunning_type.dunning_fee
- dunning.income_account = "Interest Income Account - _TC"
+ dunning.income_account = get_income_account(dunning.company)
dunning.save()
return dunning
@@ -115,3 +105,16 @@ def create_dunning_type(title, fee, interest, is_default):
)
dunning_type.save()
return dunning_type
+
+
+def get_income_account(company):
+ return frappe.get_value("Company", company, "default_income_account") or frappe.get_all(
+ "Account",
+ filters={"is_group": 0, "company": company},
+ or_filters={
+ "report_type": "Profit and Loss",
+ "account_type": ("in", ("Income Account", "Temporary")),
+ },
+ limit=1,
+ pluck="name",
+ )[0]
From 8bfe8657596168d9ebf921bbbd21b7a6d81fa37f Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Fri, 12 Nov 2021 23:24:08 +0100
Subject: [PATCH 040/107] fix: ignore cancelled dunnings
---
erpnext/accounts/doctype/dunning/dunning.py | 3 ++-
erpnext/patches/v14_0/single_to_multi_dunning.py | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 0a55ff5f5f..719f3698dc 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -75,7 +75,8 @@ def resolve_dunning(doc, state):
unresolved_dunnings = frappe.get_all("Dunning",
filters={
"sales_invoice": reference.reference_name,
- "status": ("!=", "Resolved")
+ "status": ("!=", "Resolved"),
+ "docstatus": ("!=", 2),
},
pluck="name"
)
diff --git a/erpnext/patches/v14_0/single_to_multi_dunning.py b/erpnext/patches/v14_0/single_to_multi_dunning.py
index af83ef7096..90966aa4cb 100644
--- a/erpnext/patches/v14_0/single_to_multi_dunning.py
+++ b/erpnext/patches/v14_0/single_to_multi_dunning.py
@@ -7,7 +7,7 @@ def execute():
frappe.reload_doc("accounts", "doctype", "overdue_payment")
frappe.reload_doc("accounts", "doctype", "dunning")
- all_dunnings = frappe.get_all("Dunning", pluck="name")
+ all_dunnings = frappe.get_all("Dunning", filters={"docstatus": ("!=", 2)}, pluck="name")
for dunning_name in all_dunnings:
dunning = frappe.get_doc("Dunning", dunning_name)
if not dunning.sales_invoice:
From 60b6afb470bd750d6cbac0e04a5f39c312a27765 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Sat, 13 Nov 2021 01:39:22 +0100
Subject: [PATCH 041/107] fix: fetch overdue payments
---
erpnext/accounts/doctype/dunning/dunning.js | 6 +++++-
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 3 ++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 99b408a7a1..c2b91690dc 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -49,10 +49,11 @@ frappe.ui.form.on("Dunning", {
}
if (frm.doc.docstatus === 0) {
- frm.add_custom_button(__("Fetch Overdue Payments"), function () {
+ frm.add_custom_button(__("Fetch Overdue Payments"), () => {
erpnext.utils.map_current_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
source_doctype: "Sales Invoice",
+ date_field: "due_date",
target: frm,
setters: {
customer: frm.doc.customer || undefined,
@@ -62,6 +63,9 @@ frappe.ui.form.on("Dunning", {
status: "Overdue",
company: frm.doc.company
},
+ allow_child_item_selection: true,
+ child_fielname: "payment_schedule",
+ child_columns: ["due_date", "outstanding"],
});
});
}
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index f8f7c3666a..3cce388e92 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2516,7 +2516,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
def postprocess_dunning(source, target):
from erpnext.accounts.doctype.dunning.dunning import get_dunning_letter_text
- dunning_type = frappe.db.exists("Dunning Type", {"is_default": 1})
+ dunning_type = frappe.db.exists("Dunning Type", {"is_default": 1, "company": source.company})
if dunning_type:
dunning_type = frappe.get_doc("Dunning Type", dunning_type)
target.dunning_type = dunning_type.name
@@ -2538,6 +2538,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
return get_mapped_doc(
from_doctype="Sales Invoice",
from_docname=source_name,
+ target_doc=target_doc,
table_maps={
"Sales Invoice": {
"doctype": "Dunning",
From 28dfbdda9375603bf53224c435535784d9e0fe13 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Sat, 13 Nov 2021 01:42:06 +0100
Subject: [PATCH 042/107] feat: fetch income account and cost center from
dunning type
---
erpnext/accounts/doctype/dunning/dunning.js | 8 ++++
erpnext/accounts/doctype/dunning/dunning.json | 10 +++-
.../doctype/dunning_type/dunning_type.js | 24 ++++++++--
.../doctype/dunning_type/dunning_type.json | 47 +++++++++++++++++--
.../doctype/dunning_type/dunning_type.py | 6 ++-
5 files changed, 83 insertions(+), 12 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index c2b91690dc..03553f775c 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -23,6 +23,14 @@ frappe.ui.form.on("Dunning", {
}
};
});
+ frm.set_query("cost_center", () => {
+ return {
+ filters: {
+ company: frm.doc.company,
+ is_group: 0
+ }
+ };
+ });
frm.set_query("contact_person", erpnext.queries.contact_query);
frm.set_query("customer_address", erpnext.queries.address_query);
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index fc2ccc7e5d..20e843c922 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -2,6 +2,7 @@
"actions": [],
"allow_events_in_timeline": 1,
"autoname": "naming_series:",
+ "beta": 1,
"creation": "2019-07-05 16:34:31.013238",
"doctype": "DocType",
"engine": "InnoDB",
@@ -52,8 +53,9 @@
"letter_head",
"closing_text",
"accounting_details_section",
- "cost_center",
"income_account",
+ "column_break_48",
+ "cost_center",
"amended_from"
],
"fields": [
@@ -247,6 +249,7 @@
},
{
"description": "For dunning fee and interest",
+ "fetch_from": "dunning_type.income_account",
"fieldname": "income_account",
"fieldtype": "Link",
"label": "Income Account",
@@ -308,6 +311,7 @@
"label": "Accounting Details"
},
{
+ "fetch_from": "dunning_type.cost_center",
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
@@ -375,6 +379,10 @@
"label": "Dunning Amount (Company Currency)",
"options": "Company:company:default_currency",
"read_only": 1
+ },
+ {
+ "fieldname": "column_break_48",
+ "fieldtype": "Column Break"
}
],
"is_submittable": 1,
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.js b/erpnext/accounts/doctype/dunning_type/dunning_type.js
index 54156b488d..b2c08c1c7f 100644
--- a/erpnext/accounts/doctype/dunning_type/dunning_type.js
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.js
@@ -1,8 +1,24 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-frappe.ui.form.on('Dunning Type', {
- // refresh: function(frm) {
-
- // }
+frappe.ui.form.on("Dunning Type", {
+ setup: function (frm) {
+ frm.set_query("income_account", () => {
+ return {
+ filters: {
+ root_type: "Income",
+ is_group: 0,
+ company: frm.doc.company,
+ },
+ };
+ });
+ frm.set_query("cost_center", () => {
+ return {
+ filters: {
+ is_group: 0,
+ company: frm.doc.company,
+ },
+ };
+ });
+ },
});
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.json b/erpnext/accounts/doctype/dunning_type/dunning_type.json
index b80a8b6666..5e39769735 100644
--- a/erpnext/accounts/doctype/dunning_type/dunning_type.json
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.json
@@ -1,7 +1,7 @@
{
"actions": [],
"allow_rename": 1,
- "autoname": "field:dunning_type",
+ "beta": 1,
"creation": "2019-12-04 04:59:08.003664",
"doctype": "DocType",
"editable_grid": 1,
@@ -9,12 +9,18 @@
"field_order": [
"dunning_type",
"is_default",
+ "column_break_3",
+ "company",
"section_break_6",
"dunning_fee",
"column_break_8",
"rate_of_interest",
"text_block_section",
- "dunning_letter_text"
+ "dunning_letter_text",
+ "section_break_9",
+ "income_account",
+ "column_break_13",
+ "cost_center"
],
"fields": [
{
@@ -61,6 +67,38 @@
"fieldname": "is_default",
"fieldtype": "Check",
"label": "Is Default"
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break",
+ "label": "Accounting Details"
+ },
+ {
+ "fieldname": "income_account",
+ "fieldtype": "Link",
+ "label": "Income Account",
+ "options": "Account"
+ },
+ {
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "label": "Cost Center",
+ "options": "Cost Center"
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break"
}
],
"links": [
@@ -69,12 +107,11 @@
"link_fieldname": "dunning_type"
}
],
- "migration_hash": "3a2c71ceb1a15469ffe1eca6053656a0",
- "modified": "2021-10-12 17:26:48.080519",
+ "modified": "2021-11-13 00:25:35.659283",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning Type",
- "naming_rule": "By fieldname",
+ "naming_rule": "By script",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.py b/erpnext/accounts/doctype/dunning_type/dunning_type.py
index 1b9bb9c032..b053eb51d6 100644
--- a/erpnext/accounts/doctype/dunning_type/dunning_type.py
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.py
@@ -2,9 +2,11 @@
# For license information, please see license.txt
-# import frappe
+import frappe
from frappe.model.document import Document
class DunningType(Document):
- pass
+ def autoname(self):
+ company_abbr = frappe.get_value("Company", self.company, "abbr")
+ self.name = self.dunning_type + " - " + company_abbr
From d790710ae73f3ff9c52141c02f645646daf07f6e Mon Sep 17 00:00:00 2001
From: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
Date: Mon, 29 Nov 2021 12:11:30 +0100
Subject: [PATCH 043/107] refactor: apply suggestions from code review
Co-authored-by: Himanshu
---
erpnext/accounts/doctype/dunning/dunning.js | 12 ++++--------
.../accounts/doctype/dunning_type/dunning_type.py | 2 +-
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 03553f775c..8930fcc6cb 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -90,16 +90,12 @@ frappe.ui.form.on("Dunning", {
args: { name: frm.doc.company, existing_address: frm.doc.company_address || "" },
debounce: 2000,
callback: function (r) {
- if (r.message) {
- frm.set_value("company_address", r.message);
- } else {
- frm.set_value("company_address", "");
- }
+ frm.set_value("company_address", r && r.message || "");
}
});
if (frm.fields_dict.currency) {
- var company_currency = erpnext.get_currency(frm.doc.company);
+ const company_currency = erpnext.get_currency(frm.doc.company);
if (!frm.doc.currency) {
frm.set_value("currency", company_currency);
@@ -110,7 +106,7 @@ frappe.ui.form.on("Dunning", {
}
}
- var company_doc = frappe.get_doc(":Company", frm.doc.company);
+ const company_doc = frappe.get_doc(":Company", frm.doc.company);
if (company_doc.default_letter_head) {
if (frm.fields_dict.letter_head) {
frm.set_value("letter_head", company_doc.default_letter_head);
@@ -120,7 +116,7 @@ frappe.ui.form.on("Dunning", {
},
currency: function (frm) {
// this.set_dynamic_labels();
- var company_currency = erpnext.get_currency(frm.doc.company);
+ const company_currency = erpnext.get_currency(frm.doc.company);
// Added `ignore_pricing_rule` to determine if document is loading after mapping from another doc
if (frm.doc.currency && frm.doc.currency !== company_currency) {
frappe.call({
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.py b/erpnext/accounts/doctype/dunning_type/dunning_type.py
index b053eb51d6..226e159a3b 100644
--- a/erpnext/accounts/doctype/dunning_type/dunning_type.py
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.py
@@ -9,4 +9,4 @@ from frappe.model.document import Document
class DunningType(Document):
def autoname(self):
company_abbr = frappe.get_value("Company", self.company, "abbr")
- self.name = self.dunning_type + " - " + company_abbr
+ self.name = f"{self.dunning_type} - {company_abbr}"
From 028d19f32dca25dc8fb111082f82482d082eec18 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 28 Dec 2021 19:31:18 +0100
Subject: [PATCH 044/107] test: link Dunning Type to COmpany
---
erpnext/accounts/doctype/dunning/test_dunning.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index 4048f2a846..925b7e5e55 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -92,6 +92,7 @@ def create_dunning_type(title, fee, interest, is_default):
dunning_type = frappe.new_doc("Dunning Type")
dunning_type.dunning_type = title
+ dunning_type.company = "_Test Company"
dunning_type.is_default = is_default
dunning_type.dunning_fee = fee
dunning_type.rate_of_interest = interest
From fd6d86eefc37d9447fb0c32cc13fa94a75e963ab Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 28 Dec 2021 23:50:05 +0100
Subject: [PATCH 045/107] fix: show "Create Dunning" when any scheduled payment
is overdue
---
.../accounts/doctype/sales_invoice/sales_invoice.js | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 8cb29505eb..6b0c2ee76f 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -138,8 +138,14 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
cur_frm.events.create_invoice_discounting(cur_frm);
}, __('Create'));
- if (doc.due_date < frappe.datetime.get_today()) {
- cur_frm.add_custom_button(__('Dunning'), function() {
+ const payment_is_overdue = doc.payment_schedule.map(
+ row => Date.parse(row.due_date) < Date.now()
+ ).reduce(
+ (prev, current) => prev || current
+ );
+
+ if (payment_is_overdue) {
+ cur_frm.add_custom_button(__('Dunning'), function () {
cur_frm.events.create_dunning(cur_frm);
}, __('Create'));
}
From 88f67e47862883a1084d137a8a150d9dcf0ad9e7 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Tue, 28 Dec 2021 23:51:32 +0100
Subject: [PATCH 046/107] fix: set income account and cost center
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 3cce388e92..d1494b7f7c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2522,6 +2522,8 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
target.dunning_type = dunning_type.name
target.rate_of_interest = dunning_type.rate_of_interest
target.dunning_fee = dunning_type.dunning_fee
+ target.income_account = dunning_type.income_account
+ target.cost_center = dunning_type.cost_center
letter_text = get_dunning_letter_text(
dunning_type=dunning_type.name,
doc=target.as_dict(),
From ccefe96665b651794fec79ce2ba4251563dd9cfc Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 29 Dec 2021 00:09:52 +0100
Subject: [PATCH 047/107] fix: map only overdue payments
---
.../doctype/sales_invoice/sales_invoice.py | 26 +++++++++----------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index d1494b7f7c..7b741495ea 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -622,9 +622,7 @@ class SalesInvoice(SellingController):
return
if not self.account_for_change_amount:
- self.account_for_change_amount = frappe.get_cached_value(
- "Company", self.company, "default_cash_account"
- )
+ self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account')
from erpnext.stock.get_item_details import get_pos_profile, get_pos_profile_item_details
@@ -1909,17 +1907,17 @@ def get_bank_cash_account(mode_of_payment, company):
@frappe.whitelist()
def make_maintenance_schedule(source_name, target_doc=None):
- doclist = get_mapped_doc(
- "Sales Invoice",
- source_name,
- {
- "Sales Invoice": {"doctype": "Maintenance Schedule", "validation": {"docstatus": ["=", 1]}},
- "Sales Invoice Item": {
- "doctype": "Maintenance Schedule Item",
- },
+ doclist = get_mapped_doc("Sales Invoice", source_name, {
+ "Sales Invoice": {
+ "doctype": "Maintenance Schedule",
+ "validation": {
+ "docstatus": ["=", 1]
+ }
},
- target_doc,
- )
+ "Sales Invoice Item": {
+ "doctype": "Maintenance Schedule Item",
+ },
+ }, target_doc)
return doclist
@@ -2555,7 +2553,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
"name": "payment_schedule",
"parent": "sales_invoice"
},
- "condition": lambda doc: doc.outstanding > 0
+ "condition": lambda doc: doc.outstanding > 0 and getdate(doc.due_date) < getdate(),
}
},
postprocess=postprocess_dunning,
From 4911c3b5b74f10115237528512154f5fd1d96053 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 29 Dec 2021 00:13:23 +0100
Subject: [PATCH 048/107] fix: precision for interst
---
erpnext/accounts/doctype/dunning/dunning.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 8930fcc6cb..a99b44ff1e 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -212,7 +212,7 @@ frappe.ui.form.on("Dunning", {
calculate_interest: function (frm) {
frm.doc.overdue_payments.forEach((row) => {
const interest_per_day = frm.doc.rate_of_interest / 100 / 365;
- const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest"));
+ const interest = flt((interest_per_day * row.overdue_days * row.outstanding), precision("interest", row));
frappe.model.set_value(row.doctype, row.name, "interest", interest);
});
},
From 04aaadcb3951453c488a662040b58e79e98e840e Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Mon, 3 Jan 2022 11:27:47 +0100
Subject: [PATCH 049/107] style: sider issues
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 7b741495ea..b2cd4a6d08 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -622,7 +622,7 @@ class SalesInvoice(SellingController):
return
if not self.account_for_change_amount:
- self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account')
+ self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account')
from erpnext.stock.get_item_details import get_pos_profile, get_pos_profile_item_details
@@ -1907,7 +1907,7 @@ def get_bank_cash_account(mode_of_payment, company):
@frappe.whitelist()
def make_maintenance_schedule(source_name, target_doc=None):
- doclist = get_mapped_doc("Sales Invoice", source_name, {
+ doclist = get_mapped_doc("Sales Invoice", source_name, {
"Sales Invoice": {
"doctype": "Maintenance Schedule",
"validation": {
From 315df7b2cf6261fb4656a8634026937d0e1007d8 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Mon, 3 Jan 2022 12:46:46 +0100
Subject: [PATCH 050/107] test: fix dunning test
---
.../accounts/doctype/dunning/test_dunning.py | 32 +++++++++++--------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index 925b7e5e55..129ca32d3a 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -6,6 +6,7 @@ import unittest
import frappe
from frappe.utils import add_days, nowdate, today
+from erpnext import get_default_cost_center
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
unlink_payment_on_cancel_of_invoice,
@@ -17,16 +18,19 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
create_sales_invoice_against_cost_center,
)
+test_dependencies = ["Company", "Cost Center"]
+
class TestDunning(unittest.TestCase):
@classmethod
- def setUpClass(self):
+ def setUpClass(cls):
create_dunning_type("First Notice", fee=0.0, interest=0.0, is_default=1)
create_dunning_type("Second Notice", fee=10.0, interest=10.0, is_default=0)
unlink_payment_on_cancel_of_invoice()
+ frappe.db.commit()
@classmethod
- def tearDownClass(self):
+ def tearDownClass(cls):
unlink_payment_on_cancel_of_invoice(0)
def test_first_dunning(self):
@@ -39,7 +43,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.grand_total, 2), 100.00)
def test_second_dunning(self):
- dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice")
+ dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice - _TC")
self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
self.assertEqual(round(dunning.total_interest, 2), 0.41)
@@ -48,7 +52,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.grand_total, 2), 110.41)
def test_payment_entry(self):
- dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice")
+ dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice - _TC")
dunning.submit()
pe = get_payment_entry("Dunning", dunning.name)
pe.reference_no = "1"
@@ -78,24 +82,25 @@ def create_dunning(overdue_days, dunning_type_name=None):
dunning.dunning_type = dunning_type.name
dunning.rate_of_interest = dunning_type.rate_of_interest
dunning.dunning_fee = dunning_type.dunning_fee
+ dunning.income_account = dunning_type.income_account
+ dunning.cost_center = dunning_type.cost_center
- dunning.income_account = get_income_account(dunning.company)
- dunning.save()
-
- return dunning
+ return dunning.save()
def create_dunning_type(title, fee, interest, is_default):
- existing = frappe.db.exists("Dunning Type", title)
- if existing:
- return frappe.get_doc("Dunning Type", existing)
+ company = "_Test Company"
+ if frappe.db.exists("Dunning Type", f"{title} - _TC"):
+ return
dunning_type = frappe.new_doc("Dunning Type")
dunning_type.dunning_type = title
- dunning_type.company = "_Test Company"
+ dunning_type.company = company
dunning_type.is_default = is_default
dunning_type.dunning_fee = fee
dunning_type.rate_of_interest = interest
+ dunning_type.income_account = get_income_account(company)
+ dunning_type.cost_center = get_default_cost_center(company)
dunning_type.append(
"dunning_letter_text",
{
@@ -104,8 +109,7 @@ def create_dunning_type(title, fee, interest, is_default):
"closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees.",
},
)
- dunning_type.save()
- return dunning_type
+ dunning_type.insert()
def get_income_account(company):
From 15816c8afd0ec35adb5eaf4fad07b0c43db3713f Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Mon, 3 Jan 2022 12:47:29 +0100
Subject: [PATCH 051/107] test: test records for dunning type
---
.../doctype/dunning_type/test_records.json | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 erpnext/accounts/doctype/dunning_type/test_records.json
diff --git a/erpnext/accounts/doctype/dunning_type/test_records.json b/erpnext/accounts/doctype/dunning_type/test_records.json
new file mode 100644
index 0000000000..cb589bf9ca
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning_type/test_records.json
@@ -0,0 +1,36 @@
+[
+ {
+ "doctype": "Dunning Type",
+ "dunning_type": "_Test First Notice",
+ "company": "_Test Company",
+ "is_default": 1,
+ "dunning_fee": 0.0,
+ "rate_of_interest": 0.0,
+ "dunning_letter_text": [
+ {
+ "language": "en",
+ "body_text": "We have still not received payment for our invoice",
+ "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
+ }
+ ],
+ "income_account": "Sales - _TC",
+ "cost_center": "_Test Cost Center"
+ },
+ {
+ "doctype": "Dunning Type",
+ "dunning_type": "_Test Second Notice",
+ "company": "_Test Company",
+ "is_default": 0,
+ "dunning_fee": 10.0,
+ "rate_of_interest": 10.0,
+ "dunning_letter_text": [
+ {
+ "language": "en",
+ "body_text": "We have still not received payment for our invoice",
+ "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
+ }
+ ],
+ "income_account": "Sales - _TC",
+ "cost_center": "_Test Cost Center"
+ }
+]
From 18495ed624c86d9f4cd0a75a87bedb70a0e74a04 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Mon, 3 Jan 2022 13:20:50 +0100
Subject: [PATCH 052/107] fix: semgrep issues
---
erpnext/accounts/doctype/dunning/test_dunning.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index 129ca32d3a..6125bd26c6 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -27,7 +27,6 @@ class TestDunning(unittest.TestCase):
create_dunning_type("First Notice", fee=0.0, interest=0.0, is_default=1)
create_dunning_type("Second Notice", fee=10.0, interest=10.0, is_default=0)
unlink_payment_on_cancel_of_invoice()
- frappe.db.commit()
@classmethod
def tearDownClass(cls):
From 772f6ffd212d564df1fa3b6f858e642ed9eb0d5b Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 14 Jun 2023 16:48:18 +0530
Subject: [PATCH 053/107] fix: Linter and incorrect cost center in test records
---
erpnext/accounts/doctype/dunning/dunning.py | 28 +++++++-----
.../accounts/doctype/dunning/test_dunning.py | 23 +++++-----
.../doctype/dunning_type/test_records.json | 4 +-
.../doctype/payment_entry/payment_entry.py | 42 ++++++++++--------
.../doctype/sales_invoice/sales_invoice.py | 43 ++++++++-----------
.../patches/v14_0/single_to_multi_dunning.py | 7 +--
6 files changed, 80 insertions(+), 67 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 719f3698dc..e0d75d3b47 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -23,7 +23,6 @@ from erpnext.controllers.accounts_controller import AccountsController
class Dunning(AccountsController):
-
def validate(self):
self.validate_same_currency()
self.validate_overdue_payments()
@@ -37,7 +36,11 @@ class Dunning(AccountsController):
for row in self.overdue_payments:
invoice_currency = frappe.get_value("Sales Invoice", row.sales_invoice, "currency")
if invoice_currency != self.currency:
- frappe.throw(_("The currency of invoice {} ({}) is different from the currency of this dunning ({}).").format(row.sales_invoice, invoice_currency, self.currency))
+ frappe.throw(
+ _(
+ "The currency of invoice {} ({}) is different from the currency of this dunning ({})."
+ ).format(row.sales_invoice, invoice_currency, self.currency)
+ )
def validate_overdue_payments(self):
daily_interest = self.rate_of_interest / 100 / 365
@@ -55,12 +58,13 @@ class Dunning(AccountsController):
def set_dunning_level(self):
for row in self.overdue_payments:
- past_dunnings = frappe.get_all("Overdue Payment",
+ past_dunnings = frappe.get_all(
+ "Overdue Payment",
filters={
"payment_schedule": row.payment_schedule,
"parent": ("!=", row.parent),
- "docstatus": 1
- }
+ "docstatus": 1,
+ },
)
row.dunning_level = len(past_dunnings) + 1
@@ -72,21 +76,26 @@ def resolve_dunning(doc, state):
"""
for reference in doc.references:
if reference.reference_doctype == "Sales Invoice" and reference.outstanding_amount <= 0:
- unresolved_dunnings = frappe.get_all("Dunning",
+ unresolved_dunnings = frappe.get_all(
+ "Dunning",
filters={
"sales_invoice": reference.reference_name,
"status": ("!=", "Resolved"),
"docstatus": ("!=", 2),
},
- pluck="name"
+ pluck="name",
)
for dunning_name in unresolved_dunnings:
resolve = True
dunning = frappe.get_doc("Dunning", dunning_name)
for overdue_payment in dunning.overdue_payments:
- outstanding_inv = frappe.get_value("Sales Invoice", overdue_payment.sales_invoice, "outstanding_amount")
- outstanding_ps = frappe.get_value("Payment Schedule", overdue_payment.payment_schedule, "outstanding")
+ outstanding_inv = frappe.get_value(
+ "Sales Invoice", overdue_payment.sales_invoice, "outstanding_amount"
+ )
+ outstanding_ps = frappe.get_value(
+ "Payment Schedule", overdue_payment.payment_schedule, "outstanding"
+ )
if outstanding_ps > 0 and outstanding_inv > 0:
resolve = False
@@ -95,7 +104,6 @@ def resolve_dunning(doc, state):
dunning.save()
-
@frappe.whitelist()
def get_dunning_letter_text(dunning_type, doc, language=None):
if isinstance(doc, str):
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index 6125bd26c6..be8c533d8d 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -112,13 +112,16 @@ def create_dunning_type(title, fee, interest, is_default):
def get_income_account(company):
- return frappe.get_value("Company", company, "default_income_account") or frappe.get_all(
- "Account",
- filters={"is_group": 0, "company": company},
- or_filters={
- "report_type": "Profit and Loss",
- "account_type": ("in", ("Income Account", "Temporary")),
- },
- limit=1,
- pluck="name",
- )[0]
+ return (
+ frappe.get_value("Company", company, "default_income_account")
+ or frappe.get_all(
+ "Account",
+ filters={"is_group": 0, "company": company},
+ or_filters={
+ "report_type": "Profit and Loss",
+ "account_type": ("in", ("Income Account", "Temporary")),
+ },
+ limit=1,
+ pluck="name",
+ )[0]
+ )
diff --git a/erpnext/accounts/doctype/dunning_type/test_records.json b/erpnext/accounts/doctype/dunning_type/test_records.json
index cb589bf9ca..7f28aab873 100644
--- a/erpnext/accounts/doctype/dunning_type/test_records.json
+++ b/erpnext/accounts/doctype/dunning_type/test_records.json
@@ -14,7 +14,7 @@
}
],
"income_account": "Sales - _TC",
- "cost_center": "_Test Cost Center"
+ "cost_center": "_Test Cost Center - _TC"
},
{
"doctype": "Dunning Type",
@@ -31,6 +31,6 @@
}
],
"income_account": "Sales - _TC",
- "cost_center": "_Test Cost Center"
+ "cost_center": "_Test Cost Center - _TC"
}
]
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 090308f6fd..2bd703f4bc 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1850,22 +1850,28 @@ def get_payment_entry(
else:
if dt == "Dunning":
for overdue_payment in doc.overdue_payments:
- pe.append("references", {
- "reference_doctype": "Sales Invoice",
- "reference_name": overdue_payment.sales_invoice,
- "payment_term": overdue_payment.payment_term,
- "due_date": overdue_payment.due_date,
- "total_amount": overdue_payment.outstanding,
- "outstanding_amount": overdue_payment.outstanding,
- "allocated_amount": overdue_payment.outstanding
- })
+ pe.append(
+ "references",
+ {
+ "reference_doctype": "Sales Invoice",
+ "reference_name": overdue_payment.sales_invoice,
+ "payment_term": overdue_payment.payment_term,
+ "due_date": overdue_payment.due_date,
+ "total_amount": overdue_payment.outstanding,
+ "outstanding_amount": overdue_payment.outstanding,
+ "allocated_amount": overdue_payment.outstanding,
+ },
+ )
- pe.append("deductions", {
- "account": doc.income_account,
- "cost_center": doc.cost_center,
- "amount": -1 * doc.dunning_amount,
- "description": _("Interest and/or dunning fee")
- })
+ pe.append(
+ "deductions",
+ {
+ "account": doc.income_account,
+ "cost_center": doc.cost_center,
+ "amount": -1 * doc.dunning_amount,
+ "description": _("Interest and/or dunning fee"),
+ },
+ )
else:
pe.append(
"references",
@@ -1957,8 +1963,10 @@ def set_party_account_currency(dt, party_account, doc):
def set_payment_type(dt, doc):
if (
- dt == "Sales Order" or (dt == "Sales Invoice" and doc.outstanding_amount > 0)
- ) or (dt == "Purchase Invoice" and doc.outstanding_amount < 0) or dt == "Dunning":
+ (dt == "Sales Order" or (dt == "Sales Invoice" and doc.outstanding_amount > 0))
+ or (dt == "Purchase Invoice" and doc.outstanding_amount < 0)
+ or dt == "Dunning"
+ ):
payment_type = "Receive"
else:
payment_type = "Pay"
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index b2cd4a6d08..e3a159ba58 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -622,7 +622,9 @@ class SalesInvoice(SellingController):
return
if not self.account_for_change_amount:
- self.account_for_change_amount = frappe.get_cached_value('Company', self.company, 'default_cash_account')
+ self.account_for_change_amount = frappe.get_cached_value(
+ "Company", self.company, "default_cash_account"
+ )
from erpnext.stock.get_item_details import get_pos_profile, get_pos_profile_item_details
@@ -1907,17 +1909,17 @@ def get_bank_cash_account(mode_of_payment, company):
@frappe.whitelist()
def make_maintenance_schedule(source_name, target_doc=None):
- doclist = get_mapped_doc("Sales Invoice", source_name, {
- "Sales Invoice": {
- "doctype": "Maintenance Schedule",
- "validation": {
- "docstatus": ["=", 1]
- }
+ doclist = get_mapped_doc(
+ "Sales Invoice",
+ source_name,
+ {
+ "Sales Invoice": {"doctype": "Maintenance Schedule", "validation": {"docstatus": ["=", 1]}},
+ "Sales Invoice Item": {
+ "doctype": "Maintenance Schedule Item",
+ },
},
- "Sales Invoice Item": {
- "doctype": "Maintenance Schedule Item",
- },
- }, target_doc)
+ target_doc,
+ )
return doclist
@@ -2523,9 +2525,7 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
target.income_account = dunning_type.income_account
target.cost_center = dunning_type.cost_center
letter_text = get_dunning_letter_text(
- dunning_type=dunning_type.name,
- doc=target.as_dict(),
- language=source.language
+ dunning_type=dunning_type.name, doc=target.as_dict(), language=source.language
)
if letter_text:
@@ -2542,26 +2542,19 @@ def create_dunning(source_name, target_doc=None, ignore_permissions=False):
table_maps={
"Sales Invoice": {
"doctype": "Dunning",
- "field_map": {
- "customer_address": "customer_address",
- "parent": "sales_invoice"
- },
+ "field_map": {"customer_address": "customer_address", "parent": "sales_invoice"},
},
"Payment Schedule": {
"doctype": "Overdue Payment",
- "field_map": {
- "name": "payment_schedule",
- "parent": "sales_invoice"
- },
+ "field_map": {"name": "payment_schedule", "parent": "sales_invoice"},
"condition": lambda doc: doc.outstanding > 0 and getdate(doc.due_date) < getdate(),
- }
+ },
},
postprocess=postprocess_dunning,
- ignore_permissions=ignore_permissions
+ ignore_permissions=ignore_permissions,
)
-
def check_if_return_invoice_linked_with_payment_entry(self):
# If a Return invoice is linked with payment entry along with other invoices,
# the cancellation of the Return causes allocated amount to be greater than paid
diff --git a/erpnext/patches/v14_0/single_to_multi_dunning.py b/erpnext/patches/v14_0/single_to_multi_dunning.py
index 90966aa4cb..7a8e591798 100644
--- a/erpnext/patches/v14_0/single_to_multi_dunning.py
+++ b/erpnext/patches/v14_0/single_to_multi_dunning.py
@@ -18,7 +18,8 @@ def execute():
# something's already here, doesn't need patching
continue
- payment_schedules = frappe.get_all("Payment Schedule",
+ payment_schedules = frappe.get_all(
+ "Payment Schedule",
filters={"parent": dunning.sales_invoice},
fields=[
"parent as sales_invoice",
@@ -30,8 +31,8 @@ def execute():
# at the time of creating this dunning, the full amount was outstanding
"payment_amount as outstanding",
"'0' as paid_amount",
- "discounted_amount"
- ]
+ "discounted_amount",
+ ],
)
dunning.extend("overdue_payments", payment_schedules)
From 4673aa412e0e2aec1bc82df4b7264f6fd6f3c680 Mon Sep 17 00:00:00 2001
From: marination
Date: Thu, 15 Jun 2023 15:47:18 +0530
Subject: [PATCH 054/107] fix: Broken pop-up and references to non-existent
field
- `child_fieldname` misspelled causing broken pop up to fetch overdue payments
- `sales_invoice` referenced in dunning fields, which has been removed
- Fetch `customer_name` from `customer` link field
---
erpnext/accounts/doctype/dunning/dunning.js | 2 +-
erpnext/accounts/doctype/dunning/dunning.json | 10 ++--------
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index a99b44ff1e..8171bb93ef 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -72,7 +72,7 @@ frappe.ui.form.on("Dunning", {
company: frm.doc.company
},
allow_child_item_selection: true,
- child_fielname: "payment_schedule",
+ child_fieldname: "payment_schedule",
child_columns: ["due_date", "outstanding"],
});
});
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
index 20e843c922..b7e8aeaaaf 100644
--- a/erpnext/accounts/doctype/dunning/dunning.json
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -75,7 +75,7 @@
"print_hide": 1
},
{
- "fetch_from": "sales_invoice.customer_name",
+ "fetch_from": "customer.customer_name",
"fieldname": "customer_name",
"fieldtype": "Data",
"in_list_view": 1,
@@ -184,21 +184,18 @@
"label": "Address and Contact"
},
{
- "fetch_from": "sales_invoice.address_display",
"fieldname": "address_display",
"fieldtype": "Small Text",
"label": "Address",
"read_only": 1
},
{
- "fetch_from": "sales_invoice.contact_display",
"fieldname": "contact_display",
"fieldtype": "Small Text",
"label": "Contact",
"read_only": 1
},
{
- "fetch_from": "sales_invoice.contact_mobile",
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"label": "Mobile No",
@@ -206,14 +203,12 @@
"read_only": 1
},
{
- "fetch_from": "sales_invoice.company_address_display",
"fieldname": "company_address_display",
"fieldtype": "Small Text",
"label": "Company Address Display",
"read_only": 1
},
{
- "fetch_from": "sales_invoice.contact_email",
"fieldname": "contact_email",
"fieldtype": "Data",
"label": "Contact Email",
@@ -221,7 +216,6 @@
"read_only": 1
},
{
- "fetch_from": "sales_invoice.customer",
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer",
@@ -387,7 +381,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2023-06-03 16:24:01.677026",
+ "modified": "2023-06-15 15:46:53.865712",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning",
From 254bab33da379d223751149414921145a631981e Mon Sep 17 00:00:00 2001
From: marination
Date: Thu, 15 Jun 2023 19:00:24 +0530
Subject: [PATCH 055/107] fix: Consider installments/partial payments while
back updating Dunning
- Also use data from Overdue Payment table and not just Dunning parent document
---
erpnext/accounts/doctype/dunning/dunning.py | 33 ++++++++++++++-------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index e0d75d3b47..1daaf0682a 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -75,16 +75,12 @@ def resolve_dunning(doc, state):
when a Payment Entry is submitted.
"""
for reference in doc.references:
- if reference.reference_doctype == "Sales Invoice" and reference.outstanding_amount <= 0:
- unresolved_dunnings = frappe.get_all(
- "Dunning",
- filters={
- "sales_invoice": reference.reference_name,
- "status": ("!=", "Resolved"),
- "docstatus": ("!=", 2),
- },
- pluck="name",
- )
+ # Consider partial and full payments
+ if (
+ reference.reference_doctype == "Sales Invoice"
+ and reference.outstanding_amount < reference.total_amount
+ ):
+ unresolved_dunnings = get_unresolved_dunnings(reference.reference_name)
for dunning_name in unresolved_dunnings:
resolve = True
@@ -104,6 +100,23 @@ def resolve_dunning(doc, state):
dunning.save()
+def get_unresolved_dunnings(sales_invoice):
+ dunning = frappe.qb.DocType("Dunning")
+ overdue_payment = frappe.qb.DocType("Overdue Payment")
+
+ return (
+ frappe.qb.from_(dunning)
+ .join(overdue_payment)
+ .on(overdue_payment.parent == dunning.name)
+ .select(dunning.name)
+ .where(
+ (dunning.status != "Resolved")
+ & (dunning.docstatus != 2)
+ & (overdue_payment.sales_invoice == sales_invoice)
+ )
+ ).run(as_dict=True)
+
+
@frappe.whitelist()
def get_dunning_letter_text(dunning_type, doc, language=None):
if isinstance(doc, str):
From c32113918ea92038aae94461fd61e6bcc8ade626 Mon Sep 17 00:00:00 2001
From: marination
Date: Thu, 15 Jun 2023 20:04:54 +0530
Subject: [PATCH 056/107] fix: Updation of dunning on PE cancellation
---
erpnext/accounts/doctype/dunning/dunning.py | 35 ++++++++++++---------
erpnext/hooks.py | 1 +
2 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 1daaf0682a..1447ac03f0 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -75,16 +75,23 @@ def resolve_dunning(doc, state):
when a Payment Entry is submitted.
"""
for reference in doc.references:
- # Consider partial and full payments
- if (
- reference.reference_doctype == "Sales Invoice"
- and reference.outstanding_amount < reference.total_amount
- ):
- unresolved_dunnings = get_unresolved_dunnings(reference.reference_name)
+ # Consider partial and full payments:
+ # Submitting full payment: outstanding_amount will be 0
+ # Submitting 1st partial payment: outstanding_amount will be the pending installment
+ # Cancelling full payment: outstanding_amount will revert to total amount
+ # Cancelling last partial payment: outstanding_amount will revert to pending amount
+ submit_condition = reference.outstanding_amount < reference.total_amount
+ cancel_condition = reference.outstanding_amount <= reference.total_amount
- for dunning_name in unresolved_dunnings:
+ if reference.reference_doctype == "Sales Invoice" and (
+ submit_condition if doc.docstatus == 1 else cancel_condition
+ ):
+ state = "Resolved" if doc.docstatus == 2 else "Unresolved"
+ dunnings = get_linked_dunnings_as_per_state(reference.reference_name, state)
+
+ for dunning in dunnings:
resolve = True
- dunning = frappe.get_doc("Dunning", dunning_name)
+ dunning = frappe.get_doc("Dunning", dunning.get("name"))
for overdue_payment in dunning.overdue_payments:
outstanding_inv = frappe.get_value(
"Sales Invoice", overdue_payment.sales_invoice, "outstanding_amount"
@@ -92,15 +99,13 @@ def resolve_dunning(doc, state):
outstanding_ps = frappe.get_value(
"Payment Schedule", overdue_payment.payment_schedule, "outstanding"
)
- if outstanding_ps > 0 and outstanding_inv > 0:
- resolve = False
+ resolve = False if (outstanding_ps > 0 and outstanding_inv > 0) else True
- if resolve:
- dunning.status = "Resolved"
- dunning.save()
+ dunning.status = "Resolved" if resolve else "Unresolved"
+ dunning.save()
-def get_unresolved_dunnings(sales_invoice):
+def get_linked_dunnings_as_per_state(sales_invoice, state):
dunning = frappe.qb.DocType("Dunning")
overdue_payment = frappe.qb.DocType("Overdue Payment")
@@ -110,7 +115,7 @@ def get_unresolved_dunnings(sales_invoice):
.on(overdue_payment.parent == dunning.name)
.select(dunning.name)
.where(
- (dunning.status != "Resolved")
+ (dunning.status == state)
& (dunning.docstatus != 2)
& (overdue_payment.sales_invoice == sales_invoice)
)
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index c821fcf4e6..6d64f64d1d 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -334,6 +334,7 @@ doc_events = {
"erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status",
"erpnext.accounts.doctype.dunning.dunning.resolve_dunning",
],
+ "on_cancel": ["erpnext.accounts.doctype.dunning.dunning.resolve_dunning"],
"on_trash": "erpnext.regional.check_deletion_permission",
},
"Address": {
From 47852803f0bbe578ffcb4160170eaf0120a1eb4c Mon Sep 17 00:00:00 2001
From: marination
Date: Fri, 16 Jun 2023 14:10:07 +0530
Subject: [PATCH 057/107] fix: Set Address via JS and Py files (for API
usecases)
---
erpnext/accounts/doctype/dunning/dunning.js | 3 +++
erpnext/accounts/doctype/dunning/dunning.py | 29 +++++++++++++++++++--
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 8171bb93ef..7c4e9529a7 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -140,6 +140,9 @@ frappe.ui.form.on("Dunning", {
frm.trigger("conversion_rate");
}
},
+ customer: (frm) => {
+ erpnext.utils.get_party_details(frm);
+ },
conversion_rate: function (frm) {
if (frm.doc.currency === erpnext.get_currency(frm.doc.company)) {
frm.set_value("conversion_rate", 1.0);
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 1447ac03f0..c8cfbca27d 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -11,12 +11,11 @@
-> Resolves dunning automatically
"""
-from __future__ import unicode_literals
-
import json
import frappe
from frappe import _
+from frappe.contacts.doctype.address.address import get_address_display
from frappe.utils import getdate
from erpnext.controllers.accounts_controller import AccountsController
@@ -27,6 +26,7 @@ class Dunning(AccountsController):
self.validate_same_currency()
self.validate_overdue_payments()
self.validate_totals()
+ self.set_party_details()
self.set_dunning_level()
def validate_same_currency(self):
@@ -56,6 +56,31 @@ class Dunning(AccountsController):
self.base_dunning_amount = self.dunning_amount * self.conversion_rate
self.grand_total = self.total_outstanding + self.dunning_amount
+ def set_party_details(self):
+ from erpnext.accounts.party import _get_party_details
+
+ party_details = _get_party_details(
+ self.customer,
+ ignore_permissions=self.flags.ignore_permissions,
+ doctype=self.doctype,
+ company=self.company,
+ posting_date=self.get("posting_date"),
+ fetch_payment_terms_template=False,
+ party_address=self.customer_address,
+ company_address=self.get("company_address"),
+ )
+ for field in [
+ "customer_address",
+ "address_display",
+ "company_address",
+ "contact_person",
+ "contact_display",
+ "contact_mobile",
+ ]:
+ self.set(field, party_details.get(field))
+
+ self.set("company_address_display", get_address_display(self.company_address))
+
def set_dunning_level(self):
for row in self.overdue_payments:
past_dunnings = frappe.get_all(
From 8f2e5288ff8d1651b8d41a7c7b977e99b65506c4 Mon Sep 17 00:00:00 2001
From: marination
Date: Tue, 20 Jun 2023 11:47:04 +0530
Subject: [PATCH 058/107] test: Dunning and PE against partially due invoice
- Check if the right payment portion is picked
- Check if the SI and Dunning are updated on submission and cancellation of PE
---
erpnext/accounts/doctype/dunning/dunning.js | 2 +-
erpnext/accounts/doctype/dunning/dunning.py | 2 +-
.../accounts/doctype/dunning/test_dunning.py | 86 +++++++++++++++++--
3 files changed, 80 insertions(+), 10 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
index 7c4e9529a7..1ac909e745 100644
--- a/erpnext/accounts/doctype/dunning/dunning.js
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Dunning", {
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index c8cfbca27d..9d0d36b970 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
"""
# Accounting
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index be8c533d8d..b29ace275f 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -1,9 +1,7 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
-
-import unittest
-
import frappe
+from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, nowdate, today
from erpnext import get_default_cost_center
@@ -21,9 +19,10 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
test_dependencies = ["Company", "Cost Center"]
-class TestDunning(unittest.TestCase):
+class TestDunning(FrappeTestCase):
@classmethod
def setUpClass(cls):
+ super().setUpClass()
create_dunning_type("First Notice", fee=0.0, interest=0.0, is_default=1)
create_dunning_type("Second Notice", fee=10.0, interest=10.0, is_default=0)
unlink_payment_on_cancel_of_invoice()
@@ -31,8 +30,9 @@ class TestDunning(unittest.TestCase):
@classmethod
def tearDownClass(cls):
unlink_payment_on_cancel_of_invoice(0)
+ super().tearDownClass()
- def test_first_dunning(self):
+ def test_dunning_without_fees(self):
dunning = create_dunning(overdue_days=20)
self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
@@ -41,7 +41,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.dunning_amount, 2), 0.00)
self.assertEqual(round(dunning.grand_total, 2), 100.00)
- def test_second_dunning(self):
+ def test_dunning_with_fees_and_interest(self):
dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice - _TC")
self.assertEqual(round(dunning.total_outstanding, 2), 100.00)
@@ -50,7 +50,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(dunning.dunning_amount, 2), 10.41)
self.assertEqual(round(dunning.grand_total, 2), 110.41)
- def test_payment_entry(self):
+ def test_dunning_with_payment_entry(self):
dunning = create_dunning(overdue_days=15, dunning_type_name="Second Notice - _TC")
dunning.submit()
pe = get_payment_entry("Dunning", dunning.name)
@@ -68,6 +68,44 @@ class TestDunning(unittest.TestCase):
dunning.reload()
self.assertEqual(dunning.status, "Resolved")
+ def test_dunning_and_payment_against_partially_due_invoice(self):
+ """
+ Create SI with first installment overdue. Check impact of Dunning and Payment Entry.
+ """
+ create_payment_terms_template_for_dunning()
+ sales_invoice = create_sales_invoice_against_cost_center(
+ posting_date=add_days(today(), -1 * 6),
+ qty=1,
+ rate=100,
+ do_not_submit=True,
+ )
+ sales_invoice.payment_terms_template = "_Test 50-50 for Dunning"
+ sales_invoice.submit()
+ dunning = create_dunning_from_sales_invoice(sales_invoice.name)
+
+ self.assertEqual(len(dunning.overdue_payments), 1)
+ self.assertEqual(dunning.overdue_payments[0].payment_term, "_Test Payment Term 1 for Dunning")
+
+ dunning.submit()
+ pe = get_payment_entry("Dunning", dunning.name)
+ pe.reference_no, pe.reference_date = "2", nowdate()
+ pe.insert()
+ pe.submit()
+ sales_invoice.load_from_db()
+ dunning.load_from_db()
+
+ self.assertEqual(sales_invoice.status, "Partly Paid")
+ self.assertEqual(sales_invoice.payment_schedule[0].outstanding, 0)
+ self.assertEqual(dunning.status, "Resolved")
+
+ # Test impact on cancellation of PE
+ pe.cancel()
+ sales_invoice.reload()
+ dunning.reload()
+
+ self.assertEqual(sales_invoice.status, "Overdue")
+ self.assertEqual(dunning.status, "Unresolved")
+
def create_dunning(overdue_days, dunning_type_name=None):
posting_date = add_days(today(), -1 * overdue_days)
@@ -125,3 +163,35 @@ def get_income_account(company):
pluck="name",
)[0]
)
+
+
+def create_payment_terms_template_for_dunning():
+ from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_term
+
+ create_payment_term("_Test Payment Term 1 for Dunning")
+ create_payment_term("_Test Payment Term 2 for Dunning")
+
+ if not frappe.db.exists("Payment Terms Template", "_Test 50-50 for Dunning"):
+ frappe.get_doc(
+ {
+ "doctype": "Payment Terms Template",
+ "template_name": "_Test 50-50 for Dunning",
+ "allocate_payment_based_on_payment_terms": 1,
+ "terms": [
+ {
+ "doctype": "Payment Terms Template Detail",
+ "payment_term": "_Test Payment Term 1 for Dunning",
+ "invoice_portion": 50.00,
+ "credit_days_based_on": "Day(s) after invoice date",
+ "credit_days": 5,
+ },
+ {
+ "doctype": "Payment Terms Template Detail",
+ "payment_term": "_Test Payment Term 2 for Dunning",
+ "invoice_portion": 50.00,
+ "credit_days_based_on": "Day(s) after invoice date",
+ "credit_days": 10,
+ },
+ ],
+ }
+ ).insert()
From 5a952987a316185f50d80e7a646d8edb84512105 Mon Sep 17 00:00:00 2001
From: marination
Date: Wed, 28 Jun 2023 17:13:34 +0530
Subject: [PATCH 059/107] fix: Use `this.frm` (Linter)
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 053b1a324c..d21a50c1c3 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -149,8 +149,8 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
);
if (payment_is_overdue) {
- cur_frm.add_custom_button(__('Dunning'), function () {
- cur_frm.events.create_dunning(cur_frm);
+ this.frm.add_custom_button(__('Dunning'), () => {
+ this.frm.events.create_dunning(this.frm);
}, __('Create'));
}
}
From da72bd98196623fd2246a1a9129991efbb65ab13 Mon Sep 17 00:00:00 2001
From: Florian HENRY
Date: Fri, 30 Jun 2023 15:11:45 +0200
Subject: [PATCH 060/107] feat: add Lead to Adresse And contact report
---
.../selling/report/address_and_contacts/address_and_contacts.js | 2 +-
.../selling/report/address_and_contacts/address_and_contacts.py | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.js b/erpnext/selling/report/address_and_contacts/address_and_contacts.js
index ef87586f66..8aa14d1998 100644
--- a/erpnext/selling/report/address_and_contacts/address_and_contacts.js
+++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.js
@@ -13,7 +13,7 @@ frappe.query_reports["Address And Contacts"] = {
"get_query": function() {
return {
"filters": {
- "name": ["in","Customer,Supplier,Sales Partner"],
+ "name": ["in","Customer,Supplier,Sales Partner,Lead"],
}
}
}
diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.py b/erpnext/selling/report/address_and_contacts/address_and_contacts.py
index 9a1cfda847..4542bdff43 100644
--- a/erpnext/selling/report/address_and_contacts/address_and_contacts.py
+++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.py
@@ -130,6 +130,7 @@ def get_party_group(party_type):
"Customer": "customer_group",
"Supplier": "supplier_group",
"Sales Partner": "partner_type",
+ "Lead": "status",
}
return group[party_type]
From a939431d48efc05896a356e8fd4993e59af6c6cb Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Mon, 3 Jul 2023 21:03:24 +0200
Subject: [PATCH 061/107] fix: german translations
---
erpnext/translations/de.csv | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 26a775e9de..c02aeb2f83 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -3079,9 +3079,9 @@ Total Leaves,insgesamt Blätter,
Total Order Considered,Geschätzte Summe der Bestellungen,
Total Order Value,Gesamtbestellwert,
Total Outgoing,Summe Auslieferungen,
-Total Outstanding,Absolut aussergewöhnlich,
-Total Outstanding Amount,Offener Gesamtbetrag,
-Total Outstanding: {0},Gesamtsumme: {0},
+Total Outstanding,Summe ausstehende Beträge,
+Total Outstanding Amount,Summe ausstehende Beträge,
+Total Outstanding: {0},Summe ausstehende Beträge: {0},
Total Paid Amount,Summe gezahlte Beträge,
Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total,Der gesamte Zahlungsbetrag im Zahlungsplan muss gleich Groß / Abgerundet sein,
Total Payments,Gesamtzahlungen,
@@ -8537,13 +8537,14 @@ If this is unchecked Journal Entries will be saved in a Draft state and will hav
Enable Distributed Cost Center,Aktivieren Sie die verteilte Kostenstelle,
Distributed Cost Center,Verteilte Kostenstelle,
Dunning,Mahnung,
+Dunning Level,Mahnstufe,
DUNN-.MM.-.YY.-,DUNN-.MM .-. YY.-,
Overdue Days,Überfällige Tage,
Dunning Type,Mahnart,
Dunning Fee,Mahngebühr,
Dunning Amount,Mahnbetrag,
-Resolved,Aufgelöst,
-Unresolved,Ungelöst,
+Resolved,Geklärt,
+Unresolved,Ungeklärt,
Printing Setting,Druckeinstellung,
Body Text,Hauptteil,
Closing Text,Text schließen,
@@ -8723,7 +8724,7 @@ Company {0} already exists. Continuing will overwrite the Company and Chart of A
Meta Data,Metadaten,
Unresolve,Auflösen,
Create Document,Dokument erstellen,
-Mark as unresolved,Als ungelöst markieren,
+Mark as unresolved,Als ungeklärt markieren,
TaxJar Settings,TaxJar-Einstellungen,
Sandbox Mode,Sandbox-Modus,
Enable Tax Calculation,Steuerberechnung aktivieren,
From dd8c3d5462c97f34d03f76f6e797391ad401b56d Mon Sep 17 00:00:00 2001
From: Gursheen Anand
Date: Wed, 12 Jul 2023 10:00:18 +0530
Subject: [PATCH 062/107] feat: filter based on accounting dimension in
profitability analysis
---
.../profitability_analysis.js | 15 ++++++++++++++-
.../profitability_analysis.py | 10 +++++++---
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
index 889ede5a82..4412212d2e 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
@@ -16,10 +16,23 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"fieldname": "based_on",
"label": __("Based On"),
"fieldtype": "Select",
- "options": ["Cost Center", "Project"],
+ "options": ["Cost Center", "Project", "Accounting Dimension"],
"default": "Cost Center",
"reqd": 1
},
+ {
+ "fieldname": "accounting_dimension",
+ "label": __("Accounting Dimension"),
+ "fieldtype": "Link",
+ "options": "Accounting Dimension",
+ "get_query": () =>{
+ return {
+ filters: {
+ "disabled": 0
+ }
+ }
+ }
+ },
{
"fieldname": "fiscal_year",
"label": __("Fiscal Year"),
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
index 183e279fe5..c05aa94457 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
@@ -16,8 +16,8 @@ value_fields = ("income", "expense", "gross_profit_loss")
def execute(filters=None):
- if not filters.get("based_on"):
- filters["based_on"] = "Cost Center"
+ if filters.get("based_on") == "Accounting Dimension" and not filters.get("accounting_dimension"):
+ frappe.throw(_("Select Accounting Dimension."))
based_on = filters.based_on.replace(" ", "_").lower()
validate_filters(filters)
@@ -37,6 +37,8 @@ def get_accounts_data(based_on, company):
)
elif based_on == "project":
return frappe.get_all("Project", fields=["name"], filters={"company": company}, order_by="name")
+ elif based_on == "accounting_dimension":
+ return frappe.get_all("Accounting Dimension", fields=["name"], order_by="name")
else:
filters = {}
doctype = frappe.unscrub(based_on)
@@ -60,7 +62,9 @@ def get_data(accounts, filters, based_on):
filters.get("company"),
filters.get("from_date"),
filters.get("to_date"),
- based_on,
+ based_on
+ if based_on != "accounting_dimension"
+ else filters.accounting_dimension.replace(" ", "_").lower(),
gl_entries_by_account,
ignore_closing_entries=not flt(filters.get("with_period_closing_entry")),
)
From 21c993a7b3129696ac4efa3d2dd2ac3f4d3a5ec2 Mon Sep 17 00:00:00 2001
From: Gursheen Anand
Date: Wed, 12 Jul 2023 20:32:08 +0530
Subject: [PATCH 063/107] fix: clear accounting dimension value when based on
field changes
---
.../profitability_analysis/profitability_analysis.js | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
index 4412212d2e..b45fe6fe5d 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
@@ -18,7 +18,15 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"fieldtype": "Select",
"options": ["Cost Center", "Project", "Accounting Dimension"],
"default": "Cost Center",
- "reqd": 1
+ "reqd": 1,
+ "on_change": function(query_report){
+ let based_on = query_report.get_values().based_on;
+ if(based_on!='Accounting Dimension'){
+ frappe.query_report.set_filter_value({
+ accounting_dimension: ''
+ });
+ }
+ }
},
{
"fieldname": "accounting_dimension",
From 924cdef6d9631e2d84a775b94e211c71d7e5b57a Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 14 Jul 2023 18:53:02 +0530
Subject: [PATCH 064/107] ci: add eslint and update linting confs
---
.eslintrc | 65 +++++--------------
.github/workflows/linters.yml | 9 +--
.pre-commit-config.yaml | 18 ++++-
.../report/account_balance/account_balance.js | 2 +-
.../billed_items_to_be_received.js | 4 +-
.../consolidated_financial_statement.js | 2 +-
.../customer_ledger_summary.js | 2 +-
.../deferred_revenue_and_expense.js | 2 +-
.../dimension_wise_accounts_balance_report.js | 2 +-
.../gross_and_net_profit_report.js | 2 +-
.../inactive_sales_items.js | 2 +-
.../report/payment_ledger/payment_ledger.js | 2 +-
.../report/pos_register/pos_register.js | 2 +-
.../report/share_balance/share_balance.js | 2 +-
.../report/share_ledger/share_ledger.js | 2 +-
.../supplier_ledger_summary.js | 2 +-
.../tds_computation_summary.js | 2 +-
.../tds_payable_monthly.js | 2 +-
.../voucher_wise_balance.js | 2 +-
.../fixed_asset_register.js | 2 +-
.../procurement_tracker.js | 2 +-
.../purchase_analytics/purchase_analytics.js | 9 +--
.../purchase_order_analysis.js | 2 +-
.../requested_items_to_order_and_receive.js | 2 +-
.../subcontract_order_summary.js | 2 +-
.../subcontracted_item_to_be_received.js | 2 +-
...tracted_raw_materials_to_be_transferred.js | 2 +-
.../first_response_time_for_opportunity.js | 2 +-
.../lead_conversion_time.js | 2 +-
.../crm/report/lead_details/lead_details.js | 2 +-
.../lost_opportunity/lost_opportunity.js | 2 +-
.../opportunity_summary_by_sales_stage.js | 2 +-
.../sales_pipeline_analytics.js | 2 +-
.../doctype/workstation/_test_workstation.js | 2 +-
.../doctype/workstation/workstation_list.js | 2 +-
.../report/bom_explorer/bom_explorer.js | 2 +-
.../bom_operations_time.js | 2 +-
.../bom_stock_calculated.js | 2 +-
.../bom_variance_report.js | 2 +-
.../cost_of_poor_quality_report.js | 2 +-
.../downtime_analysis/downtime_analysis.js | 2 +-
.../exponential_smoothing_forecasting.js | 2 +-
.../job_card_summary/job_card_summary.js | 2 +-
.../process_loss_report.js | 2 +-
.../production_analytics.js | 2 +-
.../production_plan_summary.js | 2 +-
.../production_planning_report.js | 2 +-
.../quality_inspection_summary.js | 2 +-
.../work_order_consumed_materials.js | 2 +-
.../work_order_stock_report.js | 2 +-
.../work_order_summary/work_order_summary.js | 2 +-
.../delayed_tasks_summary.js | 2 +-
.../employee_billing_summary.js | 2 +-
.../project_billing_summary.js | 2 +-
.../report/project_summary/project_summary.js | 2 +-
erpnext/public/js/controllers/buying.js | 2 +-
.../electronic_invoice_register.js | 2 +-
.../report/uae_vat_201/uae_vat_201.js | 2 +-
.../vat_audit_report/vat_audit_report.js | 2 +-
.../address_and_contacts.js | 2 +-
.../customer_wise_item_price.js | 2 +-
.../item_wise_sales_history.js | 2 +-
.../payment_terms_status_for_sales_order.js | 6 +-
.../pending_so_items_for_purchase_request.js | 2 +-
.../report/sales_analytics/sales_analytics.js | 2 +-
.../sales_order_analysis.js | 2 +-
.../sales_partner_commission_summary.js | 2 +-
...ner_target_variance_based_on_item_group.js | 2 +-
.../sales_partner_transaction_summary.js | 2 +-
.../sales_person_commission_summary.js | 2 +-
...son_target_variance_based_on_item_group.js | 2 +-
...ory_target_variance_based_on_item_group.js | 2 +-
.../territory_wise_sales.js | 2 +-
.../cogs_by_item_group/cogs_by_item_group.js | 2 +-
.../delayed_item_report.js | 2 +-
.../delayed_order_report.js | 2 +-
...eue_vs_qty_after_transaction_comparison.js | 2 +-
...incorrect_balance_qty_after_transaction.js | 2 +-
.../incorrect_serial_no_valuation.js | 2 +-
.../incorrect_stock_value_report.js | 2 +-
.../item_price_stock/item_price_stock.js | 2 +-
.../item_shortage_report.js | 2 +-
.../item_variant_details.js | 2 +-
.../serial_no_ledger/serial_no_ledger.js | 2 +-
.../report/stock_analytics/stock_analytics.js | 8 +--
.../stock_and_account_value_comparison.js | 2 +-
.../stock_ledger_invariant_check.js | 2 +-
.../stock_qty_vs_serial_no_count.js | 2 +-
.../total_stock_summary.js | 2 +-
...rehouse_wise_item_balance_age_and_value.js | 2 +-
.../warehouse_wise_stock_balance.js | 2 +-
.../first_response_time_for_issues.js | 2 +-
.../report/issue_analytics/issue_analytics.js | 8 +--
.../report/issue_summary/issue_summary.js | 2 +-
.../support_hour_distribution.js | 2 +-
.../youtube_interactions.js | 2 +-
96 files changed, 145 insertions(+), 158 deletions(-)
diff --git a/.eslintrc b/.eslintrc
index 12fefa0968..f3d4fd5091 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -2,65 +2,32 @@
"env": {
"browser": true,
"node": true,
- "es6": true
+ "es2022": true
},
"parserOptions": {
- "ecmaVersion": 11,
"sourceType": "module"
},
"extends": "eslint:recommended",
"rules": {
- "indent": [
- "error",
- "tab",
- { "SwitchCase": 1 }
- ],
- "brace-style": [
- "error",
- "1tbs"
- ],
- "space-unary-ops": [
- "error",
- { "words": true }
- ],
- "linebreak-style": [
- "error",
- "unix"
- ],
- "quotes": [
- "off"
- ],
- "semi": [
- "warn",
- "always"
- ],
- "camelcase": [
- "off"
- ],
- "no-unused-vars": [
- "warn"
- ],
- "no-redeclare": [
- "warn"
- ],
- "no-console": [
- "warn"
- ],
- "no-extra-boolean-cast": [
- "off"
- ],
- "no-control-regex": [
- "off"
- ],
- "space-before-blocks": "warn",
- "keyword-spacing": "warn",
- "comma-spacing": "warn",
- "key-spacing": "warn"
+ "indent": "off",
+ "brace-style": "off",
+ "no-mixed-spaces-and-tabs": "off",
+ "no-useless-escape": "off",
+ "space-unary-ops": ["error", { "words": true }],
+ "linebreak-style": "off",
+ "quotes": ["off"],
+ "semi": "off",
+ "camelcase": "off",
+ "no-unused-vars": "off",
+ "no-console": ["warn"],
+ "no-extra-boolean-cast": ["off"],
+ "no-control-regex": ["off"]
},
"root": true,
"globals": {
"frappe": true,
"Vue": true,
+ "SetVueGlobals": true,
"erpnext": true,
"hub": true,
"$": true,
@@ -97,8 +64,10 @@
"is_null": true,
"in_list": true,
"has_common": true,
+ "posthog": true,
"has_words": true,
"validate_email": true,
+ "open_web_template_values_editor": true,
"get_number_format": true,
"format_number": true,
"format_currency": true,
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml
index af6d8f26a7..94b76b12ce 100644
--- a/.github/workflows/linters.yml
+++ b/.github/workflows/linters.yml
@@ -9,21 +9,22 @@ jobs:
name: linters
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python 3.10
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: '3.10'
+ cache: pip
- name: Install and Run Pre-commit
- uses: pre-commit/action@v2.0.3
+ uses: pre-commit/action@v3.0.0
- name: Download Semgrep rules
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
- name: Download semgrep
- run: pip install semgrep==0.97.0
+ run: pip install semgrep
- name: Run Semgrep rules
run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d70977c07e..93d07485e6 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -16,8 +16,24 @@ repos:
- id: check-merge-conflict
- id: check-ast
+ - repo: https://github.com/pre-commit/mirrors-eslint
+ rev: v8.44.0
+ hooks:
+ - id: eslint
+ types_or: [javascript]
+ args: ['--quiet']
+ # Ignore any files that might contain jinja / bundles
+ exclude: |
+ (?x)^(
+ erpnext/public/dist/.*|
+ cypress/.*|
+ .*node_modules.*|
+ .*boilerplate.*|
+ erpnext/public/js/controllers/.*
+ )$
+
- repo: https://github.com/PyCQA/flake8
- rev: 5.0.4
+ rev: 6.0.0
hooks:
- id: flake8
additional_dependencies: [
diff --git a/erpnext/accounts/report/account_balance/account_balance.js b/erpnext/accounts/report/account_balance/account_balance.js
index bb66951cdc..5681be9211 100644
--- a/erpnext/accounts/report/account_balance/account_balance.js
+++ b/erpnext/accounts/report/account_balance/account_balance.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Account Balance"] = {
"filters": [
diff --git a/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.js b/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.js
index e1fccb6e72..7617ed1e22 100644
--- a/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.js
+++ b/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports['Billed Items To Be Received'] = {
'filters': [
@@ -17,7 +17,7 @@ frappe.query_reports['Billed Items To Be Received'] = {
'fieldname': 'posting_date',
'fieldtype': 'Date',
'reqd': 1,
- 'default': get_today()
+ 'default': frappe.datetime.get_today()
},
{
'label': __('Purchase Invoice'),
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
index dd965a9813..c6600b9aa7 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Consolidated Financial Statement"] = {
diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js
index a123631663..74d52de2d2 100644
--- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js
+++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Customer Ledger Summary"] = {
"filters": [
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js
index 0056b9e8f5..eb2df6284b 100644
--- a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
function get_filters() {
let filters = [
diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js
index ea05a35b25..bd4b274f4d 100644
--- a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js
+++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Dimension-wise Accounts Balance Report"] = {
diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js
index 92cf36ebc5..f6b0b8c3f7 100644
--- a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js
+++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Gross and Net Profit Report"] = {
"filters": [
diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js
index 7908c07a0a..bd9b54398b 100644
--- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js
+++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Inactive Sales Items"] = {
"filters": [
diff --git a/erpnext/accounts/report/payment_ledger/payment_ledger.js b/erpnext/accounts/report/payment_ledger/payment_ledger.js
index a5a4108f1d..65380ccdda 100644
--- a/erpnext/accounts/report/payment_ledger/payment_ledger.js
+++ b/erpnext/accounts/report/payment_ledger/payment_ledger.js
@@ -1,6 +1,6 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
function get_filters() {
let filters = [
diff --git a/erpnext/accounts/report/pos_register/pos_register.js b/erpnext/accounts/report/pos_register/pos_register.js
index b8d48d92de..6e5491a0f8 100644
--- a/erpnext/accounts/report/pos_register/pos_register.js
+++ b/erpnext/accounts/report/pos_register/pos_register.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["POS Register"] = {
"filters": [
diff --git a/erpnext/accounts/report/share_balance/share_balance.js b/erpnext/accounts/report/share_balance/share_balance.js
index 6db5bdd299..ac64a0bfb9 100644
--- a/erpnext/accounts/report/share_balance/share_balance.js
+++ b/erpnext/accounts/report/share_balance/share_balance.js
@@ -1,7 +1,7 @@
// -*- coding: utf-8 -*-
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Share Balance"] = {
"filters": [
diff --git a/erpnext/accounts/report/share_ledger/share_ledger.js b/erpnext/accounts/report/share_ledger/share_ledger.js
index 6d1c44a6d0..4f2d2cc78f 100644
--- a/erpnext/accounts/report/share_ledger/share_ledger.js
+++ b/erpnext/accounts/report/share_ledger/share_ledger.js
@@ -1,7 +1,7 @@
// -*- coding: utf-8 -*-
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Share Ledger"] = {
"filters": [
diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
index 5dc4c3d1c1..8e3c8ac630 100644
--- a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
+++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Supplier Ledger Summary"] = {
"filters": [
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.js b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.js
index d3d45b353a..d3348460a8 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.js
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["TDS Computation Summary"] = {
"filters": [
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
index ff2aa30601..202fd1d15a 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["TDS Payable Monthly"] = {
"filters": [
diff --git a/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.js b/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.js
index 0c148f85fb..f7ab029f19 100644
--- a/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.js
+++ b/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.js
@@ -1,6 +1,6 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Voucher-wise Balance"] = {
"filters": [
diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js
index b788a32d6a..2752e09909 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Fixed Asset Register"] = {
"filters": [
diff --git a/erpnext/buying/report/procurement_tracker/procurement_tracker.js b/erpnext/buying/report/procurement_tracker/procurement_tracker.js
index 283d56c946..416655d6bc 100644
--- a/erpnext/buying/report/procurement_tracker/procurement_tracker.js
+++ b/erpnext/buying/report/procurement_tracker/procurement_tracker.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Procurement Tracker"] = {
"filters": [
diff --git a/erpnext/buying/report/purchase_analytics/purchase_analytics.js b/erpnext/buying/report/purchase_analytics/purchase_analytics.js
index a884f06d2c..a0faa6869a 100644
--- a/erpnext/buying/report/purchase_analytics/purchase_analytics.js
+++ b/erpnext/buying/report/purchase_analytics/purchase_analytics.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Purchase Analytics"] = {
"filters": [
@@ -81,8 +81,9 @@ frappe.query_reports["Purchase Analytics"] = {
const tree_type = frappe.query_report.filters[0].value;
if (data_doctype != tree_type) return;
- row_name = data[2].content;
- length = data.length;
+ let row_name = data[2].content;
+ let length = data.length;
+ let row_values = '';
if (tree_type == "Supplier") {
row_values = data
@@ -104,7 +105,7 @@ frappe.query_reports["Purchase Analytics"] = {
});
}
- entry = {
+ let entry = {
name: row_name,
values: row_values,
};
diff --git a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js
index 721e54e46f..91506c0ab3 100644
--- a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js
+++ b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Purchase Order Analysis"] = {
"filters": [
diff --git a/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js
index d727584d0a..cb05109d5b 100644
--- a/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js
+++ b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Requested Items to Order and Receive"] = {
"filters": [
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
index 075671f4ec..800b8ab7db 100644
--- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Subcontract Order Summary"] = {
"filters": [
diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.js b/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.js
index 9db769d59b..35be2a9cf8 100644
--- a/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.js
+++ b/erpnext/buying/report/subcontracted_item_to_be_received/subcontracted_item_to_be_received.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Subcontracted Item To Be Received"] = {
"filters": [
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.js b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.js
index 7e5338f353..33b26dcb5f 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.js
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Subcontracted Raw Materials To Be Transferred"] = {
"filters": [
diff --git a/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.js b/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.js
index fe5707af29..4bf82479a1 100644
--- a/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.js
+++ b/erpnext/crm/report/first_response_time_for_opportunity/first_response_time_for_opportunity.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["First Response Time for Opportunity"] = {
"filters": [
diff --git a/erpnext/crm/report/lead_conversion_time/lead_conversion_time.js b/erpnext/crm/report/lead_conversion_time/lead_conversion_time.js
index eeb8984513..d7ff9ad538 100644
--- a/erpnext/crm/report/lead_conversion_time/lead_conversion_time.js
+++ b/erpnext/crm/report/lead_conversion_time/lead_conversion_time.js
@@ -1,6 +1,6 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Lead Conversion Time"] = {
"filters": [
diff --git a/erpnext/crm/report/lead_details/lead_details.js b/erpnext/crm/report/lead_details/lead_details.js
index 2f6d24224f..66611f6c6c 100644
--- a/erpnext/crm/report/lead_details/lead_details.js
+++ b/erpnext/crm/report/lead_details/lead_details.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Lead Details"] = {
"filters": [
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.js b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
index 927c54df07..8d5923950a 100644
--- a/erpnext/crm/report/lost_opportunity/lost_opportunity.js
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Lost Opportunity"] = {
"filters": [
diff --git a/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js b/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
index 7cd1710a7f..0aa21436bc 100644
--- a/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
+++ b/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Opportunity Summary by Sales Stage"] = {
"filters": [
diff --git a/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.js b/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.js
index 1426f4b6fd..3111121522 100644
--- a/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.js
+++ b/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Pipeline Analytics"] = {
"filters": [
diff --git a/erpnext/manufacturing/doctype/workstation/_test_workstation.js b/erpnext/manufacturing/doctype/workstation/_test_workstation.js
index 0f09bd1c61..f2dced81e2 100644
--- a/erpnext/manufacturing/doctype/workstation/_test_workstation.js
+++ b/erpnext/manufacturing/doctype/workstation/_test_workstation.js
@@ -1,4 +1,4 @@
-/* eslint-disable */
+
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
diff --git a/erpnext/manufacturing/doctype/workstation/workstation_list.js b/erpnext/manufacturing/doctype/workstation/workstation_list.js
index 6a89d21e1e..61f2062ec0 100644
--- a/erpnext/manufacturing/doctype/workstation/workstation_list.js
+++ b/erpnext/manufacturing/doctype/workstation/workstation_list.js
@@ -1,4 +1,4 @@
-/* eslint-disable */
+
frappe.listview_settings['Workstation'] = {
// add_fields: ["status"],
// filters:[["status","=", "Open"]]
diff --git a/erpnext/manufacturing/report/bom_explorer/bom_explorer.js b/erpnext/manufacturing/report/bom_explorer/bom_explorer.js
index b94d3f3770..50191bf8ab 100644
--- a/erpnext/manufacturing/report/bom_explorer/bom_explorer.js
+++ b/erpnext/manufacturing/report/bom_explorer/bom_explorer.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["BOM Explorer"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
index 0eb22a22f7..34edb9d538 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["BOM Operations Time"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.js b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.js
index a0fd91e866..8e66f704c8 100644
--- a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.js
+++ b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Epoch Consulting and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["BOM Stock Calculated"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.js b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.js
index c6ecaef2fa..db6f4d7688 100644
--- a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.js
+++ b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["BOM Variance Report"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js
index 72eed5e0d7..d0249ba84b 100644
--- a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js
+++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Cost of Poor Quality Report"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
index f6486743aa..0589260958 100644
--- a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
+++ b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Downtime Analysis"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.js b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.js
index a3f0d00877..3795bd3df8 100644
--- a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.js
+++ b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Exponential Smoothing Forecasting"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/job_card_summary/job_card_summary.js b/erpnext/manufacturing/report/job_card_summary/job_card_summary.js
index 782ce8110a..aa4251cd50 100644
--- a/erpnext/manufacturing/report/job_card_summary/job_card_summary.js
+++ b/erpnext/manufacturing/report/job_card_summary/job_card_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Job Card Summary"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/process_loss_report/process_loss_report.js b/erpnext/manufacturing/report/process_loss_report/process_loss_report.js
index b0c2b94a25..c08413dc4a 100644
--- a/erpnext/manufacturing/report/process_loss_report/process_loss_report.js
+++ b/erpnext/manufacturing/report/process_loss_report/process_loss_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Process Loss Report"] = {
filters: [
diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.js b/erpnext/manufacturing/report/production_analytics/production_analytics.js
index 99f9b1260a..72f06edf85 100644
--- a/erpnext/manufacturing/report/production_analytics/production_analytics.js
+++ b/erpnext/manufacturing/report/production_analytics/production_analytics.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Production Analytics"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.js b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.js
index 59396fef16..521543ab1b 100644
--- a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.js
+++ b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Production Plan Summary"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.js b/erpnext/manufacturing/report/production_planning_report/production_planning_report.js
index 675b8a1100..422583274b 100644
--- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.js
+++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Production Planning Report"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.js b/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.js
index d4587aa661..905d185076 100644
--- a/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.js
+++ b/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Quality Inspection Summary"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js
index 2fb4ec6791..70d7f92da0 100644
--- a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js
+++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Work Order Consumed Materials"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js
index dbb7c23410..cf651cb394 100644
--- a/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js
+++ b/erpnext/manufacturing/report/work_order_stock_report/work_order_stock_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Work Order Stock Report"] = {
"filters": [
diff --git a/erpnext/manufacturing/report/work_order_summary/work_order_summary.js b/erpnext/manufacturing/report/work_order_summary/work_order_summary.js
index 67bd24dd80..d0242f4d3b 100644
--- a/erpnext/manufacturing/report/work_order_summary/work_order_summary.js
+++ b/erpnext/manufacturing/report/work_order_summary/work_order_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Work Order Summary"] = {
"filters": [
diff --git a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js
index 5aa44c0a8c..fa70b9394a 100644
--- a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js
+++ b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Delayed Tasks Summary"] = {
"filters": [
diff --git a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js
index 13f49ed6be..8566b1fc78 100644
--- a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js
+++ b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Employee Billing Summary"] = {
"filters": [
diff --git a/erpnext/projects/report/project_billing_summary/project_billing_summary.js b/erpnext/projects/report/project_billing_summary/project_billing_summary.js
index caac1d86b4..0242036dc7 100644
--- a/erpnext/projects/report/project_billing_summary/project_billing_summary.js
+++ b/erpnext/projects/report/project_billing_summary/project_billing_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Project Billing Summary"] = {
"filters": [
diff --git a/erpnext/projects/report/project_summary/project_summary.js b/erpnext/projects/report/project_summary/project_summary.js
index 414b7b206a..21dbfda73f 100644
--- a/erpnext/projects/report/project_summary/project_summary.js
+++ b/erpnext/projects/report/project_summary/project_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Project Summary"] = {
"filters": [
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index c001b4eb56..75d9891b81 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -34,7 +34,7 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
this.frm.set_value("disable_rounded_total", disable);
}
- /* eslint-disable */
+
// no idea where me is coming from
if(this.frm.get_field('shipping_address')) {
this.frm.set_query("shipping_address", function() {
diff --git a/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.js b/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.js
index d7e3ac9a5d..4fc1be1ff5 100644
--- a/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.js
+++ b/erpnext/regional/report/electronic_invoice_register/electronic_invoice_register.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Electronic Invoice Register"] = {
"filters": [
diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.js b/erpnext/regional/report/uae_vat_201/uae_vat_201.js
index 5957424770..eaefc0420a 100644
--- a/erpnext/regional/report/uae_vat_201/uae_vat_201.js
+++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["UAE VAT 201"] = {
"filters": [
diff --git a/erpnext/regional/report/vat_audit_report/vat_audit_report.js b/erpnext/regional/report/vat_audit_report/vat_audit_report.js
index 39ef9b563a..41318f3160 100644
--- a/erpnext/regional/report/vat_audit_report/vat_audit_report.js
+++ b/erpnext/regional/report/vat_audit_report/vat_audit_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["VAT Audit Report"] = {
"filters": [
diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.js b/erpnext/selling/report/address_and_contacts/address_and_contacts.js
index ef87586f66..c16d9752f5 100644
--- a/erpnext/selling/report/address_and_contacts/address_and_contacts.js
+++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Address And Contacts"] = {
"filters": [
diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js
index d333c8be65..2aac3436c0 100644
--- a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js
+++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Customer-wise Item Price"] = {
"filters": [
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
index 073be78979..f63d02ec84 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
@@ -1,6 +1,6 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Item-wise Sales History"] = {
"filters": [
diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js
index 990d736baa..0203a054f9 100644
--- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js
+++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.js
@@ -1,6 +1,6 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
function get_filters() {
let filters = [
@@ -116,7 +116,7 @@ frappe.query_reports["Payment Terms Status for Sales Order"] = {
"filters": get_filters(),
"formatter": function(value, row, column, data, default_formatter){
if(column.fieldname == 'invoices' && value) {
- invoices = value.split(',');
+ let invoices = value.split(',');
const invoice_formatter = (prev_value, curr_value) => {
if(prev_value != "") {
return prev_value + ", " + default_formatter(curr_value, row, column, data);
@@ -128,7 +128,7 @@ frappe.query_reports["Payment Terms Status for Sales Order"] = {
return invoices.reduce(invoice_formatter, "")
}
else if (column.fieldname == 'paid_amount' && value){
- formatted_value = default_formatter(value, row, column, data);
+ let formatted_value = default_formatter(value, row, column, data);
if(value > 0) {
formatted_value = "" + formatted_value + ""
}
diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.js b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.js
index 37634efb6c..204205949e 100644
--- a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.js
+++ b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Pending SO Items For Purchase Request"] = {
}
diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.js b/erpnext/selling/report/sales_analytics/sales_analytics.js
index 87dd02f991..ace16f4f41 100644
--- a/erpnext/selling/report/sales_analytics/sales_analytics.js
+++ b/erpnext/selling/report/sales_analytics/sales_analytics.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Analytics"] = {
"filters": [
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
index f3f931edfd..ac3d3dbf71 100644
--- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Order Analysis"] = {
"filters": [
diff --git a/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js b/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js
index 63d930c145..f08780ae72 100644
--- a/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js
+++ b/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Partner Commission Summary"] = {
"filters": [
diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js
index adae47b87d..83934fb359 100644
--- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js
+++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Partner Target Variance based on Item Group"] = {
"filters": [
diff --git a/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js
index e404233953..e443ab39f6 100644
--- a/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js
+++ b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Partner Transaction Summary"] = {
"filters": [
diff --git a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js
index ba6ee784b9..306ef6fffd 100644
--- a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js
+++ b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Person Commission Summary"] = {
"filters": [
diff --git a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js
index 2b8443627d..9414ad6a8f 100644
--- a/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js
+++ b/erpnext/selling/report/sales_person_target_variance_based_on_item_group/sales_person_target_variance_based_on_item_group.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Sales Person Target Variance Based On Item Group"] = {
"filters": [
diff --git a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js
index 9f3d255e66..12bb49fd18 100644
--- a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js
+++ b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Territory Target Variance Based On Item Group"] = {
"filters": [
diff --git a/erpnext/selling/report/territory_wise_sales/territory_wise_sales.js b/erpnext/selling/report/territory_wise_sales/territory_wise_sales.js
index bef800f104..c755a75d82 100644
--- a/erpnext/selling/report/territory_wise_sales/territory_wise_sales.js
+++ b/erpnext/selling/report/territory_wise_sales/territory_wise_sales.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Territory-wise Sales"] = {
diff --git a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.js b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.js
index d7c50a6697..a032285124 100644
--- a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.js
+++ b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["COGS By Item Group"] = {
diff --git a/erpnext/stock/report/delayed_item_report/delayed_item_report.js b/erpnext/stock/report/delayed_item_report/delayed_item_report.js
index 40e6abefeb..cf6e12ff47 100644
--- a/erpnext/stock/report/delayed_item_report/delayed_item_report.js
+++ b/erpnext/stock/report/delayed_item_report/delayed_item_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Delayed Item Report"] = {
"filters": [
diff --git a/erpnext/stock/report/delayed_order_report/delayed_order_report.js b/erpnext/stock/report/delayed_order_report/delayed_order_report.js
index aab0f3d0d1..cf489c932e 100644
--- a/erpnext/stock/report/delayed_order_report/delayed_order_report.js
+++ b/erpnext/stock/report/delayed_order_report/delayed_order_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Delayed Order Report"] = {
"filters": [
diff --git a/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.js b/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.js
index 0b8f49653d..bc86979132 100644
--- a/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.js
+++ b/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.js
@@ -1,6 +1,6 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
const DIFFERNCE_FIELD_NAMES = [
"fifo_qty_diff",
diff --git a/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.js b/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.js
index bf11277d9c..0f9120ba2f 100644
--- a/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.js
+++ b/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Incorrect Balance Qty After Transaction"] = {
"filters": [
diff --git a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.js b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.js
index c62d48081c..6325cc85c4 100644
--- a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.js
+++ b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Incorrect Serial No Valuation"] = {
"filters": [
diff --git a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.js b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.js
index ff424807e3..174d03317d 100644
--- a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.js
+++ b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Incorrect Stock Value Report"] = {
"filters": [
diff --git a/erpnext/stock/report/item_price_stock/item_price_stock.js b/erpnext/stock/report/item_price_stock/item_price_stock.js
index 7af1dab6a0..c4684daa9f 100644
--- a/erpnext/stock/report/item_price_stock/item_price_stock.js
+++ b/erpnext/stock/report/item_price_stock/item_price_stock.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Item Price Stock"] = {
"filters": [
diff --git a/erpnext/stock/report/item_shortage_report/item_shortage_report.js b/erpnext/stock/report/item_shortage_report/item_shortage_report.js
index ca42a331e9..5642038f3f 100644
--- a/erpnext/stock/report/item_shortage_report/item_shortage_report.js
+++ b/erpnext/stock/report/item_shortage_report/item_shortage_report.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Item Shortage Report"] = {
"filters": [
diff --git a/erpnext/stock/report/item_variant_details/item_variant_details.js b/erpnext/stock/report/item_variant_details/item_variant_details.js
index 78eab4050c..b9022948f4 100644
--- a/erpnext/stock/report/item_variant_details/item_variant_details.js
+++ b/erpnext/stock/report/item_variant_details/item_variant_details.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Item Variant Details"] = {
"filters": [
diff --git a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.js b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.js
index 976e5156ad..fe977c6d5c 100644
--- a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.js
+++ b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Serial No Ledger"] = {
"filters": [
diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.js b/erpnext/stock/report/stock_analytics/stock_analytics.js
index 78afe6d264..ea7bf5688e 100644
--- a/erpnext/stock/report/stock_analytics/stock_analytics.js
+++ b/erpnext/stock/report/stock_analytics/stock_analytics.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Stock Analytics"] = {
"filters": [
@@ -93,11 +93,11 @@ frappe.query_reports["Stock Analytics"] = {
checkboxColumn: true,
events: {
onCheckRow: function(data) {
- row_name = data[2].content;
- row_values = data.slice(7).map(function (column) {
+ let row_name = data[2].content;
+ let row_values = data.slice(7).map(function (column) {
return column.content;
})
- entry = {
+ let entry = {
'name':row_name,
'values':row_values
}
diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js
index 254f5273be..ffef11a20e 100644
--- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js
+++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Stock and Account Value Comparison"] = {
"filters": [
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
index 31f389f236..3447e0a6fa 100644
--- a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
const DIFFERNCE_FIELD_NAMES = [
"difference_in_qty",
diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js
index 2a0fd4025c..7a48798495 100644
--- a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js
+++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Stock Qty vs Serial No Count"] = {
"filters": [
diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.js b/erpnext/stock/report/total_stock_summary/total_stock_summary.js
index 88054aaea7..3d247f6740 100644
--- a/erpnext/stock/report/total_stock_summary/total_stock_summary.js
+++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Total Stock Summary"] = {
"filters": [
diff --git a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.js b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.js
index 39cfd7274f..8d6b283a15 100644
--- a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.js
+++ b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Warehouse wise Item Balance Age and Value"] = {
"filters": [
diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
index 752e464e27..4a77052a90 100644
--- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
+++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js
@@ -1,6 +1,6 @@
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Warehouse Wise Stock Balance"] = {
"filters": [
diff --git a/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.js b/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.js
index 18691fe264..a133770f6d 100644
--- a/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.js
+++ b/erpnext/support/report/first_response_time_for_issues/first_response_time_for_issues.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["First Response Time for Issues"] = {
"filters": [
diff --git a/erpnext/support/report/issue_analytics/issue_analytics.js b/erpnext/support/report/issue_analytics/issue_analytics.js
index 746eee025a..be45b9b44a 100644
--- a/erpnext/support/report/issue_analytics/issue_analytics.js
+++ b/erpnext/support/report/issue_analytics/issue_analytics.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Issue Analytics"] = {
"filters": [
@@ -93,11 +93,11 @@ frappe.query_reports["Issue Analytics"] = {
events: {
onCheckRow: function(data) {
if (data && data.length) {
- row_name = data[2].content;
- row_values = data.slice(3).map(function(column) {
+ let row_name = data[2].content;
+ let row_values = data.slice(3).map(function(column) {
return column.content;
})
- entry = {
+ let entry = {
'name': row_name,
'values': row_values
}
diff --git a/erpnext/support/report/issue_summary/issue_summary.js b/erpnext/support/report/issue_summary/issue_summary.js
index a5122d03ad..aee6f53f17 100644
--- a/erpnext/support/report/issue_summary/issue_summary.js
+++ b/erpnext/support/report/issue_summary/issue_summary.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Issue Summary"] = {
"filters": [
diff --git a/erpnext/support/report/support_hour_distribution/support_hour_distribution.js b/erpnext/support/report/support_hour_distribution/support_hour_distribution.js
index ae30b6a550..82ccc73bf9 100644
--- a/erpnext/support/report/support_hour_distribution/support_hour_distribution.js
+++ b/erpnext/support/report/support_hour_distribution/support_hour_distribution.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["Support Hour Distribution"] = {
"filters": [
diff --git a/erpnext/utilities/report/youtube_interactions/youtube_interactions.js b/erpnext/utilities/report/youtube_interactions/youtube_interactions.js
index 6e3e4e6980..adf2cf62f7 100644
--- a/erpnext/utilities/report/youtube_interactions/youtube_interactions.js
+++ b/erpnext/utilities/report/youtube_interactions/youtube_interactions.js
@@ -1,6 +1,6 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* eslint-disable */
+
frappe.query_reports["YouTube Interactions"] = {
"filters": [
From 3fa2a8c2d8f4e8e25727b64fe85b65a8724907fa Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sat, 15 Jul 2023 18:03:16 +0530
Subject: [PATCH 065/107] chore: fix linting issues
---
.../doctype/journal_entry/journal_entry.js | 8 +-
.../doctype/payment_order/payment_order.js | 2 +-
.../sales_payment_summary.js | 1 -
erpnext/assets/doctype/asset/asset.js | 2 +-
.../supplier_scorecard_period.js | 3 -
.../supplier_scorecard_standing.js | 1 -
.../supplier_scorecard_variable.js | 2 -
erpnext/crm/doctype/lead/lead.js | 5 +-
.../doctype/work_order/work_order.js | 9 +-
erpnext/public/js/agriculture/ternary_plot.js | 232 ------------------
erpnext/public/js/stock_analytics.js | 9 +-
erpnext/public/js/stock_grid_report.js | 21 +-
.../page/point_of_sale/pos_item_cart.js | 2 +-
erpnext/stock/doctype/batch/batch_list.js | 2 +-
.../doctype/delivery_trip/delivery_trip.js | 2 +-
.../stock_reconciliation.js | 4 +-
erpnext/templates/includes/product_list.js | 10 +-
erpnext/templates/pages/projects.js | 2 +-
18 files changed, 42 insertions(+), 275 deletions(-)
delete mode 100644 erpnext/public/js/agriculture/ternary_plot.js
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index a51e38eefe..8d8cbefa71 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -264,11 +264,11 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
}
if(jvd.party_type && jvd.party) {
- var party_field = "";
+ let party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) {
- var party_field = "customer";
+ party_field = "customer";
} else if (jvd.reference_type.indexOf("Purchase")===0) {
- var party_field = "supplier";
+ party_field = "supplier";
}
if (party_field) {
@@ -368,7 +368,7 @@ cur_frm.cscript.update_totals = function(doc) {
td += flt(accounts[i].debit, precision("debit", accounts[i]));
tc += flt(accounts[i].credit, precision("credit", accounts[i]));
}
- var doc = locals[doc.doctype][doc.name];
+ doc = locals[doc.doctype][doc.name];
doc.total_debit = td;
doc.total_credit = tc;
doc.difference = flt((td - tc), precision("difference"));
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js
index 7d85d89c45..6630e7122c 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.js
+++ b/erpnext/accounts/doctype/payment_order/payment_order.js
@@ -124,7 +124,7 @@ frappe.ui.form.on('Payment Order', {
return frappe.call({
method: "erpnext.accounts.doctype.payment_order.payment_order.make_payment_records",
args: {
- "name": me.frm.doc.name,
+ "name": frm.doc.name,
"supplier": args.supplier,
"mode_of_payment": args.mode_of_payment
},
diff --git a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.js b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.js
index 44e20e83c5..92e6f7f514 100644
--- a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.js
+++ b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.js
@@ -29,7 +29,6 @@ frappe.query_reports["Sales Payment Summary"] = {
"label": __("Owner"),
"fieldtype": "Link",
"options": "User",
- "defaults": user
},
{
"fieldname":"is_pos",
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 43920adca3..97a41de526 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -473,7 +473,7 @@ frappe.ui.form.on('Asset', {
}
const item = purchase_doc.items.find(item => item.item_code === frm.doc.item_code);
if (!item) {
- doctype_field = frappe.scrub(doctype)
+ let doctype_field = frappe.scrub(doctype)
frm.set_value(doctype_field, '');
frappe.msgprint({
title: __('Invalid {0}', [__(doctype)]),
diff --git a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.js b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.js
index a4cdeb3195..62079cc3e0 100644
--- a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.js
+++ b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.js
@@ -1,9 +1,6 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* global frappe */
-
-
frappe.ui.form.on("Supplier Scorecard Period", {
onload: function(frm) {
let criteria_grid = frm.get_field("criteria").grid;
diff --git a/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.js b/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.js
index dccfcc34bb..22756e75cf 100644
--- a/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.js
+++ b/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.js
@@ -1,7 +1,6 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* global frappe */
frappe.ui.form.on("Supplier Scorecard Standing", {
refresh: function() {
diff --git a/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.js b/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.js
index 2d74fdd190..b3b4321a88 100644
--- a/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.js
+++ b/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.js
@@ -1,8 +1,6 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-/* global frappe */
-
frappe.ui.form.on("Supplier Scorecard Variable", {
refresh: function() {
diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js
index 9ac54183a2..b1799cee6c 100644
--- a/erpnext/crm/doctype/lead/lead.js
+++ b/erpnext/crm/doctype/lead/lead.js
@@ -54,6 +54,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
}
add_lead_to_prospect () {
+ let me = this;
frappe.prompt([
{
fieldname: 'prospect',
@@ -67,12 +68,12 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
frappe.call({
method: 'erpnext.crm.doctype.lead.lead.add_lead_to_prospect',
args: {
- 'lead': cur_frm.doc.name,
+ 'lead': me.frm.doc.name,
'prospect': data.prospect
},
callback: function(r) {
if (!r.exc) {
- frm.reload_doc();
+ me.frm.reload_doc();
}
},
freeze: true,
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index c1a078d65e..58945bba77 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -624,7 +624,7 @@ erpnext.work_order = {
if ((flt(doc.produced_qty) < flt(doc.material_transferred_for_manufacturing))) {
frm.has_finish_btn = true;
- var finish_btn = frm.add_custom_button(__('Finish'), function() {
+ let finish_btn = frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture');
});
@@ -648,7 +648,7 @@ erpnext.work_order = {
}
} else {
if ((flt(doc.produced_qty) < flt(doc.qty))) {
- var finish_btn = frm.add_custom_button(__('Finish'), function() {
+ let finish_btn = frm.add_custom_button(__('Finish'), function() {
erpnext.work_order.make_se(frm, 'Manufacture');
});
finish_btn.addClass('btn-primary');
@@ -756,13 +756,14 @@ erpnext.work_order = {
},
make_consumption_se: function(frm, backflush_raw_materials_based_on) {
+ let max = 0;
if(!frm.doc.skip_transfer){
- var max = (backflush_raw_materials_based_on === "Material Transferred for Manufacture") ?
+ max = (backflush_raw_materials_based_on === "Material Transferred for Manufacture") ?
flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty) :
flt(frm.doc.qty) - flt(frm.doc.produced_qty);
// flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing);
} else {
- var max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
+ max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
}
frappe.call({
diff --git a/erpnext/public/js/agriculture/ternary_plot.js b/erpnext/public/js/agriculture/ternary_plot.js
deleted file mode 100644
index b06a1fd7c8..0000000000
--- a/erpnext/public/js/agriculture/ternary_plot.js
+++ /dev/null
@@ -1,232 +0,0 @@
-frappe.provide('agriculture');
-
-agriculture.TernaryPlot = class TernaryPlot {
- constructor(opts) {
- Object.assign(this, opts);
-
- frappe.require('assets/frappe/js/lib/snap.svg-min.js', () => {
- this.make_svg();
- this.init_snap();
- this.init_config();
- this.make_plot();
- this.make_plot_marking();
- this.make_legend();
- this.mark_blip();
- });
- }
-
- make_svg() {
- this.$svg = $('