Merge pull request #27279 from deepeshgarg007/gstr_1_cdnr_unregistered_json_develop

feat: CDNR Unreg json generation
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 1570b49..2c96749 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -549,3 +549,11 @@
 	}, target_doc, set_missing_values)
 
 	return doclist
+
+def validate_payment(doc, method=""):
+	if not frappe.db.has_column(doc.reference_doctype, 'status'):
+		return
+
+	status = frappe.db.get_value(doc.reference_doctype, doc.reference_docname, 'status')
+	if status == 'Paid':
+		frappe.throw(_("The Payment Request {0} is already paid, cannot process payment twice").format(doc.reference_docname))
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index babfb0a..5b6e1ee 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -318,6 +318,9 @@
 	},
 	"Company": {
 		"on_trash": "erpnext.regional.india.utils.delete_gst_settings_for_company"
+	},
+	"Integration Request": {
+		"validate": "erpnext.accounts.doctype.payment_request.payment_request.validate_payment"
 	}
 }
 
diff --git a/erpnext/patches/v13_0/add_custom_field_for_south_africa.py b/erpnext/patches/v13_0/add_custom_field_for_south_africa.py
index 93a7de6..96aa547 100644
--- a/erpnext/patches/v13_0/add_custom_field_for_south_africa.py
+++ b/erpnext/patches/v13_0/add_custom_field_for_south_africa.py
@@ -1,8 +1,6 @@
 # Copyright (c) 2020, Frappe and Contributors
 # License: GNU General Public License v3. See license.txt
 
-from __future__ import unicode_literals
-
 import frappe
 
 from erpnext.regional.south_africa.setup import add_permissions, make_custom_fields
@@ -13,5 +11,8 @@
 	if not company:
 		return
 
+	frappe.reload_doc('regional', 'doctype', 'south_africa_vat_settings')
+	frappe.reload_doc('accounts', 'doctype', 'south_africa_vat_account')
+
 	make_custom_fields()
 	add_permissions()
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 531cf65..59fcb98 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -18,9 +18,10 @@
   "close_opportunity_after_days",
   "item_price_settings_section",
   "selling_price_list",
+  "maintain_same_rate_action",
+  "role_to_override_stop_action",
   "column_break_15",
   "maintain_same_sales_rate",
-  "maintain_same_rate_action",
   "editable_price_list_rate",
   "validate_selling_price",
   "editable_bundle_item_rates",
@@ -29,7 +30,6 @@
   "dn_required",
   "sales_update_frequency",
   "column_break_5",
-  "role_to_override_stop_action",
   "allow_multiple_items",
   "allow_against_multiple_purchase_orders",
   "hide_tax_id"
@@ -147,15 +147,14 @@
   {
    "default": "Stop",
    "depends_on": "maintain_same_sales_rate",
-   "description": "Configure the action to stop the transaction or just warn if the same rate is not maintained.",
    "fieldname": "maintain_same_rate_action",
    "fieldtype": "Select",
-   "label": "Action if Same Rate is Not Maintained",
+   "label": "Action if Same Rate is Not Maintained Throughout Sales Cycle",
    "mandatory_depends_on": "maintain_same_sales_rate",
    "options": "Stop\nWarn"
   },
   {
-   "depends_on": "eval: doc.maintain_same_rate_action == 'Stop'",
+   "depends_on": "eval: doc.maintain_same_sales_rate && doc.maintain_same_rate_action == 'Stop'",
    "fieldname": "role_to_override_stop_action",
    "fieldtype": "Link",
    "label": "Role Allowed to Override Stop Action",
@@ -205,7 +204,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-08-24 22:08:34.470897",
+ "modified": "2021-09-01 22:55:33.803624",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling Settings",
@@ -224,4 +223,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/setup/workspace/home/home.json b/erpnext/setup/workspace/home/home.json
index cc9569f..a4e7ad8 100644
--- a/erpnext/setup/workspace/home/home.json
+++ b/erpnext/setup/workspace/home/home.json
@@ -1,7 +1,7 @@
 {
  "category": "",
  "charts": [],
- "content": "[{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
  "creation": "2020-01-23 13:46:38.833076",
  "developer_mode_only": 0,
  "disable_user_customization": 0,
diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py
index 229a7a1..6f0b8a6 100644
--- a/erpnext/support/doctype/issue/test_issue.py
+++ b/erpnext/support/doctype/issue/test_issue.py
@@ -26,58 +26,58 @@
 
 class TestIssue(TestSetUp):
 	def test_response_time_and_resolution_time_based_on_different_sla(self):
-		creation = datetime.datetime(2019, 3, 4, 12, 0)
+		creation = get_datetime("2019-03-04 12:00")
 
 		# make issue with customer specific SLA
 		customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory")
 		issue = make_issue(creation, "_Test Customer", 1)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00"))
 
 		# make issue with customer_group specific SLA
 		customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory")
 		issue = make_issue(creation, "__Test Customer", 2)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00"))
 
 
 		# make issue with territory specific SLA
 		customer = create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory")
 		issue = make_issue(creation, "___Test Customer", 3)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 15, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00"))
 
 		# make issue with default SLA
 		issue = make_issue(creation=creation, index=4)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 16, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 18, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-04 16:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 18:00"))
 
 		# make issue with default SLA before working hours
-		creation = datetime.datetime(2019, 3, 4, 7, 0)
+		creation = get_datetime("2019-03-04 7:00")
 		issue = make_issue(creation=creation, index=5)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 14, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 4, 16, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 16:00"))
 
 		# make issue with default SLA after working hours
-		creation = datetime.datetime(2019, 3, 4, 20, 0)
+		creation = get_datetime("2019-03-04 20:00")
 		issue = make_issue(creation, index=6)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 6, 14, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 6, 16, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-06 14:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-06 16:00"))
 
 		# make issue with default SLA next day
-		creation = datetime.datetime(2019, 3, 4, 14, 0)
+		creation = get_datetime("2019-03-04 14:00")
 		issue = make_issue(creation=creation, index=7)
 
-		self.assertEqual(issue.response_by, datetime.datetime(2019, 3, 4, 18, 0))
-		self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0))
+		self.assertEqual(issue.response_by, get_datetime("2019-03-04 18:00"))
+		self.assertEqual(issue.resolution_by, get_datetime("2019-03-06 12:00"))
 
