Merge pull request #32005 from niyazrazak/patch-4

fix: lost quotation not to expired
diff --git a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
index 4596b00..22842ce 100644
--- a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
+++ b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
@@ -22,7 +22,8 @@
   "amount",
   "account_currency",
   "amount_in_account_currency",
-  "delinked"
+  "delinked",
+  "remarks"
  ],
  "fields": [
   {
@@ -136,12 +137,17 @@
    "fieldtype": "Link",
    "label": "Finance Book",
    "options": "Finance Book"
+  },
+  {
+   "fieldname": "remarks",
+   "fieldtype": "Text",
+   "label": "Remarks"
   }
  ],
  "in_create": 1,
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2022-07-11 09:13:54.379168",
+ "modified": "2022-08-22 15:32:56.629430",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Ledger Entry",
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 0238711..0b4e577 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -179,6 +179,11 @@
 			"hidden": 1
 		},
 		{
+			"fieldname": "show_remarks",
+			"label": __("Show Remarks"),
+			"fieldtype": "Check",
+		},
+		{
 			"fieldname": "customer_name",
 			"label": __("Customer Name"),
 			"fieldtype": "Data",
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index f4f2989..3f504b1 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -119,6 +119,7 @@
 					party_account=ple.account,
 					posting_date=ple.posting_date,
 					account_currency=ple.account_currency,
+					remarks=ple.remarks,
 					invoiced=0.0,
 					paid=0.0,
 					credit_note=0.0,
@@ -697,6 +698,7 @@
 				ple.account_currency,
 				ple.amount,
 				ple.amount_in_account_currency,
+				ple.remarks,
 			)
 			.where(ple.delinked == 0)
 			.where(Criterion.all(self.qb_selection_filter))
@@ -975,6 +977,9 @@
 				options="Supplier Group",
 			)
 
+		if self.filters.show_remarks:
+			self.add_column(label=_("Remarks"), fieldname="remarks", fieldtype="Text", width=200),
+
 	def add_column(self, label, fieldname=None, fieldtype="Currency", options=None, width=120):
 		if not fieldname:
 			fieldname = scrub(label)
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 018e8f9..f61e8ac 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -1424,6 +1424,7 @@
 						"amount": dr_or_cr,
 						"amount_in_account_currency": dr_or_cr_account_currency,
 						"delinked": True if cancel else False,
+						"remarks": gle.remarks,
 					}
 				)
 
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index bc38d08..9dbcdb0 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -41,6 +41,7 @@
 		if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"):
 			self.doc.grand_total -= self.doc.discount_amount
 			self.doc.base_grand_total -= self.doc.base_discount_amount
+			self.set_rounded_total()
 
 		self.calculate_shipping_charges()
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d92353a..4729add 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -311,4 +311,5 @@
 erpnext.patches.v13_0.fix_number_and_frequency_for_monthly_depreciation
 erpnext.patches.v14_0.remove_hr_and_payroll_modules # 20-07-2022
 erpnext.patches.v14_0.fix_crm_no_of_employees
-erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes
\ No newline at end of file
+erpnext.patches.v14_0.create_accounting_dimensions_in_subcontracting_doctypes
+erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger
diff --git a/erpnext/patches/v13_0/add_doctype_to_sla.py b/erpnext/patches/v13_0/add_doctype_to_sla.py
index 5f5974f..2d3b0de 100644
--- a/erpnext/patches/v13_0/add_doctype_to_sla.py
+++ b/erpnext/patches/v13_0/add_doctype_to_sla.py
@@ -14,7 +14,8 @@
 
 	for sla in frappe.get_all("Service Level Agreement"):
 		agreement = frappe.get_doc("Service Level Agreement", sla.name)
-		agreement.document_type = "Issue"
+		agreement.db_set("document_type", "Issue")
+		agreement.reload()
 		agreement.apply_sla_for_resolution = 1
 		agreement.append("sla_fulfilled_on", {"status": "Resolved"})
 		agreement.append("sla_fulfilled_on", {"status": "Closed"})
