Merge pull request #31799 from abhinavxd/fix-process-loan-interest-accrual

fix: process loan interest accrual
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
index 4d2dc58..9e06254 100644
--- a/.github/workflows/patch.yml
+++ b/.github/workflows/patch.yml
@@ -11,7 +11,7 @@
   workflow_dispatch:
 
 concurrency:
-  group: patch-develop-${{ github.event.number }}
+  group: patch-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
   cancel-in-progress: true
 
 jobs:
diff --git a/.github/workflows/server-tests-mariadb.yml b/.github/workflows/server-tests-mariadb.yml
index 64134bc..e3b92fd 100644
--- a/.github/workflows/server-tests-mariadb.yml
+++ b/.github/workflows/server-tests-mariadb.yml
@@ -27,7 +27,7 @@
         type: string
 
 concurrency:
-  group: server-mariadb-develop-${{ github.event.number }}
+  group: server-mariadb-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
   cancel-in-progress: true
 
 jobs:
diff --git a/.github/workflows/server-tests-postgres.yml b/.github/workflows/server-tests-postgres.yml
index 651c935..df43801 100644
--- a/.github/workflows/server-tests-postgres.yml
+++ b/.github/workflows/server-tests-postgres.yml
@@ -9,7 +9,7 @@
     types: [opened, labelled, synchronize, reopened]
 
 concurrency:
-  group: server-postgres-develop-${{ github.event.number }}
+  group: server-postgres-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
   cancel-in-progress: true
 
 jobs:
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index ba4cdd6..adcbb83 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -1024,7 +1024,7 @@
 		]
 	});
 