-		frappe.flags.current_time = datetime.datetime(2019, 3, 4, 15, 0)
+		frappe.flags.current_time = get_datetime("2019-03-04 15:00")
 		issue.reload()
 		issue.status = 'Closed'
 		issue.save()
@@ -85,21 +85,21 @@
 		self.assertEqual(issue.agreement_status, 'Fulfilled')
 
 	def test_issue_metrics(self):
-		creation = datetime.datetime(2020, 3, 4, 4, 0)
+		creation = get_datetime("2020-03-04 4:00")
 
 		issue = make_issue(creation, index=1)
 		create_communication(issue.name, "test@example.com", "Received", creation)
 
-		creation = datetime.datetime(2020, 3, 4, 4, 15)
+		creation = get_datetime("2020-03-04 4:15")
 		create_communication(issue.name, "test@admin.com", "Sent", creation)
 
-		creation = datetime.datetime(2020, 3, 4, 5, 0)
+		creation = get_datetime("2020-03-04 5:00")
 		create_communication(issue.name, "test@example.com", "Received", creation)
 
-		creation = datetime.datetime(2020, 3, 4, 5, 5)
+		creation = get_datetime("2020-03-04 5:05")
 		create_communication(issue.name, "test@admin.com", "Sent", creation)
 
-		frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 5)
+		frappe.flags.current_time = get_datetime("2020-03-04 5:05")
 		issue.reload()
 		issue.status = 'Closed'
 		issue.save()
@@ -109,33 +109,33 @@
 		self.assertEqual(issue.user_resolution_time, 1200)
 
 	def test_hold_time_on_replied(self):
-		creation = datetime.datetime(2020, 3, 4, 4, 0)
+		creation = get_datetime("2020-03-04 4:00")
 
 		issue = make_issue(creation, index=1)
 		create_communication(issue.name, "test@example.com", "Received", creation)
 
-		creation = datetime.datetime(2020, 3, 4, 4, 15)
+		creation = get_datetime("2020-03-04 4:15")
 		create_communication(issue.name, "test@admin.com", "Sent", creation)
 
-		frappe.flags.current_time = datetime.datetime(2020, 3, 4, 4, 15)
+		frappe.flags.current_time = get_datetime("2020-03-04 4:15")
 		issue.reload()
 		issue.status = 'Replied'
 		issue.save()
 
 		self.assertEqual(issue.on_hold_since, frappe.flags.current_time)
 
-		creation = datetime.datetime(2020, 3, 4, 5, 0)
-		frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 0)
+		creation = get_datetime("2020-03-04 5:00")
+		frappe.flags.current_time = get_datetime("2020-03-04 5:00")
 		create_communication(issue.name, "test@example.com", "Received", creation)
 
 		issue.reload()
 		self.assertEqual(flt(issue.total_hold_time, 2), 2700)
-		self.assertEqual(issue.resolution_by, datetime.datetime(2020, 3, 4, 16, 45))
+		self.assertEqual(issue.resolution_by, get_datetime("2020-03-04 16:45"))
 
-		creation = datetime.datetime(2020, 3, 4, 5, 5)
+		creation = get_datetime("2020-03-04 5:05")
 		create_communication(issue.name, "test@admin.com", "Sent", creation)
 
-		frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 5)
+		frappe.flags.current_time = get_datetime("2020-03-04 5:05")
 		issue.reload()
 		issue.status = 'Closed'
 		issue.save()