diff --git a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py
new file mode 100644
index 0000000..062d24b
--- /dev/null
+++ b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py
@@ -0,0 +1,56 @@
+import frappe
+from frappe import qb
+from frappe.utils import create_batch
+
+
+def execute():
+	if frappe.reload_doc("accounts", "doctype", "payment_ledger_entry"):
+
+		gle = qb.DocType("GL Entry")
+		ple = qb.DocType("Payment Ledger Entry")
+
+		# get ple and their remarks from GL Entry
+		pl_entries = (
+			qb.from_(ple)
+			.left_join(gle)
+			.on(
+				(ple.account == gle.account)
+				& (ple.party_type == gle.party_type)
+				& (ple.party == gle.party)
+				& (ple.voucher_type == gle.voucher_type)
+				& (ple.voucher_no == gle.voucher_no)
+				& (ple.company == gle.company)
+			)
+			.select(
+				ple.company,
+				ple.account,
+				ple.party_type,
+				ple.party,
+				ple.voucher_type,
+				ple.voucher_no,
+				gle.remarks.as_("gle_remarks"),
+			)
+			.where((ple.delinked == 0) & (gle.is_cancelled == 0))
+			.run(as_dict=True)
+		)
+
+		if pl_entries:
+			# split into multiple batches, update and commit for each batch
+			batch_size = 1000
+			for batch in create_batch(pl_entries, batch_size):
+				for entry in batch:
+					query = (
+						qb.update(ple)
+						.set(ple.remarks, entry.gle_remarks)
+						.where(
+							(ple.company == entry.company)
+							& (ple.account == entry.account)
+							& (ple.party_type == entry.party_type)
+							& (ple.party == entry.party)
+							& (ple.voucher_type == entry.voucher_type)
+							& (ple.voucher_no == entry.voucher_no)
+						)
+					)
+					query.run()
+
+				frappe.db.commit()
diff --git a/erpnext/projects/doctype/task_type/task_type.json b/erpnext/projects/doctype/task_type/task_type.json
index 3254444..b04264e 100644
--- a/erpnext/projects/doctype/task_type/task_type.json
+++ b/erpnext/projects/doctype/task_type/task_type.json
@@ -1,127 +1,70 @@
 {
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "actions": [],
  "autoname": "Prompt",
- "beta": 0,
  "creation": "2019-04-19 15:04:05.317138",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
- "document_type": "",
- "editable_grid": 0,
  "engine": "InnoDB",
+ "field_order": [
+  "weight",
+  "description"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fetch_if_empty": 0,
    "fieldname": "weight",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "label": "Weight",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "label": "Weight"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fetch_if_empty": 0,
    "fieldname": "description",
    "fieldtype": "Small Text",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "label": "Description",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "label": "Description"
   }
  ],
- "has_web_view": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-04-19 15:31:48.080164",
+ "links": [],
+ "modified": "2022-08-29 17:46:41.342979",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Task Type",
- "name_case": "",
+ "naming_rule": "Set by user",
  "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "System Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Projects Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Projects User",
+   "share": 1
   }
  ],
  "quick_entry": 1,
- "read_only": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
  "sort_order": "ASC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "states": [],
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 7721efb..d709522 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -2568,27 +2568,26 @@
 
 @frappe.whitelist()
 def get_items_from_subcontracting_order(source_name, target_doc=None):
-	sco = frappe.get_doc("Subcontracting Order", source_name)
+	def post_process(source, target):
+		target.stock_entry_type = target.purpose = "Send to Subcontractor"
+		target.subcontracting_order = source_name
 
-	if sco.docstatus == 1:
-		if target_doc and isinstance(target_doc, str):
-			target_doc = frappe.get_doc(json.loads(target_doc))
-
-		if target_doc.items:
-			target_doc.items = []
+		if target.items:
+			target.items = []
 
 		warehouses = {}
-		for item in sco.items:
+		for item in source.items:
 			warehouses[item.name] = item.warehouse
 
-		for item in sco.supplied_items:
-			target_doc.append(
+		for item in source.supplied_items:
+			target.append(
 				"items",
 				{
 					"s_warehouse": warehouses.get(item.reference_name),
-					"t_warehouse": sco.supplier_warehouse,
+					"t_warehouse": source.supplier_warehouse,
+					"subcontracted_item": item.main_item_code,
 					"item_code": item.rm_item_code,
-					"qty": item.required_qty,
+					"qty": max(item.required_qty - item.total_supplied_qty, 0),
 					"transfer_qty": item.required_qty,
 					"uom": item.stock_uom,
 					"stock_uom": item.stock_uom,
@@ -2596,6 +2595,23 @@
 				},
 			)
 
+	target_doc = get_mapped_doc(
+		"Subcontracting Order",
+		source_name,
+		{
+			"Subcontracting Order": {
+				"doctype": "Stock Entry",
+				"field_no_map": ["purchase_order"],
+				"validation": {
+					"docstatus": ["=", 1],
+				},
+			},
+		},
+		target_doc,
+		post_process,
+		ignore_child_tables=True,
+	)
+
 	return target_doc
 
 
diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
index bbc58fe..065ef39 100644
--- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
+++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
@@ -164,10 +164,7 @@
 				if (flt(doc.per_received) < 100) {
 					cur_frm.add_custom_button(__('Subcontracting Receipt'), this.make_subcontracting_receipt, __('Create'));
 					if (me.has_unsupplied_items()) {
-						cur_frm.add_custom_button(__('Material to Supplier'),
-							() => {
-								me.make_stock_entry();
-							}, __('Transfer'));
+						cur_frm.add_custom_button(__('Material to Supplier'), this.make_stock_entry, __('Transfer'));
 					}
 				}
 				cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
@@ -195,120 +192,6 @@
 		transaction_controller.autofill_warehouse(child_table, warehouse_field, warehouse);
 	}
 