-	dialog.set_primary_action(__("Set"), function() {
+	dialog.set_primary_action(__("Set Loyalty Program"), function() {
 		dialog.hide();
 		return frappe.call({
 			method: "frappe.client.set_value",
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
index 08d2008..db3d5d4 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
@@ -14,9 +14,9 @@
 	filters.naming_series = frappe.db.get_single_value("Buying Settings", "supp_master_name")
 
 	columns = get_columns(filters)
-	tds_docs, tds_accounts, tax_category_map = get_tds_docs(filters)
+	tds_docs, tds_accounts, tax_category_map, journal_entry_party_map = get_tds_docs(filters)
 
-	res = get_result(filters, tds_docs, tds_accounts, tax_category_map)
+	res = get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map)
 	final_result = group_by_supplier_and_category(res)
 
 	return columns, final_result
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index 16e0ac1..f2809a9 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -26,7 +26,6 @@
 	supplier_map = get_supplier_pan_map()
 	tax_rate_map = get_tax_rate_map(filters)
 	gle_map = get_gle_map(tds_docs)
-	print(journal_entry_party_map)
 
 	out = []
 	for name, details in gle_map.items():
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index c0f3745..7ab8f81 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -308,7 +308,8 @@
 
 					rate = flt(outgoing_rate * (d.conversion_factor or 1), d.precision("rate"))
 				else:
-					rate = frappe.db.get_value(ref_doctype, d.get(frappe.scrub(ref_doctype)), "rate")
+					field = "incoming_rate" if self.get("is_internal_supplier") else "rate"
+					rate = frappe.db.get_value(ref_doctype, d.get(frappe.scrub(ref_doctype)), field)
 
 				if self.is_internal_transfer():
 					if rate != d.rate:
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index c946ae4..99c00ad 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -340,8 +340,8 @@
    "fieldname": "no_of_employees",
    "fieldtype": "Select",
    "label": "No of Employees",
-   "options": "1-10\n11-20\n21-30\n31-100\n11-50\n51-200\n201-500\n101-500\n500-1000\n501-1000\n>1000\n1000+"
-  }, 
+   "options": "1-10\n11-50\n51-200\n201-500\n501-1000\n1000+"
+  },
   {
    "fieldname": "column_break_22",
    "fieldtype": "Column Break"
@@ -514,7 +514,7 @@
  "idx": 5,
  "image_field": "image",
  "links": [],
- "modified": "2022-07-22 15:55:03.176094",
+ "modified": "2022-08-09 18:26:17.101521",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lead",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 68a2156..fed0c7c 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -463,7 +463,7 @@
    "fieldname": "no_of_employees",
    "fieldtype": "Select",
    "label": "No of Employees",
-   "options": "1-10\n11-20\n21-30\n31-100\n11-50\n51-200\n201-500\n101-500\n500-1000\n501-1000\n>1000\n1000+"
+   "options": "1-10\n11-50\n51-200\n201-500\n501-1000\n1000+"
   },
   {
    "fieldname": "annual_revenue",
@@ -622,7 +622,7 @@
  "icon": "fa fa-info-sign",
  "idx": 195,
  "links": [],
- "modified": "2022-07-22 18:46:32.858696",
+ "modified": "2022-08-09 18:26:37.235964",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Opportunity",
diff --git a/erpnext/crm/doctype/prospect/prospect.json b/erpnext/crm/doctype/prospect/prospect.json
index 7f33c08..820a6c7 100644
--- a/erpnext/crm/doctype/prospect/prospect.json
+++ b/erpnext/crm/doctype/prospect/prospect.json
@@ -82,7 +82,7 @@
    "fieldname": "no_of_employees",
    "fieldtype": "Select",
    "label": "No. of Employees",
-   "options": "1-10\n11-20\n21-30\n31-100\n11-50\n51-200\n201-500\n101-500\n500-1000\n501-1000\n>1000\n1000+"
+   "options": "1-10\n11-50\n51-200\n201-500\n501-1000\n1000+"
   },
   {
    "fieldname": "annual_revenue",
@@ -218,7 +218,7 @@
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2022-06-22 15:10:26.887502",
+ "modified": "2022-08-09 18:26:56.950185",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Prospect",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index aa10e31..c4f0c59 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -507,6 +507,7 @@
 	"Shipping Rule",
 	"Landed Cost Item",
 	"Asset Value Adjustment",
+	"Asset Repair",
 	"Loyalty Program",
 	"Stock Reconciliation",
 	"POS Profile",
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1d5f5d7..e5beacd 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -268,6 +268,7 @@
 erpnext.patches.v13_0.show_india_localisation_deprecation_warning
 erpnext.patches.v13_0.show_hr_payroll_deprecation_warning
 erpnext.patches.v13_0.reset_corrupt_defaults
+erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair
 
 [post_model_sync]
 execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')
@@ -308,4 +309,5 @@
 erpnext.patches.v14_0.crm_ux_cleanup
 erpnext.patches.v14_0.remove_india_localisation # 14-07-2022
 erpnext.patches.v13_0.fix_number_and_frequency_for_monthly_depreciation
-erpnext.patches.v14_0.remove_hr_and_payroll_modules # 20-07-2022
\ No newline at end of file
+erpnext.patches.v14_0.remove_hr_and_payroll_modules # 20-07-2022
+erpnext.patches.v14_0.fix_crm_no_of_employees
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/create_accounting_dimensions_for_asset_repair.py b/erpnext/patches/v13_0/create_accounting_dimensions_for_asset_repair.py
new file mode 100644
index 0000000..61a5c86
--- /dev/null
+++ b/erpnext/patches/v13_0/create_accounting_dimensions_for_asset_repair.py
@@ -0,0 +1,29 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_field
+
+
+def execute():
+	accounting_dimensions = frappe.db.get_all(
+		"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
+	)
+
+	if not accounting_dimensions:
+		return
+
+	for d in accounting_dimensions:
+		doctype = "Asset Repair"
+		field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
+
+		if field:
+			continue
+
+		df = {
+			"fieldname": d.fieldname,
+			"label": d.label,
+			"fieldtype": "Link",
+			"options": d.document_type,
+			"insert_after": "accounting_dimensions_section",
+		}
+
+		create_custom_field(doctype, df, ignore_validate=True)
+		frappe.clear_cache(doctype=doctype)
diff --git a/erpnext/patches/v14_0/fix_crm_no_of_employees.py b/erpnext/patches/v14_0/fix_crm_no_of_employees.py
new file mode 100644
index 0000000..268eb95
--- /dev/null
+++ b/erpnext/patches/v14_0/fix_crm_no_of_employees.py
@@ -0,0 +1,26 @@
+import frappe
+
+
+def execute():
+	options = {
+		"11-20": "11-50",
+		"21-30": "11-50",
+		"31-100": "51-200",
+		"101-500": "201-500",
+		"500-1000": "501-1000",
+		">1000": "1000+",
+	}
+
+	for doctype in ("Lead", "Opportunity", "Prospect"):
+		frappe.reload_doctype(doctype)
+		for key, value in options.items():
+			frappe.db.sql(
+				"""
+                update `tab{doctype}`
+                set no_of_employees = %s
+                where no_of_employees = %s
+            """.format(
+					doctype=doctype
+				),
+				(value, key),
+			)
diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
index 27b0169..27c8fe4 100644
--- a/erpnext/portal/doctype/homepage_section/test_homepage_section.py
+++ b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
@@ -57,7 +57,11 @@
 		self.assertEqual(cards[0].h5.text, "Card 1")
 		self.assertEqual(cards[0].a["href"], "/card-1")
 		self.assertEqual(cards[1].p.text, "Subtitle 2")
-		self.assertEqual(cards[1].find(class_="website-image-lazy")["data-src"], "test.jpg")
+
+		img = cards[1].find(class_="card-img-top")
+
+		self.assertEqual(img["src"], "test.jpg")
+		self.assertEqual(img["loading"], "lazy")
 
 		# cleanup
 		frappe.db.rollback()
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index 13d5069..c12a9f8 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -253,16 +253,20 @@
 			"POS Invoice",
 			filters={"customer": ["like", "%{}%".format(search_term)], "status": status},
 			fields=fields,
+			page_length=limit,
 		)
 		invoices_by_name = frappe.db.get_all(
 			"POS Invoice",
 			filters={"name": ["like", "%{}%".format(search_term)], "status": status},
 			fields=fields,
+			page_length=limit,
 		)
 
 		invoice_list = invoices_by_customer + invoices_by_name
 	elif status:
-		invoice_list = frappe.db.get_all("POS Invoice", filters={"status": status}, fields=fields)
+		invoice_list = frappe.db.get_all(
+			"POS Invoice", filters={"status": status}, fields=fields, page_length=limit
+		)
 
 	return invoice_list
 
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index fd1aece..3524a47 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -646,6 +646,24 @@
 					voucher_detail_no=sle.voucher_detail_no,
 					sle=sle,
 				)
+
+			elif (
+				sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
+				and sle.actual_qty > 0
+				and frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_internal_supplier")
+			):
+				sle_details = frappe.db.get_value(
+					"Stock Ledger Entry",
+					{
+						"voucher_type": sle.voucher_type,
+						"voucher_no": sle.voucher_no,
+						"dependant_sle_voucher_detail_no": sle.voucher_detail_no,
+					},
+					["stock_value_difference", "actual_qty"],
+					as_dict=1,
+				)
+
+				rate = abs(sle_details.stock_value_difference / sle.actual_qty)
 			else:
 				if sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
 					rate_field = "valuation_rate"
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index 3e20e50..f56dc3a 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -46,7 +46,7 @@
 		<div class="col-md-{{ section.column_value }} mb-4">
 			<div class="card h-100 justify-content-between">
 				{% if card.image %}
-				<div class="website-image-lazy" data-class="card-img-top h-75" data-src="{{ card.image }}" data-alt="{{ card.title }}"></div>
+				<img class="card-img-top h-75" src="{{ card.image }}" loading="lazy" alt="{{ card.title }}"></img>
 				{% endif %}
 				<div class="card-body">
 					<h5 class="card-title">{{ card.title }}</h5>
diff --git a/erpnext/templates/pages/home.html b/erpnext/templates/pages/home.html
index 4c69b83..27d966a 100644
--- a/erpnext/templates/pages/home.html
+++ b/erpnext/templates/pages/home.html
@@ -37,7 +37,7 @@
 			{% for item in homepage.products %}
 			<div class="col-md-4 mb-4">
 				<div class="card h-100 justify-content-between">
-					<div class="website-image-lazy" data-class="card-img-top website-image-extra-large" data-src="{{ item.image }}" data-alt="{{ item.item_name }}"></div>
+					<img class="card-img-top website-image-extra-large" src="{{ item.image }}" loading="lazy" alt="{{ item.item_name }}"></img>
 					<div class="card-body flex-grow-0">
 						<h5 class="card-title">{{ item.item_name }}</h5>
 						<a href="{{ item.route }}" class="card-link">{{ _('More details') }}</a>
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 01795af..d6bceb3 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -4051,7 +4051,7 @@
 Service Level Agreement has been changed to {0}.,Service Level Agreement wurde in {0} geändert.,
 Service Level Agreement was reset.,Service Level Agreement wurde zurückgesetzt.,
 Service Level Agreement with Entity Type {0} and Entity {1} already exists.,Service Level Agreement mit Entitätstyp {0} und Entität {1} ist bereits vorhanden.,
-Set,Menge,
+Set Loyalty Program,Treueprogramm eintragen,
 Set Meta Tags,Festlegen von Meta-Tags,
 Set {0} in company {1},{0} in Firma {1} festlegen,
 Setup,Einstellungen,
@@ -4231,10 +4231,8 @@
 Write Off,Abschreiben,
 {0} Created,{0} Erstellt,
 Email Id,E-Mail-ID,
-No,Kein,
 Reference Doctype,Referenz-DocType,
 User Id,Benutzeridentifikation,
-Yes,Ja,
 Actual ,Tatsächlich,
 Add to cart,In den Warenkorb legen,
 Budget,Budget,