-	make_stock_entry() {
-		var items = $.map(cur_frm.doc.items, (d) => d.bom ? d.item_code : false);
-		var me = this;
-
-		if (items.length >= 1) {
-			me.raw_material_data = [];
-			me.show_dialog = 1;
-			let title = __('Transfer Material to Supplier');
-			let fields = [
-				{ fieldtype: 'Section Break', label: __('Raw Materials') },
-				{
-					fieldname: 'sub_con_rm_items', fieldtype: 'Table', label: __('Items'),
-					fields: [
-						{
-							fieldtype: 'Data',
-							fieldname: 'item_code',
-							label: __('Item'),
-							read_only: 1,
-							in_list_view: 1
-						},
-						{
-							fieldtype: 'Data',
-							fieldname: 'rm_item_code',
-							label: __('Raw Material'),
-							read_only: 1,
-							in_list_view: 1
-						},
-						{
-							fieldtype: 'Float',
-							read_only: 1,
-							fieldname: 'qty',
-							label: __('Quantity'),
-							in_list_view: 1
-						},
-						{
-							fieldtype: 'Data',
-							read_only: 1,
-							fieldname: 'warehouse',
-							label: __('Reserve Warehouse'),
-							in_list_view: 1
-						},
-						{
-							fieldtype: 'Float',
-							read_only: 1,
-							fieldname: 'rate',
-							label: __('Rate'),
-							hidden: 1
-						},
-						{
-							fieldtype: 'Float',
-							read_only: 1,
-							fieldname: 'amount',
-							label: __('Amount'),
-							hidden: 1
-						},
-						{
-							fieldtype: 'Link',
-							read_only: 1,
-							fieldname: 'uom',
-							label: __('UOM'),
-							hidden: 1
-						}
-					],
-					data: me.raw_material_data,
-					get_data: () => me.raw_material_data
-				}
-			];
-
-			me.dialog = new frappe.ui.Dialog({
-				title: title, fields: fields
-			});
-
-			if (me.frm.doc['supplied_items']) {
-				me.frm.doc['supplied_items'].forEach((item) => {
-					if (item.rm_item_code && item.main_item_code && item.required_qty - item.supplied_qty != 0) {
-						me.raw_material_data.push({
-							'name': item.name,
-							'item_code': item.main_item_code,
-							'rm_item_code': item.rm_item_code,
-							'item_name': item.rm_item_code,
-							'qty': item.required_qty - item.supplied_qty,
-							'warehouse': item.reserve_warehouse,
-							'rate': item.rate,
-							'amount': item.amount,
-							'stock_uom': item.stock_uom
-						});
-						me.dialog.fields_dict.sub_con_rm_items.grid.refresh();
-					}
-				});
-			}
-
-			me.dialog.get_field('sub_con_rm_items').check_all_rows();
-
-			me.dialog.show();
-			this.dialog.set_primary_action(__('Transfer'), () => {
-				me.values = me.dialog.get_values();
-				if (me.values) {
-					me.values.sub_con_rm_items.map((row, i) => {
-						if (!row.item_code || !row.rm_item_code || !row.warehouse || !row.qty || row.qty === 0) {
-							let row_id = i + 1;
-							frappe.throw(__('Item Code, warehouse and quantity are required on row {0}', [row_id]));
-						}
-					});
-					me.make_rm_stock_entry(me.dialog.fields_dict.sub_con_rm_items.grid.get_selected_children());
-					me.dialog.hide();
-				}
-			});
-		}
-
-		me.dialog.get_close_btn().on('click', () => {
-			me.dialog.hide();
-		});
-	}
-
 	has_unsupplied_items() {
 		return this.frm.doc['supplied_items'].some(item => item.required_qty > item.supplied_qty);
 	}
@@ -321,6 +204,15 @@
 		});
 	}
 
+	make_stock_entry() {
+		frappe.model.open_mapped_doc({
+			method: 'erpnext.stock.doctype.stock_entry.stock_entry.get_items_from_subcontracting_order',
+			source_name: cur_frm.doc.name,
+			freeze: true,
+			freeze_message: __('Creating Stock Entry ...')
+		});
+	}
+
 	make_rm_stock_entry(rm_items) {
 		frappe.call({
 			method: 'erpnext.controllers.subcontracting_controller.make_rm_stock_entry',