From 815c616f18ae1cd6ec1dbd315fa5f0376edef523 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 15:26:52 +0530 Subject: [PATCH 001/202] chore: remove 'Bulk Transaction Log' doctype --- .../doctype/bulk_transaction_log/__init__.py | 0 .../bulk_transaction_log.js | 30 ------- .../bulk_transaction_log.json | 51 ------------ .../bulk_transaction_log.py | 67 ---------------- .../test_bulk_transaction_log.py | 79 ------------------- 5 files changed, 227 deletions(-) delete mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/__init__.py delete mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js delete mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json delete mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py delete mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/__init__.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js deleted file mode 100644 index 0073170a85..0000000000 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Bulk Transaction Log', { - - refresh: function(frm) { - frm.disable_save(); - frm.add_custom_button(__('Retry Failed Transactions'), ()=>{ - frappe.confirm(__("Retry Failing Transactions ?"), ()=>{ - query(frm, 1); - } - ); - }); - } -}); - -function query(frm) { - frappe.call({ - method: "erpnext.bulk_transaction.doctype.bulk_transaction_log.bulk_transaction_log.retry_failing_transaction", - args: { - log_date: frm.doc.log_date - } - }).then((r) => { - if (r.message === "No Failed Records") { - frappe.show_alert(__(r.message), 5); - } else { - frappe.show_alert(__("Retrying Failed Transactions"), 5); - } - }); -} \ No newline at end of file diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json deleted file mode 100644 index da42cf1bd4..0000000000 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "actions": [], - "allow_rename": 1, - "creation": "2021-11-30 13:41:16.343827", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "log_date", - "logger_data" - ], - "fields": [ - { - "fieldname": "log_date", - "fieldtype": "Date", - "label": "Log Date", - "read_only": 1 - }, - { - "fieldname": "logger_data", - "fieldtype": "Table", - "label": "Logger Data", - "options": "Bulk Transaction Log Detail" - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2022-02-03 17:23:02.935325", - "modified_by": "Administrator", - "module": "Bulk Transaction", - "name": "Bulk Transaction Log", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "track_changes": 1 -} \ No newline at end of file diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py deleted file mode 100644 index 0596be4462..0000000000 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from datetime import date - -import frappe -from frappe.model.document import Document - -from erpnext.utilities.bulk_transaction import task, update_logger - - -class BulkTransactionLog(Document): - pass - - -@frappe.whitelist() -def retry_failing_transaction(log_date=None): - if not log_date: - log_date = str(date.today()) - btp = frappe.qb.DocType("Bulk Transaction Log Detail") - data = ( - frappe.qb.from_(btp) - .select(btp.transaction_name, btp.from_doctype, btp.to_doctype) - .distinct() - .where(btp.retried != 1) - .where(btp.transaction_status == "Failed") - .where(btp.date == log_date) - ).run(as_dict=True) - - if data: - if len(data) > 10: - frappe.enqueue(job, queue="long", job_name="bulk_retry", data=data, log_date=log_date) - else: - job(data, log_date) - else: - return "No Failed Records" - - -def job(data, log_date): - for d in data: - failed = [] - try: - frappe.db.savepoint("before_creation_of_record") - task(d.transaction_name, d.from_doctype, d.to_doctype) - except Exception as e: - frappe.db.rollback(save_point="before_creation_of_record") - failed.append(e) - update_logger( - d.transaction_name, - e, - d.from_doctype, - d.to_doctype, - status="Failed", - log_date=log_date, - restarted=1, - ) - - if not failed: - update_logger( - d.transaction_name, - None, - d.from_doctype, - d.to_doctype, - status="Success", - log_date=log_date, - restarted=1, - ) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py deleted file mode 100644 index c673be89b3..0000000000 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest -from datetime import date - -import frappe - -from erpnext.utilities.bulk_transaction import transaction_processing - - -class TestBulkTransactionLog(unittest.TestCase): - def setUp(self): - create_company() - create_customer() - create_item() - - def test_entry_in_log(self): - so_name = create_so() - transaction_processing([{"name": so_name}], "Sales Order", "Sales Invoice") - doc = frappe.get_doc("Bulk Transaction Log", str(date.today())) - for d in doc.get("logger_data"): - if d.transaction_name == so_name: - self.assertEqual(d.transaction_name, so_name) - self.assertEqual(d.transaction_status, "Success") - self.assertEqual(d.from_doctype, "Sales Order") - self.assertEqual(d.to_doctype, "Sales Invoice") - self.assertEqual(d.retried, 0) - - -def create_company(): - if not frappe.db.exists("Company", "_Test Company"): - frappe.get_doc( - { - "doctype": "Company", - "company_name": "_Test Company", - "country": "India", - "default_currency": "INR", - } - ).insert() - - -def create_customer(): - if not frappe.db.exists("Customer", "Bulk Customer"): - frappe.get_doc({"doctype": "Customer", "customer_name": "Bulk Customer"}).insert() - - -def create_item(): - if not frappe.db.exists("Item", "MK"): - frappe.get_doc( - { - "doctype": "Item", - "item_code": "MK", - "item_name": "Milk", - "description": "Milk", - "item_group": "Products", - } - ).insert() - - -def create_so(intent=None): - so = frappe.new_doc("Sales Order") - so.customer = "Bulk Customer" - so.company = "_Test Company" - so.transaction_date = date.today() - - so.set_warehouse = "Finished Goods - _TC" - so.append( - "items", - { - "item_code": "MK", - "delivery_date": date.today(), - "qty": 10, - "rate": 80, - }, - ) - so.insert() - so.submit() - return so.name From e5a8ad54e26d74b5713e7db057860c1262c1b93b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 15:29:57 +0530 Subject: [PATCH 002/202] chore: convert child to normal table --- .../bulk_transaction_log_detail.js | 8 ++++++++ .../bulk_transaction_log_detail.json | 18 +++++++++++++++--- .../test_bulk_transaction_log_detail.py | 9 +++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.js create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/test_bulk_transaction_log_detail.py diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.js new file mode 100644 index 0000000000..5669601d11 --- /dev/null +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.js @@ -0,0 +1,8 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Bulk Transaction Log Detail", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json index 8262caa020..64518de4c0 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json @@ -71,14 +71,26 @@ } ], "index_web_pages_for_search": 1, - "istable": 1, "links": [], - "modified": "2022-02-03 19:57:31.650359", + "modified": "2023-11-09 15:29:33.013547", "modified_by": "Administrator", "module": "Bulk Transaction", "name": "Bulk Transaction Log Detail", "owner": "Administrator", - "permissions": [], + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], "sort_field": "modified", "sort_order": "DESC", "states": [], diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/test_bulk_transaction_log_detail.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/test_bulk_transaction_log_detail.py new file mode 100644 index 0000000000..5217b601f8 --- /dev/null +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/test_bulk_transaction_log_detail.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestBulkTransactionLogDetail(FrappeTestCase): + pass From c4f8f3613f1173a54b17e3c6ca8ea52469f32e3b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 16:07:45 +0530 Subject: [PATCH 003/202] chore: rearrange fields --- .../bulk_transaction_log_detail.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json index 64518de4c0..051dc0af02 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json @@ -6,12 +6,12 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "from_doctype", "transaction_name", "date", "time", "transaction_status", "error_description", - "from_doctype", "to_doctype", "retried" ], @@ -72,7 +72,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-09 15:29:33.013547", + "modified": "2023-11-09 15:33:26.828998", "modified_by": "Administrator", "module": "Bulk Transaction", "name": "Bulk Transaction Log Detail", From ebd74a4e5b68534a4ceab2482618e16643f220d1 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 16:38:34 +0530 Subject: [PATCH 004/202] refactor: simplify logging logic bulk_transaction --- erpnext/utilities/bulk_transaction.py | 74 +++++---------------------- 1 file changed, 14 insertions(+), 60 deletions(-) diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index fcee265644..fd8e722648 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -3,6 +3,7 @@ from datetime import date, datetime import frappe from frappe import _ +from frappe.utils import today @frappe.whitelist() @@ -38,7 +39,7 @@ def job(deserialized_data, from_doctype, to_doctype): except Exception as e: frappe.db.rollback(save_point="before_creation_state") fail_count += 1 - update_logger( + create_log( doc_name, str(frappe.get_traceback()), from_doctype, @@ -47,7 +48,7 @@ def job(deserialized_data, from_doctype, to_doctype): log_date=str(date.today()), ) else: - update_logger( + create_log( doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today()) ) @@ -108,45 +109,18 @@ def task(doc_name, from_doctype, to_doctype): obj.insert(ignore_mandatory=True) -def check_logger_doc_exists(log_date): - return frappe.db.exists("Bulk Transaction Log", log_date) - - -def get_logger_doc(log_date): - return frappe.get_doc("Bulk Transaction Log", log_date) - - -def create_logger_doc(): - log_doc = frappe.new_doc("Bulk Transaction Log") - log_doc.set_new_name(set_name=str(date.today())) - log_doc.log_date = date.today() - - return log_doc - - -def append_data_to_logger(log_doc, doc_name, error, from_doctype, to_doctype, status, restarted): - row = log_doc.append("logger_data", {}) - row.transaction_name = doc_name - row.date = date.today() +def create_log(doc_name, e, from_doctype, to_doctype, status, log_date=None, restarted=0): + transaction_log = frappe.new_doc("Bulk Transaction Log Detail") + transaction_log.transaction_name = doc_name + transaction_log.date = today() now = datetime.now() - row.time = now.strftime("%H:%M:%S") - row.transaction_status = status - row.error_description = str(error) - row.from_doctype = from_doctype - row.to_doctype = to_doctype - row.retried = restarted - - -def update_logger(doc_name, e, from_doctype, to_doctype, status, log_date=None, restarted=0): - if not check_logger_doc_exists(log_date): - log_doc = create_logger_doc() - append_data_to_logger(log_doc, doc_name, e, from_doctype, to_doctype, status, restarted) - log_doc.insert() - else: - log_doc = get_logger_doc(log_date) - if record_exists(log_doc, doc_name, status): - append_data_to_logger(log_doc, doc_name, e, from_doctype, to_doctype, status, restarted) - log_doc.save() + transaction_log.time = now.strftime("%H:%M:%S") + transaction_log.transaction_status = status + transaction_log.error_description = str(e) + transaction_log.from_doctype = from_doctype + transaction_log.to_doctype = to_doctype + transaction_log.retried = restarted + transaction_log.save() def show_job_status(fail_count, deserialized_data_count, to_doctype): @@ -176,23 +150,3 @@ def show_job_status(fail_count, deserialized_data_count, to_doctype): title="Failed", indicator="red", ) - - -def record_exists(log_doc, doc_name, status): - record = mark_retrired_transaction(log_doc, doc_name) - if record and status == "Failed": - return False - elif record and status == "Success": - return True - else: - return True - - -def mark_retrired_transaction(log_doc, doc_name): - record = 0 - for d in log_doc.get("logger_data"): - if d.transaction_name == doc_name and d.transaction_status == "Failed": - frappe.db.set_value("Bulk Transaction Log Detail", d.name, "retried", 1) - record = record + 1 - - return record From ade09bc709ab8bca047abdad5235461a4618bc17 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 17:16:58 +0530 Subject: [PATCH 005/202] chore: add list view filters --- .../bulk_transaction_log_detail.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json index 051dc0af02..3a5d434a04 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json @@ -20,6 +20,7 @@ "fieldname": "transaction_name", "fieldtype": "Dynamic Link", "in_list_view": 1, + "in_standard_filter": 1, "label": "Name", "options": "from_doctype" }, @@ -39,6 +40,7 @@ { "fieldname": "from_doctype", "fieldtype": "Link", + "in_standard_filter": 1, "label": "From Doctype", "options": "DocType", "read_only": 1 @@ -54,6 +56,7 @@ "fieldname": "date", "fieldtype": "Date", "in_list_view": 1, + "in_standard_filter": 1, "label": "Date ", "read_only": 1 }, @@ -70,9 +73,10 @@ "read_only": 1 } ], + "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-09 15:33:26.828998", + "modified": "2023-11-09 16:55:31.026064", "modified_by": "Administrator", "module": "Bulk Transaction", "name": "Bulk Transaction Log Detail", From 73090fa1306fd65ff8e290d57486697af5722081 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 17:40:04 +0530 Subject: [PATCH 006/202] chore: add indexes --- .../bulk_transaction_log_detail.json | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json index 3a5d434a04..fe1a6d9b56 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json @@ -22,7 +22,8 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Name", - "options": "from_doctype" + "options": "from_doctype", + "search_index": 1 }, { "fieldname": "transaction_status", @@ -43,7 +44,8 @@ "in_standard_filter": 1, "label": "From Doctype", "options": "DocType", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "fieldname": "to_doctype", @@ -58,7 +60,8 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Date ", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "fieldname": "time", @@ -76,7 +79,7 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-09 16:55:31.026064", + "modified": "2023-11-09 17:44:14.804836", "modified_by": "Administrator", "module": "Bulk Transaction", "name": "Bulk Transaction Log Detail", @@ -99,4 +102,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} From b0dfc936a10aef4dfd743959a6cf5e47ea69632e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 17:43:04 +0530 Subject: [PATCH 007/202] chore: make `from_doctype` readonly --- .../bulk_transaction_log_detail/bulk_transaction_log_detail.json | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json index fe1a6d9b56..5491f56a1a 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json @@ -23,6 +23,7 @@ "in_standard_filter": 1, "label": "Name", "options": "from_doctype", + "read_only": 1, "search_index": 1 }, { From a248b13cc353fcd94b0009c74c24512ea629a376 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 20:15:33 +0530 Subject: [PATCH 008/202] feat: virtual parent doctype --- .../doctype/bulk_transaction_log/__init__.py | 0 .../bulk_transaction_log.js | 8 ++ .../bulk_transaction_log.json | 80 +++++++++++++++++++ .../bulk_transaction_log.py | 28 +++++++ .../test_bulk_transaction_log.py | 9 +++ 5 files changed, 125 insertions(+) create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/__init__.py create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py create mode 100644 erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/__init__.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js new file mode 100644 index 0000000000..07a8009816 --- /dev/null +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js @@ -0,0 +1,8 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Bulk Transaction Log", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json new file mode 100644 index 0000000000..a874b791ca --- /dev/null +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json @@ -0,0 +1,80 @@ +{ + "actions": [], + "allow_copy": 1, + "creation": "2023-11-09 20:14:45.139593", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "date", + "column_break_bsan", + "log_entries", + "section_break_mdmv", + "succeeded", + "column_break_qryp", + "failed" + ], + "fields": [ + { + "fieldname": "date", + "fieldtype": "Date", + "label": "Date", + "read_only": 1 + }, + { + "fieldname": "log_entries", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Log Entries", + "read_only": 1 + }, + { + "fieldname": "column_break_bsan", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_mdmv", + "fieldtype": "Section Break" + }, + { + "fieldname": "succeeded", + "fieldtype": "Int", + "label": "Succeeded", + "read_only": 1 + }, + { + "fieldname": "column_break_qryp", + "fieldtype": "Column Break" + }, + { + "fieldname": "failed", + "fieldtype": "Int", + "label": "Failed", + "read_only": 1 + } + ], + "in_create": 1, + "is_virtual": 1, + "links": [], + "modified": "2023-11-10 11:13:52.733076", + "modified_by": "Administrator", + "module": "Bulk Transaction", + "name": "Bulk Transaction Log", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py new file mode 100644 index 0000000000..fb9fcf7c52 --- /dev/null +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class BulkTransactionLog(Document): + def db_insert(self, *args, **kwargs): + pass + + def load_from_db(self): + pass + + def db_update(self): + pass + + @staticmethod + def get_list(args): + pass + + @staticmethod + def get_count(args): + pass + + @staticmethod + def get_stats(args): + pass diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py new file mode 100644 index 0000000000..01bb615a3e --- /dev/null +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestBulkTransactionLog(FrappeTestCase): + pass From af35590549987ab84eadbf08c10f3837242203dc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 9 Nov 2023 21:07:01 +0530 Subject: [PATCH 009/202] refactor: add basic functionalities --- .../bulk_transaction_log.js | 15 ++-- .../bulk_transaction_log.py | 71 +++++++++++++++++-- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js index 07a8009816..218424beca 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js @@ -1,8 +1,13 @@ // Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -// frappe.ui.form.on("Bulk Transaction Log", { -// refresh(frm) { - -// }, -// }); +frappe.ui.form.on("Bulk Transaction Log", { + refresh(frm) { + frm.add_custom_button(__('Succeeded Entries'), function() { + frappe.set_route('List', 'Bulk Transaction Log Detail', {'date': frm.doc.date, 'transaction_status': "Success"}); + }, __("View")); + frm.add_custom_button(__('Failed Entries'), function() { + frappe.set_route('List', 'Bulk Transaction Log Detail', {'date': frm.doc.date, 'transaction_status': "Failed"}); + }, __("View")); + }, +}); diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py index fb9fcf7c52..4febb48a60 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py @@ -1,8 +1,14 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +import frappe +from frappe import qb from frappe.model.document import Document +from frappe.query_builder.functions import Count +from frappe.utils import cint +from pypika import Order + +log_detail = qb.DocType("Bulk Transaction Log Detail") class BulkTransactionLog(Document): @@ -10,14 +16,51 @@ class BulkTransactionLog(Document): pass def load_from_db(self): - pass - - def db_update(self): - pass + succeeded_logs = ( + qb.from_(log_detail) + .select(Count(log_detail.date).as_("count")) + .where((log_detail.date == self.name) & (log_detail.transaction_status == "Success")) + .run() + )[0][0] or 0 + failed_logs = ( + qb.from_(log_detail) + .select(Count(log_detail.date).as_("count")) + .where((log_detail.date == self.name) & (log_detail.transaction_status == "Failed")) + .run() + )[0][0] or 0 + total_logs = succeeded_logs + failed_logs + transaction_log = frappe._dict( + { + "date": self.name, + "count": total_logs, + "succeeded": succeeded_logs, + "failed": failed_logs, + } + ) + super(Document, self).__init__(serialize_transaction_log(transaction_log)) @staticmethod def get_list(args): - pass + limit = cint(args.get("page_length")) or 20 + dates = ( + qb.from_(log_detail) + .select(log_detail.date) + .distinct() + .orderby(log_detail.date, order=Order.desc) + .limit(limit) + .run() + ) + + transaction_logs = ( + qb.from_(log_detail) + .select(log_detail.date.as_("date"), Count(log_detail.date).as_("count")) + .where(log_detail.date.isin(dates)) + .orderby(log_detail.date, order=Order.desc) + .groupby(log_detail.date) + .limit(limit) + .run(as_dict=True) + ) + return [serialize_transaction_log(x) for x in transaction_logs] @staticmethod def get_count(args): @@ -26,3 +69,19 @@ class BulkTransactionLog(Document): @staticmethod def get_stats(args): pass + + def db_update(self, *args, **kwargs): + pass + + def delete(self): + pass + + +def serialize_transaction_log(data): + return frappe._dict( + name=data.date, + date=data.date, + log_entries=data.count, + succeeded=data.succeeded, + failed=data.failed, + ) From 194d70f8a0c93c8e2952cd58cdc5d994414198fb Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 10 Nov 2023 11:44:25 +0530 Subject: [PATCH 010/202] chore: show retried in list view --- .../bulk_transaction_log_detail.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json index 5491f56a1a..9590325a06 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json @@ -73,6 +73,7 @@ { "fieldname": "retried", "fieldtype": "Int", + "in_list_view": 1, "label": "Retried", "read_only": 1 } @@ -80,7 +81,7 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-09 17:44:14.804836", + "modified": "2023-11-10 11:44:10.758342", "modified_by": "Administrator", "module": "Bulk Transaction", "name": "Bulk Transaction Log Detail", @@ -103,4 +104,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} +} \ No newline at end of file From 0aa1636d04bed9fef260aedde4ed6a42b6a1968b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 10 Nov 2023 12:20:30 +0530 Subject: [PATCH 011/202] refactor: barebones retry functionality --- .../bulk_transaction_log.js | 8 ++++++ erpnext/utilities/bulk_transaction.py | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js index 218424beca..6e2250052d 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js @@ -9,5 +9,13 @@ frappe.ui.form.on("Bulk Transaction Log", { frm.add_custom_button(__('Failed Entries'), function() { frappe.set_route('List', 'Bulk Transaction Log Detail', {'date': frm.doc.date, 'transaction_status': "Failed"}); }, __("View")); + if (frm.doc.failed) { + frm.add_custom_button(__('Retry Failed Transactions'), function() { + frappe.call({ + method: "erpnext.utilities.bulk_transaction.retry_failed_transactions", + args: {date: frm.doc.date} + }).then(()=> { }); + }); + } }, }); diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index fd8e722648..a596001583 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -29,6 +29,34 @@ def transaction_processing(data, from_doctype, to_doctype): job(deserialized_data, from_doctype, to_doctype) +@frappe.whitelist() +def retry_failed_transactions(date: str | None): + if date: + failed_docs = frappe.db.get_all( + "Bulk Transaction Log Detail", + filters={"date": date, "transaction_status": "Failed", "retried": 0}, + fields=["name", "transaction_name", "from_doctype", "to_doctype"], + ) + if not failed_docs: + frappe.msgprint("There are no Failed transactions") + return + + for log in failed_docs: + try: + frappe.db.savepoint("before_creation_state") + task(log.transaction_name, log.from_doctype, log.to_doctype) + except Exception as e: + frappe.db.rollback(save_point="before_creation_state") + update_log(log.name, "Failed", 1) + else: + update_log(log.name, "Success", 1) + + +def update_log(log_name, status, retried): + frappe.db.set_value("Bulk Transaction Log Detail", log_name, "transaction_status", status) + frappe.db.set_value("Bulk Transaction Log Detail", log_name, "retried", retried) + + def job(deserialized_data, from_doctype, to_doctype): fail_count = 0 for d in deserialized_data: From c3202886901eaecc0ab8b9bf73d8816994e6dc1f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 10 Nov 2023 13:45:52 +0530 Subject: [PATCH 012/202] refactor: rollback for retries and UI alerts --- .../bulk_transaction_log.js | 2 +- erpnext/utilities/bulk_transaction.py | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js index 6e2250052d..3135d41cc1 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js @@ -12,7 +12,7 @@ frappe.ui.form.on("Bulk Transaction Log", { if (frm.doc.failed) { frm.add_custom_button(__('Retry Failed Transactions'), function() { frappe.call({ - method: "erpnext.utilities.bulk_transaction.retry_failed_transactions", + method: "erpnext.utilities.bulk_transaction.retry", args: {date: frm.doc.date} }).then(()=> { }); }); diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index a596001583..7e73c2fe0b 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -3,7 +3,7 @@ from datetime import date, datetime import frappe from frappe import _ -from frappe.utils import today +from frappe.utils import get_link_to_form, today @frappe.whitelist() @@ -30,7 +30,7 @@ def transaction_processing(data, from_doctype, to_doctype): @frappe.whitelist() -def retry_failed_transactions(date: str | None): +def retry(date: str | None): if date: failed_docs = frappe.db.get_all( "Bulk Transaction Log Detail", @@ -38,9 +38,21 @@ def retry_failed_transactions(date: str | None): fields=["name", "transaction_name", "from_doctype", "to_doctype"], ) if not failed_docs: - frappe.msgprint("There are no Failed transactions") - return + frappe.msgprint(_("There are no Failed transactions")) + else: + job = frappe.enqueue( + retry_failed_transactions, + failed_docs=failed_docs, + ) + frappe.msgprint( + _("Job: {0} has been triggered for processing failed transactions").format( + get_link_to_form("RQ Job", job.id) + ) + ) + +def retry_failed_transactions(failed_docs: list | None): + if failed_docs: for log in failed_docs: try: frappe.db.savepoint("before_creation_state") From 73639db9105260d0d1af3cea35caa03523f396e5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 10 Nov 2023 15:27:28 +0530 Subject: [PATCH 013/202] chore: resolve linting issue --- .../doctype/bulk_transaction_log/bulk_transaction_log.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py index 4febb48a60..1a078b53d5 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py @@ -8,14 +8,13 @@ from frappe.query_builder.functions import Count from frappe.utils import cint from pypika import Order -log_detail = qb.DocType("Bulk Transaction Log Detail") - class BulkTransactionLog(Document): def db_insert(self, *args, **kwargs): pass def load_from_db(self): + log_detail = qb.DocType("Bulk Transaction Log Detail") succeeded_logs = ( qb.from_(log_detail) .select(Count(log_detail.date).as_("count")) @@ -41,6 +40,7 @@ class BulkTransactionLog(Document): @staticmethod def get_list(args): + log_detail = qb.DocType("Bulk Transaction Log Detail") limit = cint(args.get("page_length")) or 20 dates = ( qb.from_(log_detail) From 93295bf25b67069936e23d03f5a1c559294bc25f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 11 Nov 2023 05:10:16 +0530 Subject: [PATCH 014/202] refactor: support list view filters --- .../bulk_transaction_log.json | 8 +++- .../bulk_transaction_log.py | 42 +++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json index a874b791ca..75cb358ff2 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json @@ -2,6 +2,7 @@ "actions": [], "allow_copy": 1, "creation": "2023-11-09 20:14:45.139593", + "default_view": "List", "doctype": "DocType", "engine": "InnoDB", "field_order": [ @@ -17,6 +18,8 @@ { "fieldname": "date", "fieldtype": "Date", + "in_list_view": 1, + "in_standard_filter": 1, "label": "Date", "read_only": 1 }, @@ -55,7 +58,7 @@ "in_create": 1, "is_virtual": 1, "links": [], - "modified": "2023-11-10 11:13:52.733076", + "modified": "2023-11-11 04:52:49.347376", "modified_by": "Administrator", "module": "Bulk Transaction", "name": "Bulk Transaction Log", @@ -76,5 +79,6 @@ ], "sort_field": "modified", "sort_order": "DESC", - "states": [] + "states": [], + "title_field": "date" } \ No newline at end of file diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py index 1a078b53d5..8ae54ddab8 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py @@ -40,26 +40,33 @@ class BulkTransactionLog(Document): @staticmethod def get_list(args): - log_detail = qb.DocType("Bulk Transaction Log Detail") + filter_date = parse_list_filters(args) limit = cint(args.get("page_length")) or 20 - dates = ( + log_detail = qb.DocType("Bulk Transaction Log Detail") + + dates_query = ( qb.from_(log_detail) .select(log_detail.date) .distinct() .orderby(log_detail.date, order=Order.desc) .limit(limit) - .run() ) + if filter_date: + dates_query = dates_query.where(log_detail.date == filter_date) + dates = dates_query.run() + + transaction_logs = [] + if dates: + transaction_logs_query = ( + qb.from_(log_detail) + .select(log_detail.date.as_("date"), Count(log_detail.date).as_("count")) + .where(log_detail.date.isin(dates)) + .orderby(log_detail.date, order=Order.desc) + .groupby(log_detail.date) + .limit(limit) + ) + transaction_logs = transaction_logs_query.run(as_dict=True) - transaction_logs = ( - qb.from_(log_detail) - .select(log_detail.date.as_("date"), Count(log_detail.date).as_("count")) - .where(log_detail.date.isin(dates)) - .orderby(log_detail.date, order=Order.desc) - .groupby(log_detail.date) - .limit(limit) - .run(as_dict=True) - ) return [serialize_transaction_log(x) for x in transaction_logs] @staticmethod @@ -85,3 +92,14 @@ def serialize_transaction_log(data): succeeded=data.succeeded, failed=data.failed, ) + + +def parse_list_filters(args): + # parse date filter + filter_date = None + for fil in args.get("filters"): + if isinstance(fil, list): + for elem in fil: + if elem == "date": + filter_date = fil[3] + return filter_date From a52a1b49af1c7b72ba85563057f60bb7cf54e81c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 11 Nov 2023 05:20:27 +0530 Subject: [PATCH 015/202] refactor: update traceback on retry --- erpnext/utilities/bulk_transaction.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index 7e73c2fe0b..402c305ca9 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -59,14 +59,16 @@ def retry_failed_transactions(failed_docs: list | None): task(log.transaction_name, log.from_doctype, log.to_doctype) except Exception as e: frappe.db.rollback(save_point="before_creation_state") - update_log(log.name, "Failed", 1) + update_log(log.name, "Failed", 1, str(frappe.get_traceback())) else: update_log(log.name, "Success", 1) -def update_log(log_name, status, retried): +def update_log(log_name, status, retried, err=None): frappe.db.set_value("Bulk Transaction Log Detail", log_name, "transaction_status", status) frappe.db.set_value("Bulk Transaction Log Detail", log_name, "retried", retried) + if err: + frappe.db.set_value("Bulk Transaction Log Detail", log_name, "error_description", err) def job(deserialized_data, from_doctype, to_doctype): From a393a6b76c35d95e4422fbf239c468ab48e67b71 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 13 Nov 2023 10:39:40 +0530 Subject: [PATCH 016/202] refactor: raise exception on invalid date --- .../doctype/bulk_transaction_log/bulk_transaction_log.js | 2 +- .../doctype/bulk_transaction_log/bulk_transaction_log.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js index 3135d41cc1..dc54d606e7 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.js @@ -14,7 +14,7 @@ frappe.ui.form.on("Bulk Transaction Log", { frappe.call({ method: "erpnext.utilities.bulk_transaction.retry", args: {date: frm.doc.date} - }).then(()=> { }); + }); }); } }, diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py index 8ae54ddab8..712caf1f91 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py @@ -15,6 +15,13 @@ class BulkTransactionLog(Document): def load_from_db(self): log_detail = qb.DocType("Bulk Transaction Log Detail") + + has_records = frappe.db.sql( + f"select exists (select * from `tabBulk Transaction Log Detail` where date = '{self.name}');" + )[0][0] + if not has_records: + raise frappe.DoesNotExistError + succeeded_logs = ( qb.from_(log_detail) .select(Count(log_detail.date).as_("count")) From 9ae5c979e894c791087579fdd00aa2cdb6e1e34f Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 14:43:46 +0530 Subject: [PATCH 017/202] fix: Identical items are added line by line instead of grouped together in POS (#37986) fix: Identical items are added line by line instead of grouped together in POS (#37986) fix: Identical items are added line by line instead of grouped together in POS (#37986) (cherry picked from commit 011cf3d73e2f4dd98c4b33c502ca34665e067c57) Co-authored-by: bVisible --- erpnext/selling/page/point_of_sale/pos_controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 9bba4ebf50..feecd9cfd8 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -609,11 +609,12 @@ erpnext.PointOfSale.Controller = class { // if item is clicked twice from item selector // then "item_code, batch_no, uom, rate" will help in getting the exact item // to increase the qty by one - const has_batch_no = batch_no; + const has_batch_no = (batch_no !== 'null' && batch_no !== null); item_row = this.frm.doc.items.find( i => i.item_code === item_code && (!has_batch_no || (has_batch_no && i.batch_no === batch_no)) && (i.uom === uom) + && (i.rate === flt(rate)) ); } From 5b446d45750c45c6a86bb420c689a06945ab4974 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 15:05:34 +0530 Subject: [PATCH 018/202] fix: handle partial return against invoices --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index fc22f53f4d..2634972800 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1074,9 +1074,7 @@ class PaymentEntry(AccountsController): reverse_dr_or_cr, standalone_note = 0, 0 if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]: - is_return, return_against = frappe.db.get_value( - d.reference_doctype, d.reference_name, ["is_return", "return_against"] - ) + is_return = frappe.db.get_value(d.reference_doctype, d.reference_name, "is_return") payable_party_types = get_party_types_from_account_type("Payable") receivable_party_types = get_party_types_from_account_type("Receivable") if is_return and self.party_type in receivable_party_types and (self.payment_type == "Pay"): @@ -1086,7 +1084,7 @@ class PaymentEntry(AccountsController): ): reverse_dr_or_cr = 1 - if is_return and not return_against and not reverse_dr_or_cr: + if is_return and not reverse_dr_or_cr: dr_or_cr = "debit" if dr_or_cr == "credit" else "credit" gle.update( From 56b8d1b9277a1290b18c6745736bef8dfa4e6f90 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 13 Nov 2023 17:00:02 +0530 Subject: [PATCH 019/202] fix: remove ESS role when not mapped to employee (#37867) * fix: remove ESS role when not mapped to employee * fix: emp role removal on unlinking * fix: test case for user employee role mapping * fix: mapped employee and user on creation --- erpnext/setup/doctype/employee/employee.js | 4 ++- erpnext/setup/doctype/employee/employee.py | 29 +++++++++++++++---- .../setup/doctype/employee/test_employee.py | 9 ++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/erpnext/setup/doctype/employee/employee.js b/erpnext/setup/doctype/employee/employee.js index 39a215f383..efc3fd1d33 100755 --- a/erpnext/setup/doctype/employee/employee.js +++ b/erpnext/setup/doctype/employee/employee.js @@ -81,8 +81,10 @@ frappe.ui.form.on("Employee", { employee: frm.doc.name, email: frm.doc.prefered_email }, + freeze: true, + freeze_message: __("Creating User..."), callback: function (r) { - frm.set_value("user_id", r.message); + frm.reload_doc(); } }); } diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index 78fb4dfc58..6f9176cf27 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -48,6 +48,9 @@ class Employee(NestedSet): else: existing_user_id = frappe.db.get_value("Employee", self.name, "user_id") if existing_user_id: + user = frappe.get_doc("User", existing_user_id) + validate_employee_role(user, ignore_emp_check=True) + user.save(ignore_permissions=True) remove_user_permission("Employee", self.name, existing_user_id) def after_rename(self, old, new, merge): @@ -230,12 +233,26 @@ class Employee(NestedSet): frappe.cache().hdel("employees_with_number", prev_number) -def validate_employee_role(doc, method): +def validate_employee_role(doc, method=None, ignore_emp_check=False): # called via User hook - if "Employee" in [d.role for d in doc.get("roles")]: - if not frappe.db.get_value("Employee", {"user_id": doc.name}): - frappe.msgprint(_("Please set User ID field in an Employee record to set Employee Role")) - doc.get("roles").remove(doc.get("roles", {"role": "Employee"})[0]) + if not ignore_emp_check: + if frappe.db.get_value("Employee", {"user_id": doc.name}): + return + + user_roles = [d.role for d in doc.get("roles")] + if "Employee" in user_roles: + frappe.msgprint( + _("User {0}: Removed Employee role as there is no mapped employee.").format(doc.name) + ) + doc.get("roles").remove(doc.get("roles", {"role": "Employee"})[0]) + + if "Employee Self Service" in user_roles: + frappe.msgprint( + _("User {0}: Removed Employee Self Service role as there is no mapped employee.").format( + doc.name + ) + ) + doc.get("roles").remove(doc.get("roles", {"role": "Employee Self Service"})[0]) def update_user_permissions(doc, method): @@ -347,6 +364,8 @@ def create_user(employee, user=None, email=None): } ) user.insert() + emp.user_id = user.name + emp.save() return user.name diff --git a/erpnext/setup/doctype/employee/test_employee.py b/erpnext/setup/doctype/employee/test_employee.py index 5a693c5eff..9b70683626 100644 --- a/erpnext/setup/doctype/employee/test_employee.py +++ b/erpnext/setup/doctype/employee/test_employee.py @@ -25,6 +25,15 @@ class TestEmployee(unittest.TestCase): employee1_doc.status = "Left" self.assertRaises(InactiveEmployeeStatusError, employee1_doc.save) + def test_user_has_employee(self): + employee = make_employee("test_emp_user_creation@company.com") + employee_doc = frappe.get_doc("Employee", employee) + user = employee_doc.user_id + self.assertTrue("Employee" in frappe.get_roles(user)) + employee_doc.user_id = "" + employee_doc.save() + self.assertTrue("Employee" not in frappe.get_roles(user)) + def tearDown(self): frappe.db.rollback() From 2f9e96e3245e210ab1a26ffe99499367b0e0afa5 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 13 Nov 2023 18:03:33 +0530 Subject: [PATCH 020/202] chore: delete comments and unlink attachments on company transactions deletion --- .../transaction_deletion_record.py | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py index 481a3a5ebe..d266285b29 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py @@ -108,7 +108,16 @@ class TransactionDeletionRecord(Document): if no_of_docs > 0: self.delete_version_log(docfield["parent"], docfield["fieldname"]) - self.delete_communications(docfield["parent"], docfield["fieldname"]) + + reference_docs = frappe.get_all( + docfield["parent"], filters={docfield["fieldname"]: self.company} + ) + reference_doc_names = [r.name for r in reference_docs] + + self.delete_communications(docfield["parent"], reference_doc_names) + self.delete_comments(docfield["parent"], reference_doc_names) + self.unlink_attachments(docfield["parent"], reference_doc_names) + self.populate_doctypes_table(tables, docfield["parent"], no_of_docs) self.delete_child_tables(docfield["parent"], docfield["fieldname"]) @@ -197,19 +206,49 @@ class TransactionDeletionRecord(Document): (versions.ref_doctype == doctype) & (versions.docname.isin(batch)) ).run() - def delete_communications(self, doctype, company_fieldname): - reference_docs = frappe.get_all(doctype, filters={company_fieldname: self.company}) - reference_doc_names = [r.name for r in reference_docs] - + def delete_communications(self, doctype, reference_doc_names): communications = frappe.get_all( "Communication", filters={"reference_doctype": doctype, "reference_name": ["in", reference_doc_names]}, ) communication_names = [c.name for c in communications] + if not communication_names: + return + for batch in create_batch(communication_names, self.batch_size): frappe.delete_doc("Communication", batch, ignore_permissions=True) + def delete_comments(self, doctype, reference_doc_names): + comments = frappe.get_all( + "Comment", + filters={"reference_doctype": doctype, "reference_name": ["in", reference_doc_names]}, + ) + comment_names = [c.name for c in comments] + + if not comment_names: + return + + for batch in create_batch(comment_names, self.batch_size): + frappe.delete_doc("Comment", batch, ignore_permissions=True) + + def unlink_attachments(self, doctype, reference_doc_names): + files = frappe.get_all( + "File", + filters={"attached_to_doctype": doctype, "attached_to_name": ["in", reference_doc_names]}, + ) + file_names = [c.name for c in files] + + if not file_names: + return + + file = qb.DocType("File") + + for batch in create_batch(file_names, self.batch_size): + qb.update(file).set(file.attached_to_doctype, None).set(file.attached_to_name, None).where( + file.name.isin(batch) + ).run() + @frappe.whitelist() def get_doctypes_to_be_ignored(): From b097bb20d99f1d25fbd8bdcf0277859741a0ee53 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Mon, 13 Nov 2023 18:09:09 +0530 Subject: [PATCH 021/202] fix: unrelated transation date typo --- erpnext/controllers/buying_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index ece08d83f9..a470b47a45 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -365,7 +365,7 @@ class BuyingController(SubcontractingController): { "item_code": d.item_code, "warehouse": d.get("from_warehouse"), - "posting_date": self.get("posting_date") or self.get("transation_date"), + "posting_date": self.get("posting_date") or self.get("transaction_date"), "posting_time": posting_time, "qty": -1 * flt(d.get("stock_qty")), "serial_and_batch_bundle": d.get("serial_and_batch_bundle"), From a59c942cd487e0440625663034760eb89171e2ef Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 18:09:49 +0530 Subject: [PATCH 022/202] fix: reset dr_or_cr for every reference --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 2634972800..448224b3a7 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1054,9 +1054,9 @@ class PaymentEntry(AccountsController): item=self, ) - dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" - for d in self.get("references"): + # re-defining dr_or_cr for every reference in order to avoid the last value affecting calculation of reverse + dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" cost_center = self.cost_center if d.reference_doctype == "Sales Invoice" and not cost_center: cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center") @@ -1072,7 +1072,7 @@ class PaymentEntry(AccountsController): against_voucher_type = d.reference_doctype against_voucher = d.reference_name - reverse_dr_or_cr, standalone_note = 0, 0 + reverse_dr_or_cr = 0 if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]: is_return = frappe.db.get_value(d.reference_doctype, d.reference_name, "is_return") payable_party_types = get_party_types_from_account_type("Payable") @@ -1098,6 +1098,7 @@ class PaymentEntry(AccountsController): ) gl_entries.append(gle) + dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" if self.unallocated_amount: exchange_rate = self.get_exchange_rate() base_unallocated_amount = self.unallocated_amount * exchange_rate From 09f9764bbdec90d1b9f85ccc5a368bf85547bea1 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 18:11:00 +0530 Subject: [PATCH 023/202] test: payment against partial return invoices --- .../payment_entry/test_payment_entry.py | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 603f24a09c..5af37b6a5e 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -1290,6 +1290,9 @@ class TestPaymentEntry(FrappeTestCase): self.assertEqual(references[2].payment_term, "Tax Receivable") def test_receive_payment_from_payable_party_type(self): + """ + Checks GL entries generated while receiving payments from a Payable Party Type. + """ pe = create_payment_entry( party_type="Supplier", party="_Test Supplier", @@ -1301,8 +1304,55 @@ class TestPaymentEntry(FrappeTestCase): ) self.voucher_no = pe.name self.expected_gle = [ - {"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0}, {"account": "Creditors - _TC", "debit": 0.0, "credit": 1000.0}, + {"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0}, + ] + self.check_gl_entries() + + def test_payment_against_partial_return_invoice(self): + """ + Checks GL entries generated for partial return invoice payments. + """ + si = create_sales_invoice(qty=10, rate=10, customer="_Test Customer") + credit_note = create_sales_invoice( + qty=-4, rate=10, customer="_Test Customer", is_return=1, return_against=si.name + ) + pe = create_payment_entry( + party_type="Customer", + party="_Test Customer", + payment_type="Receive", + paid_from="Debtors - _TC", + paid_to="_Test Cash - _TC", + ) + pe.set( + "references", + [ + { + "reference_doctype": "Sales Invoice", + "reference_name": si.name, + "due_date": si.get("due_date"), + "total_amount": si.grand_total, + "outstanding_amount": si.outstanding_amount, + "allocated_amount": si.outstanding_amount, + }, + { + "reference_doctype": "Sales Invoice", + "reference_name": credit_note.name, + "due_date": credit_note.get("due_date"), + "total_amount": credit_note.grand_total, + "outstanding_amount": credit_note.outstanding_amount, + "allocated_amount": credit_note.outstanding_amount, + }, + ], + ) + pe.save() + pe.submit() + self.voucher_no = pe.name + self.expected_gle = [ + {"account": "Debtors - _TC", "debit": 40.0, "credit": 0.0}, + {"account": "Debtors - _TC", "debit": 0.0, "credit": 940.0}, + {"account": "Debtors - _TC", "debit": 0.0, "credit": 100.0}, + {"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0}, ] self.check_gl_entries() @@ -1316,7 +1366,7 @@ class TestPaymentEntry(FrappeTestCase): gle.credit, ) .where((gle.voucher_no == self.voucher_no) & (gle.is_cancelled == 0)) - .orderby(gle.account) + .orderby(gle.account, gle.debit, gle.credit, order=frappe.qb.desc) ).run(as_dict=True) for row in range(len(self.expected_gle)): for field in ["account", "debit", "credit"]: From 780b827adcba571b46ee73404f9a038c36dd0eb9 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 20:24:32 +0530 Subject: [PATCH 024/202] refactor: validate reposting settings for editables inv --- .../repost_accounting_ledger.py | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py index 69cfe9fcd7..1d72a46c12 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -10,12 +10,7 @@ from frappe.utils.data import comma_and class RepostAccountingLedger(Document): def __init__(self, *args, **kwargs): super(RepostAccountingLedger, self).__init__(*args, **kwargs) - self._allowed_types = [ - x.document_type - for x in frappe.db.get_all( - "Repost Allowed Types", filters={"allowed": True}, fields=["distinct(document_type)"] - ) - ] + self._allowed_types = get_allowed_types_from_settings() def validate(self): self.validate_vouchers() @@ -56,15 +51,7 @@ class RepostAccountingLedger(Document): def validate_vouchers(self): if self.vouchers: - # Validate voucher types - voucher_types = set([x.voucher_type for x in self.vouchers]) - if disallowed_types := voucher_types.difference(self._allowed_types): - frappe.throw( - _("{0} types are not allowed. Only {1} are.").format( - frappe.bold(comma_and(list(disallowed_types))), - frappe.bold(comma_and(list(self._allowed_types))), - ) - ) + validate_docs_for_voucher_types([x.voucher_type for x in self.vouchers]) def get_existing_ledger_entries(self): vouchers = [x.voucher_no for x in self.vouchers] @@ -168,6 +155,15 @@ def start_repost(account_repost_doc=str) -> None: frappe.db.commit() +def get_allowed_types_from_settings(): + return [ + x.document_type + for x in frappe.db.get_all( + "Repost Allowed Types", filters={"allowed": True}, fields=["distinct(document_type)"] + ) + ] + + def validate_docs_for_deferred_accounting(sales_docs, purchase_docs): docs_with_deferred_revenue = frappe.db.get_all( "Sales Invoice Item", @@ -191,6 +187,25 @@ def validate_docs_for_deferred_accounting(sales_docs, purchase_docs): ) +def validate_docs_for_voucher_types(doc_voucher_types): + allowed_types = get_allowed_types_from_settings() + # Validate voucher types + voucher_types = set(doc_voucher_types) + if disallowed_types := voucher_types.difference(allowed_types): + message = "are" if len(disallowed_types) > 1 else "is" + frappe.throw( + _("{0} {1} not allowed to be reposted. Modify {2} to enable reposting.").format( + frappe.bold(comma_and(list(disallowed_types))), + message, + frappe.bold( + frappe.utils.get_link_to_form( + "Repost Accounting Ledger Settings", "Repost Accounting Ledger Settings" + ) + ), + ) + ) + + @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def get_repost_allowed_types(doctype, txt, searchfield, start, page_len, filters): From ad5edbb1de95befa1b6f312dcb7df6d8c5a8ce6c Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 20:25:26 +0530 Subject: [PATCH 025/202] fix: do not set repost flag without validating voucher --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index e1f0f1932e..d7c2361b4d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -13,6 +13,7 @@ from erpnext.accounts.deferred_revenue import validate_service_stop_date from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import ( validate_docs_for_deferred_accounting, + validate_docs_for_voucher_types, ) from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( check_if_return_invoice_linked_with_payment_entry, @@ -491,6 +492,7 @@ class PurchaseInvoice(BuyingController): def validate_for_repost(self): self.validate_write_off_account() self.validate_expense_account() + validate_docs_for_voucher_types(["Purchase Invoice"]) validate_docs_for_deferred_accounting([], [self.name]) def on_submit(self): From 5fae2f6d57bac332263d8c73e3d090f485b5844d Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 20:27:09 +0530 Subject: [PATCH 026/202] fix: allow on submit for child table fields --- .../doctype/purchase_invoice_item/purchase_invoice_item.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 424e942990..6987a8faf0 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -497,6 +497,7 @@ "fieldtype": "Column Break" }, { + "allow_on_submit": 1, "fieldname": "project", "fieldtype": "Link", "label": "Project", @@ -504,6 +505,7 @@ "print_hide": 1 }, { + "allow_on_submit": 1, "default": ":Company", "depends_on": "eval:!doc.is_fixed_asset", "fieldname": "cost_center", @@ -915,7 +917,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-10-03 21:01:01.824892", + "modified": "2023-11-13 20:26:18.329983", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", From 894ae1fe0f8da1931f705d433c15b19410486186 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 13 Nov 2023 20:28:44 +0530 Subject: [PATCH 027/202] fix: check reposting settings before allowing editable si --- 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 fa95ccdc57..adb8286be7 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -17,6 +17,7 @@ from erpnext.accounts.doctype.loyalty_program.loyalty_program import ( ) from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import ( validate_docs_for_deferred_accounting, + validate_docs_for_voucher_types, ) from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import ( get_party_tax_withholding_details, @@ -172,6 +173,7 @@ class SalesInvoice(SellingController): self.validate_write_off_account() self.validate_account_for_change_amount() self.validate_income_account() + validate_docs_for_voucher_types(["Sales Invoice"]) validate_docs_for_deferred_accounting([self.name], []) def validate_fixed_asset(self): From c31ee8ea33afcc8128270f098c40cc0b0e3f1a49 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 14 Nov 2023 06:44:49 +0530 Subject: [PATCH 028/202] refactor: use 'boolean' parameter while fetching FY year --- erpnext/accounts/utils.py | 3 +++ erpnext/public/js/financial_statements.js | 10 ++++++++-- erpnext/public/js/utils.js | 5 +++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 31bc6fdef8..7d91309fcc 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -53,6 +53,9 @@ GL_REPOSTING_CHUNK = 100 def get_fiscal_year( date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False, boolean=False ): + if isinstance(boolean, str): + boolean = frappe.json.loads(boolean) + fiscal_years = get_fiscal_years( date, fiscal_year, label, verbose, company, as_dict=as_dict, boolean=boolean ) diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 907a775bfa..1b10d8ad3a 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -139,7 +139,6 @@ function get_filters() { "label": __("Start Year"), "fieldtype": "Link", "options": "Fiscal Year", - "default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()), "reqd": 1, "depends_on": "eval:doc.filter_based_on == 'Fiscal Year'" }, @@ -148,7 +147,6 @@ function get_filters() { "label": __("End Year"), "fieldtype": "Link", "options": "Fiscal Year", - "default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()), "reqd": 1, "depends_on": "eval:doc.filter_based_on == 'Fiscal Year'" }, @@ -197,5 +195,13 @@ function get_filters() { } ] + // Dynamically set 'default' values for fiscal year filters + let fy_filters = filters.filter(x=>{return ["from_fiscal_year", "to_fiscal_year"].includes(x.fieldname);}) + let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), false, true); + if (fiscal_year) { + let fy = erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), false, false); + fy_filters.forEach(x=>{x.default = fy;}) + } + return filters; } diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index d435711cf5..25fc754b9a 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -404,7 +404,7 @@ $.extend(erpnext.utils, { }); }, - get_fiscal_year: function(date, with_dates=false) { + get_fiscal_year: function(date, with_dates=false, boolean=false) { if(!date) { date = frappe.datetime.get_today(); } @@ -413,7 +413,8 @@ $.extend(erpnext.utils, { frappe.call({ method: "erpnext.accounts.utils.get_fiscal_year", args: { - date: date + date: date, + boolean: boolean }, async: false, callback: function(r) { From e769e750ec712872a8fd28c533d1f02444e351a9 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 14 Nov 2023 15:08:37 +0530 Subject: [PATCH 029/202] fix: Not able to save subcontracting receipt (#38085) --- .../serial_and_batch_bundle.py | 3 + .../subcontracting_receipt.py | 2 + .../test_subcontracting_receipt.py | 71 ++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index f2bbf2b211..0a4cae7b34 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1604,6 +1604,9 @@ def get_ledgers_from_serial_batch_bundle(**kwargs) -> List[frappe._dict]: ) for key, val in kwargs.items(): + if not val: + continue + if key in ["get_subcontracted_item"]: continue diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 7e06444e1e..8d705aa97d 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -148,6 +148,8 @@ class SubcontractingReceipt(SubcontractingController): if ( frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on") == "BOM" + and self.supplied_items + and not any(item.serial_and_batch_bundle for item in self.supplied_items) ): self.supplied_items = [] diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 1828f6960f..96babf2b32 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -6,7 +6,7 @@ import copy import frappe from frappe.tests.utils import FrappeTestCase -from frappe.utils import add_days, cint, cstr, flt, today +from frappe.utils import add_days, cint, cstr, flt, nowtime, today import erpnext from erpnext.accounts.doctype.account.test_account import get_inventory_account @@ -26,6 +26,10 @@ from erpnext.controllers.tests.test_subcontracting_controller import ( from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries +from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import ( + get_batch_from_bundle, + make_serial_batch_bundle, +) from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( create_stock_reconciliation, @@ -507,6 +511,71 @@ class TestSubcontractingReceipt(FrappeTestCase): self.assertNotEqual(scr.supplied_items[0].rate, prev_cost) self.assertEqual(scr.supplied_items[0].rate, sr.items[0].valuation_rate) + def test_subcontracting_receipt_for_batch_raw_materials_without_material_transfer(self): + set_backflush_based_on("BOM") + + fg_item = make_item(properties={"is_stock_item": 1, "is_sub_contracted_item": 1}).name + rm_item1 = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "BNGS-.####", + } + ).name + + bom = make_bom(item=fg_item, raw_materials=[rm_item1]) + + rm_batch_no = None + for row in bom.items: + se = make_stock_entry( + item_code=row.item_code, + qty=1, + target="_Test Warehouse 1 - _TC", + rate=300, + ) + + se.reload() + rm_batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 1", + "qty": 1, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 1, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + scr = make_subcontracting_receipt(sco.name) + scr.save() + scr.reload() + + bundle_doc = make_serial_batch_bundle( + { + "item_code": scr.supplied_items[0].rm_item_code, + "warehouse": "_Test Warehouse 1 - _TC", + "voucher_type": "Subcontracting Receipt", + "posting_date": today(), + "posting_time": nowtime(), + "qty": -1, + "batches": frappe._dict({rm_batch_no: 1}), + "type_of_transaction": "Outward", + "do_not_submit": True, + } + ) + + scr.supplied_items[0].serial_and_batch_bundle = bundle_doc.name + scr.submit() + scr.reload() + + batch_no = get_batch_from_bundle(scr.supplied_items[0].serial_and_batch_bundle) + self.assertEqual(batch_no, rm_batch_no) + self.assertEqual(scr.items[0].rm_cost_per_qty, 300) + self.assertEqual(scr.items[0].service_cost_per_qty, 100) + def test_subcontracting_receipt_raw_material_rate(self): # Step - 1: Set Backflush Based On as "BOM" set_backflush_based_on("BOM") From 3e77c0b5644c28ed9b4eef22b228fdc4a1283020 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 14 Nov 2023 19:27:41 +0530 Subject: [PATCH 030/202] fix: valuation rate for the subcontracting receipt supplied items with Serial and Batch Bundle (#38094) fix: valuation rate for the subcontracting receipt supplied items with batch --- .../controllers/subcontracting_controller.py | 13 +++ .../stock_ledger_entry.json | 10 +- erpnext/stock/serial_batch_bundle.py | 10 +- erpnext/stock/stock_ledger.py | 4 +- .../subcontracting_receipt.js | 10 ++ .../test_subcontracting_receipt.py | 91 +++++++++++++++++++ 6 files changed, 135 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index 5fa66b1a87..3d55a087bd 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -626,6 +626,18 @@ class SubcontractingController(StockController): (row.item_code, row.get(self.subcontract_data.order_field)) ] -= row.qty + def __set_rate_for_serial_and_batch_bundle(self): + if self.doctype != "Subcontracting Receipt": + return + + for row in self.get(self.raw_material_table): + if not row.get("serial_and_batch_bundle"): + continue + + row.rate = frappe.get_cached_value( + "Serial and Batch Bundle", row.serial_and_batch_bundle, "avg_rate" + ) + def __modify_serial_and_batch_bundle(self): if self.is_new(): return @@ -681,6 +693,7 @@ class SubcontractingController(StockController): self.__remove_changed_rows() self.__set_supplied_items() self.__modify_serial_and_batch_bundle() + self.__set_rate_for_serial_and_batch_bundle() def __validate_batch_no(self, row, key): if row.get("batch_no") and row.get("batch_no") not in self.__transferred_items.get(key).get( diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json index dcbd9b2d06..be379940ca 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json @@ -12,6 +12,7 @@ "posting_date", "posting_time", "is_adjustment_entry", + "auto_created_serial_and_batch_bundle", "column_break_6", "voucher_type", "voucher_no", @@ -340,6 +341,13 @@ "fieldname": "is_adjustment_entry", "fieldtype": "Check", "label": "Is Adjustment Entry" + }, + { + "default": "0", + "depends_on": "serial_and_batch_bundle", + "fieldname": "auto_created_serial_and_batch_bundle", + "fieldtype": "Check", + "label": "Auto Created Serial and Batch Bundle" } ], "hide_toolbar": 1, @@ -348,7 +356,7 @@ "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2023-10-23 18:07:42.063615", + "modified": "2023-11-14 16:47:39.791967", "modified_by": "Administrator", "module": "Stock", "name": "Stock Ledger Entry", diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 5998274bb7..da98455b5c 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -129,7 +129,9 @@ class SerialBatchBundle: frappe.throw(_(error_msg)) def set_serial_and_batch_bundle(self, sn_doc): - self.sle.db_set("serial_and_batch_bundle", sn_doc.name) + self.sle.db_set( + {"serial_and_batch_bundle": sn_doc.name, "auto_created_serial_and_batch_bundle": 1} + ) if sn_doc.is_rejected: frappe.db.set_value( @@ -143,6 +145,12 @@ class SerialBatchBundle: @property def child_doctype(self): child_doctype = self.sle.voucher_type + " Item" + + if ( + self.sle.voucher_type == "Subcontracting Receipt" and self.sle.dependant_sle_voucher_detail_no + ): + child_doctype = "Subcontracting Receipt Supplied Item" + if self.sle.voucher_type == "Stock Entry": child_doctype = "Stock Entry Detail" diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 63908945c3..9142a27f4c 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -766,7 +766,9 @@ class update_entries_after(object): sle.doctype = "Stock Ledger Entry" frappe.get_doc(sle).db_update() - if not self.args.get("sle_id"): + if not self.args.get("sle_id") or ( + sle.serial_and_batch_bundle and sle.auto_created_serial_and_batch_bundle + ): self.update_outgoing_rate_on_transaction(sle) def reset_actual_qty_for_stock_reco(self, sle): diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 19a1c939c3..36001eb78f 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -13,6 +13,16 @@ frappe.ui.form.on('Subcontracting Receipt', { frm.trigger('set_queries'); }, + on_submit(frm) { + frm.events.refresh_serial_batch_bundle_field(frm); + }, + + refresh_serial_batch_bundle_field(frm) { + frappe.route_hooks.after_submit = (frm_obj) => { + frm_obj.reload_doc(); + } + }, + refresh: (frm) => { if (frm.doc.docstatus > 0) { frm.add_custom_button(__('Stock Ledger'), () => { diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 96babf2b32..6191a8ca94 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -576,6 +576,97 @@ class TestSubcontractingReceipt(FrappeTestCase): self.assertEqual(scr.items[0].rm_cost_per_qty, 300) self.assertEqual(scr.items[0].service_cost_per_qty, 100) + def test_subcontracting_receipt_valuation_with_auto_created_serial_batch_bundle(self): + set_backflush_based_on("BOM") + + fg_item = make_item(properties={"is_stock_item": 1, "is_sub_contracted_item": 1}).name + rm_item1 = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "BNGS-.####", + } + ).name + + rm_item2 = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "has_serial_no": 1, + "create_new_batch": 1, + "batch_number_series": "BNGS-.####", + "serial_no_series": "BNSS-.####", + } + ).name + + rm_item3 = make_item( + properties={ + "is_stock_item": 1, + "has_serial_no": 1, + "serial_no_series": "BSSSS-.####", + } + ).name + + bom = make_bom(item=fg_item, raw_materials=[rm_item1, rm_item2, rm_item3]) + + rm_batch_no = None + for row in bom.items: + make_stock_entry( + item_code=row.item_code, + qty=1, + target="_Test Warehouse 1 - _TC", + rate=300, + ) + + make_stock_entry( + item_code=row.item_code, + qty=1, + target="_Test Warehouse 1 - _TC", + rate=400, + ) + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 1", + "qty": 1, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 1, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 1 + ) + scr = make_subcontracting_receipt(sco.name) + scr.save() + for row in scr.supplied_items: + self.assertNotEqual(row.rate, 300.00) + self.assertFalse(row.serial_and_batch_bundle) + + scr.submit() + scr.reload() + + for row in scr.supplied_items: + self.assertEqual(row.rate, 300.00) + self.assertTrue(row.serial_and_batch_bundle) + auto_created_serial_batch = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_no": scr.name, "voucher_detail_no": row.name}, + "auto_created_serial_and_batch_bundle", + ) + + self.assertTrue(auto_created_serial_batch) + + self.assertEqual(scr.items[0].rm_cost_per_qty, 900) + self.assertEqual(scr.items[0].service_cost_per_qty, 100) + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0 + ) + def test_subcontracting_receipt_raw_material_rate(self): # Step - 1: Set Backflush Based On as "BOM" set_backflush_based_on("BOM") From e93a19ffb5d45a3bf0136ca3fc24a828b008aeee Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Tue, 14 Nov 2023 19:38:15 +0530 Subject: [PATCH 031/202] chore: refetch item images on transaction save (#38095) chore: re fetch item images on transaction save --- .../doctype/pos_invoice_item/pos_invoice_item.json | 3 ++- .../purchase_invoice_item/purchase_invoice_item.json | 3 ++- .../doctype/sales_invoice_item/sales_invoice_item.json | 5 +++-- .../purchase_order_item/purchase_order_item.json | 3 ++- .../request_for_quotation_item.json | 7 +++++-- .../supplier_quotation_item.json | 7 +++++-- .../crm/doctype/opportunity_item/opportunity_item.json | 4 +++- .../doctype/bom_explosion_item/bom_explosion_item.json | 3 ++- erpnext/manufacturing/doctype/bom_item/bom_item.json | 3 ++- .../selling/doctype/quotation_item/quotation_item.json | 5 +++-- .../doctype/sales_order_item/sales_order_item.json | 10 ++-------- .../doctype/delivery_note_item/delivery_note_item.json | 3 ++- .../material_request_item/material_request_item.json | 3 ++- .../purchase_receipt_item/purchase_receipt_item.json | 3 ++- .../subcontracting_order_item.json | 3 ++- .../subcontracting_receipt_item.json | 3 ++- 16 files changed, 41 insertions(+), 27 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json index cb0ed3d6aa..5a281aaa4f 100644 --- a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json +++ b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json @@ -186,6 +186,7 @@ "label": "Image" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -833,7 +834,7 @@ ], "istable": 1, "links": [], - "modified": "2023-03-12 13:36:40.160468", + "modified": "2023-11-14 18:33:22.585715", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice Item", diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 424e942990..bcedb7c943 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -158,6 +158,7 @@ "width": "300px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -915,7 +916,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-10-03 21:01:01.824892", + "modified": "2023-11-14 18:33:48.547297", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index 5d2764b669..a403b14c54 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -167,6 +167,7 @@ "print_hide": 1 }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -901,7 +902,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-07-26 12:53:22.404057", + "modified": "2023-11-14 18:34:10.479329", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", @@ -911,4 +912,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} +} \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 2b6ffb752f..2d706f41e5 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -189,6 +189,7 @@ "fieldtype": "Column Break" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -916,7 +917,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-06 11:00:53.596417", + "modified": "2023-11-14 18:34:27.267382", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", diff --git a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json index 82fcfa2713..6cdd2bac0d 100644 --- a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json +++ b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json @@ -87,6 +87,7 @@ "width": "300px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -260,13 +261,15 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-09-24 17:26:46.276934", + "modified": "2023-11-14 18:34:48.327224", "modified_by": "Administrator", "module": "Buying", "name": "Request for Quotation Item", + "naming_rule": "Random", "owner": "Administrator", "permissions": [], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 -} +} \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json index 8d491fbc84..4bbcacfef3 100644 --- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json @@ -133,6 +133,7 @@ "fieldtype": "Column Break" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -559,13 +560,15 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-10-19 12:36:26.913211", + "modified": "2023-11-14 18:35:03.435817", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation Item", + "naming_rule": "Random", "owner": "Administrator", "permissions": [], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 -} +} \ No newline at end of file diff --git a/erpnext/crm/doctype/opportunity_item/opportunity_item.json b/erpnext/crm/doctype/opportunity_item/opportunity_item.json index 1b4973c1b2..732f80d01c 100644 --- a/erpnext/crm/doctype/opportunity_item/opportunity_item.json +++ b/erpnext/crm/doctype/opportunity_item/opportunity_item.json @@ -103,6 +103,7 @@ "fieldtype": "Column Break" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -165,7 +166,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2021-07-30 16:39:09.775720", + "modified": "2023-11-14 18:35:30.887278", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity Item", @@ -173,5 +174,6 @@ "permissions": [], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json index 9b1db63494..c75ac32cd1 100644 --- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json +++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json @@ -85,6 +85,7 @@ "fieldtype": "Column Break" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -169,7 +170,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2022-05-27 13:42:23.305455", + "modified": "2023-11-14 18:35:40.856895", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Explosion Item", diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index c5266119dc..cb58af1f29 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -111,6 +111,7 @@ "fieldtype": "Column Break" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -289,7 +290,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2022-07-28 10:20:51.559010", + "modified": "2023-11-14 18:35:51.378513", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Item", diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index 5016f1f1fd..0e25313f76 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -135,6 +135,7 @@ "width": "300px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -666,7 +667,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-09-26 13:42:11.410294", + "modified": "2023-11-14 18:24:24.619832", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", @@ -676,4 +677,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} +} \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index f82047f511..b4f73003ae 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -68,7 +68,6 @@ "total_weight", "column_break_21", "weight_uom", - "accounting_dimensions_section", "warehouse_and_reference", "warehouse", "target_warehouse", @@ -177,6 +176,7 @@ "print_hide": 1 }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -890,18 +890,12 @@ "label": "Production Plan Qty", "no_copy": 1, "read_only": 1 - }, - { - "collapsible": 1, - "fieldname": "accounting_dimensions_section", - "fieldtype": "Section Break", - "label": "Accounting Dimensions" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-10-17 18:18:26.475259", + "modified": "2023-11-14 18:37:12.787893", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json index 6148950462..a44b9ac44b 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -168,6 +168,7 @@ "width": "300px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -893,7 +894,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-10-16 16:18:18.013379", + "modified": "2023-11-14 18:37:38.638144", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json index 9912be145f..5dc07c99f6 100644 --- a/erpnext/stock/doctype/material_request_item/material_request_item.json +++ b/erpnext/stock/doctype/material_request_item/material_request_item.json @@ -110,6 +110,7 @@ "width": "250px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach Image", "label": "Image", @@ -478,7 +479,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-10-27 15:53:41.444236", + "modified": "2023-11-14 18:37:59.599115", "modified_by": "Administrator", "module": "Stock", "name": "Material Request Item", diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 718f007577..ce2e5d7f84 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -192,6 +192,7 @@ "width": "300px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -1090,7 +1091,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-10-30 17:32:24.560337", + "modified": "2023-11-14 18:38:15.251994", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json index d77e77440e..46c229bfd3 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -112,6 +112,7 @@ "fieldtype": "Column Break" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -337,7 +338,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-01-20 23:25:45.363281", + "modified": "2023-11-14 18:38:37.640677", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json index 38432beb44..26a29dd811 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json @@ -109,6 +109,7 @@ "width": "300px" }, { + "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -521,7 +522,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-09-03 17:04:21.214316", + "modified": "2023-11-14 18:38:26.459669", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Receipt Item", From 908b21f7fd8d0c62ffd51eb2ca5238225d0f52ad Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 15 Nov 2023 12:34:38 +0530 Subject: [PATCH 032/202] fix: duplicate field in `Closing Stock Balance` (#38105) --- .../closing_stock_balance/closing_stock_balance.json | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json index 225da6d15e..0c4757ffad 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json @@ -103,15 +103,6 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "amended_from", - "fieldtype": "Link", - "label": "Amended From", - "no_copy": 1, - "options": "Closing Stock Balance", - "print_hide": 1, - "read_only": 1 - }, { "fieldname": "include_uom", "fieldtype": "Link", @@ -145,4 +136,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} From 2499675ad121ab370f672e6f9ffdcda3c8c76b8e Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 15 Nov 2023 13:32:23 +0530 Subject: [PATCH 033/202] fix: test total unallocated amount in payment --- erpnext/accounts/doctype/payment_entry/test_payment_entry.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 5af37b6a5e..f4b0c55313 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -1347,6 +1347,8 @@ class TestPaymentEntry(FrappeTestCase): ) pe.save() pe.submit() + self.assertEqual(pe.total_allocated_amount, 60) + self.assertEqual(pe.unallocated_amount, 940) self.voucher_no = pe.name self.expected_gle = [ {"account": "Debtors - _TC", "debit": 40.0, "credit": 0.0}, From 6e0362dee85811267edff53f23a24b48ebd91c11 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Wed, 15 Nov 2023 17:58:37 +0530 Subject: [PATCH 034/202] chore: change read only condition of asset quantity field (#38111) chore: change read only condition of asset quantity --- erpnext/assets/doctype/asset/asset.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 40f51ab570..d6b9c461cb 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -481,11 +481,10 @@ "read_only": 1 }, { - "depends_on": "eval.doc.asset_quantity", "fieldname": "asset_quantity", "fieldtype": "Int", "label": "Asset Quantity", - "read_only": 1 + "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset" }, { "fieldname": "depr_entry_posting_status", @@ -572,7 +571,7 @@ "link_fieldname": "target_asset" } ], - "modified": "2023-10-27 17:03:46.629617", + "modified": "2023-11-15 17:40:17.315203", "modified_by": "Administrator", "module": "Assets", "name": "Asset", From 426c245032bccc93b79d0505f853bc25ae51f37e Mon Sep 17 00:00:00 2001 From: David Arnold Date: Tue, 14 Nov 2023 11:13:05 +0100 Subject: [PATCH 035/202] fix(dn): regression from bulk transaction fix --- erpnext/selling/doctype/sales_order/sales_order.py | 7 +++++-- erpnext/utilities/bulk_transaction.py | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index e4f1a28316..a97198aa78 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -767,8 +767,11 @@ def make_delivery_note(source_name, target_doc=None, kwargs=None): if target.company_address: target.update(get_fetch_values("Delivery Note", "company_address", target.company_address)) - # set target items names to ensure proper linking with packed_items - target.set_new_name() + # if invoked in bulk creation, validations are ignored and thus this method is nerver invoked + if frappe.flags.bulk_transaction: + # set target items names to ensure proper linking with packed_items + target.set_new_name() + make_packing_list(target) def condition(doc): diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index fcee265644..56f3b41c2e 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -98,6 +98,7 @@ def task(doc_name, from_doctype, to_doctype): }, "Purchase Receipt": {"Purchase Invoice": purchase_receipt.make_purchase_invoice}, } + frappe.flags.bulk_transaction = True if to_doctype in ["Payment Entry"]: obj = mapper[from_doctype][to_doctype](from_doctype, doc_name) else: @@ -106,6 +107,7 @@ def task(doc_name, from_doctype, to_doctype): obj.flags.ignore_validate = True obj.set_title_field() obj.insert(ignore_mandatory=True) + del frappe.flags.bulk_transaction def check_logger_doc_exists(log_date): From da80e4dbce07707d57e3739b7bb2138adf199905 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 16 Nov 2023 13:05:49 +0530 Subject: [PATCH 036/202] feat: add `Supplier Delivery Note` field in SCR --- .../subcontracting_receipt/subcontracting_receipt.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json index 8be1c1ba97..383a83b3fc 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json @@ -11,6 +11,7 @@ "naming_series", "supplier", "supplier_name", + "supplier_delivery_note", "column_break1", "company", "posting_date", @@ -634,12 +635,17 @@ "fieldtype": "Button", "label": "Get Scrap Items", "options": "get_scrap_items" + }, + { + "fieldname": "supplier_delivery_note", + "fieldtype": "Data", + "label": "Supplier Delivery Note" } ], "in_create": 1, "is_submittable": 1, "links": [], - "modified": "2023-08-26 10:52:04.050829", + "modified": "2023-11-16 13:04:00.710534", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Receipt", From 2df767f596417143ae3b855b2252585bf2bc96f9 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 16 Nov 2023 16:01:35 +0530 Subject: [PATCH 037/202] fix: bom creator not able to amend / duplicate (#38128) fix: bom creator not able to amend --- .../doctype/bom_creator/bom_creator.js | 2 +- .../doctype/bom_creator/bom_creator.py | 14 +++++++++++--- .../doctype/bom_creator_item/bom_creator_item.json | 3 +-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.js b/erpnext/manufacturing/doctype/bom_creator/bom_creator.js index 0cf2b51df2..243e52df5b 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.js +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.js @@ -15,7 +15,7 @@ frappe.ui.form.on("BOM Creator", { || frappe.bom_configurator.bom_configurator !== frm.doc.name)) { frm.trigger("build_tree"); } - } else { + } else if (!frm.doc.items?.length ) { let $parent = $(frm.fields_dict["bom_creator"].wrapper); $parent.empty(); frm.trigger("make_new_entry"); diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py index 058caa3686..49041a0929 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py @@ -6,7 +6,7 @@ from collections import OrderedDict import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import flt +from frappe.utils import cint, flt from erpnext.manufacturing.doctype.bom.bom import get_bom_item_rate @@ -91,11 +91,19 @@ class BOMCreator(Document): parent_reference = {row.idx: row.name for row in self.items} for row in self.items: - if row.fg_reference_id: + ref_id = "" + + if row.parent_row_no: + ref_id = parent_reference.get(cint(row.parent_row_no)) + + # Check whether the reference id of the FG Item has correct or not + if row.fg_reference_id and row.fg_reference_id == ref_id: continue if row.parent_row_no: - row.fg_reference_id = parent_reference.get(row.parent_row_no) + row.fg_reference_id = ref_id + elif row.fg_item == self.item_code: + row.fg_reference_id = self.name @frappe.whitelist() def add_boms(self): diff --git a/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json b/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json index fdb5d3ad33..56acd8a1a6 100644 --- a/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json +++ b/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json @@ -215,7 +215,6 @@ "fieldname": "parent_row_no", "fieldtype": "Data", "label": "Parent Row No", - "no_copy": 1, "print_hide": 1 }, { @@ -231,7 +230,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-08-07 11:52:30.492233", + "modified": "2023-11-16 13:34:06.321061", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Creator Item", From 134201794ace2863c02458b3e1797da816802d06 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 16 Nov 2023 10:04:50 +0530 Subject: [PATCH 038/202] fix: add revaluation journal filter in Payable report --- erpnext/accounts/report/accounts_payable/accounts_payable.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index 10362dba3d..b608ebc395 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -149,6 +149,11 @@ frappe.query_reports["Accounts Payable"] = { "label": __("In Party Currency"), "fieldtype": "Check", }, + { + "fieldname": "for_revaluation_journals", + "label": __("Revaluation Journals"), + "fieldtype": "Check", + }, { "fieldname": "ignore_accounts", "label": __("Group by Voucher"), From b27af6b5c85a99d22060ac85b9ba37893317bfbb Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 17 Nov 2023 12:36:57 +0530 Subject: [PATCH 039/202] fix: show party instead of party name where naming series not set --- .../tax_withholding_details/tax_withholding_details.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 06c9e44b45..f6c7bd3db7 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -184,6 +184,16 @@ def get_columns(filters): "width": 180, } ) + else: + columns.append( + { + "label": _(filters.get("party_type")), + "fieldname": "party", + "fieldtype": "Dynamic Link", + "options": "party_type", + "width": 180, + } + ) columns.extend( [ From 089da459f73791b86d33cf066e6879e77af200b5 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 17 Nov 2023 12:37:14 +0530 Subject: [PATCH 040/202] feat: Add accounting dimensions to Supplier Quotation --- .../supplier_quotation.json | 27 ++++++++++++++++++- .../supplier_quotation_item.json | 15 +++++++++-- erpnext/hooks.py | 2 ++ erpnext/patches.txt | 1 + ...unting_dimensions_in_supplier_quotation.py | 8 ++++++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 erpnext/patches/v14_0/create_accounting_dimensions_in_supplier_quotation.py diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index ad1aa2b108..18912610ce 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -20,6 +20,10 @@ "valid_till", "quotation_number", "amended_from", + "accounting_dimensions_section", + "cost_center", + "dimension_col_break", + "project", "currency_and_price_list", "currency", "conversion_rate", @@ -896,6 +900,27 @@ "fieldtype": "Small Text", "label": "Billing Address Details", "read_only": 1 + }, + { + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center" + }, + { + "fieldname": "project", + "fieldtype": "Link", + "label": "Project", + "options": "Project" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" + }, + { + "fieldname": "accounting_dimensions_section", + "fieldtype": "Section Break", + "label": "Accounting Dimensions" } ], "icon": "fa fa-shopping-cart", @@ -903,7 +928,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2023-11-03 13:21:40.172508", + "modified": "2023-11-17 12:34:30.083077", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json index 4bbcacfef3..a6229b5950 100644 --- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json @@ -68,6 +68,8 @@ "column_break_15", "manufacturer_part_no", "ad_sec_break", + "cost_center", + "dimension_col_break", "project", "section_break_44", "page_break" @@ -133,7 +135,6 @@ "fieldtype": "Column Break" }, { - "fetch_from": "item_code.image", "fieldname": "image", "fieldtype": "Attach", "hidden": 1, @@ -554,13 +555,23 @@ "fieldname": "expected_delivery_date", "fieldtype": "Date", "label": "Expected Delivery Date" + }, + { + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center" + }, + { + "fieldname": "dimension_col_break", + "fieldtype": "Column Break" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:35:03.435817", + "modified": "2023-11-17 12:25:26.235367", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation Item", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 5483a10b57..55ffaca419 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -539,6 +539,8 @@ accounting_dimension_doctypes = [ "Subcontracting Receipt", "Subcontracting Receipt Item", "Account Closing Balance", + "Supplier Quotation", + "Supplier Quotation Item", ] get_matching_queries = ( diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0aeadce6c8..6c10dd9bbb 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -350,5 +350,6 @@ erpnext.patches.v14_0.add_default_for_repost_settings erpnext.patches.v15_0.rename_daily_depreciation_to_depreciation_amount_based_on_num_days_in_month erpnext.patches.v15_0.rename_depreciation_amount_based_on_num_days_in_month_to_daily_prorata_based erpnext.patches.v15_0.set_reserved_stock_in_bin +erpnext.patches.v14_0.create_accounting_dimensions_in_supplier_quotation # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger diff --git a/erpnext/patches/v14_0/create_accounting_dimensions_in_supplier_quotation.py b/erpnext/patches/v14_0/create_accounting_dimensions_in_supplier_quotation.py new file mode 100644 index 0000000000..6966db1fd7 --- /dev/null +++ b/erpnext/patches/v14_0/create_accounting_dimensions_in_supplier_quotation.py @@ -0,0 +1,8 @@ +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + create_accounting_dimensions_for_doctype, +) + + +def execute(): + create_accounting_dimensions_for_doctype(doctype="Supplier Quotation") + create_accounting_dimensions_for_doctype(doctype="Supplier Quotation Item") From 7e43d7b1312fd665bdcde7db7c67d192f746e60a Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Fri, 17 Nov 2023 12:38:08 +0530 Subject: [PATCH 041/202] fix: allow regional gl in payment entry for gl preview (#38136) --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 448224b3a7..ef304bc110 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1022,6 +1022,7 @@ class PaymentEntry(AccountsController): self.add_bank_gl_entries(gl_entries) self.add_deductions_gl_entries(gl_entries) self.add_tax_gl_entries(gl_entries) + add_regional_gl_entries(gl_entries, self) return gl_entries def make_gl_entries(self, cancel=0, adv_adj=0): @@ -2621,3 +2622,8 @@ def make_payment_order(source_name, target_doc=None): ) return doclist + + +@erpnext.allow_regional +def add_regional_gl_entries(gl_entries, doc): + return From 7842c9fba8b521b9ba7f65281c4f2384f62b06e1 Mon Sep 17 00:00:00 2001 From: kunhi Date: Fri, 17 Nov 2023 11:22:08 +0400 Subject: [PATCH 042/202] fix: issue occured when creating supplier with contact details --- erpnext/selling/doctype/customer/customer.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 459fc9fcff..d4702e8fb9 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -629,8 +629,12 @@ def make_contact(args, is_primary_contact=1): "is_primary_contact": is_primary_contact, "links": [{"link_doctype": args.get("doctype"), "link_name": args.get("name")}], } - if args.customer_type == "Individual": - first, middle, last = parse_full_name(args.get("customer_name")) + + party_type = args.customer_type if args.doctype == "Customer" else args.supplier_type + party_name_key = "customer_name" if args.doctype == "Customer" else "supplier_name" + + if party_type == "Individual": + first, middle, last = parse_full_name(args.get(party_name_key)) values.update( { "first_name": first, @@ -641,9 +645,10 @@ def make_contact(args, is_primary_contact=1): else: values.update( { - "company_name": args.get("customer_name"), + "company_name": args.get(party_name_key), } ) + contact = frappe.get_doc(values) if args.get("email_id"): From 545ef3c23491e895bf288ddf7666ea80251b41e7 Mon Sep 17 00:00:00 2001 From: Kunhi Date: Fri, 17 Nov 2023 11:43:36 +0400 Subject: [PATCH 043/202] fix: Suppier name was not taken when creating address from supplier --- erpnext/selling/doctype/customer/customer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index d4702e8fb9..1db07972bb 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -677,10 +677,12 @@ def make_address(args, is_primary_address=1, is_shipping_address=1): title=_("Missing Values Required"), ) + party_name_key = "customer_name" if args.doctype == "Customer" else "supplier_name" + address = frappe.get_doc( { "doctype": "Address", - "address_title": args.get("customer_name"), + "address_title": args.get(party_name_key), "address_line1": args.get("address_line1"), "address_line2": args.get("address_line2"), "city": args.get("city"), From 20c6e9fca29d80016cefb83deee4e44ac9bc1d47 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 17 Nov 2023 18:08:55 +0530 Subject: [PATCH 044/202] fix(Timesheet): reset billing hours equal to hours if they exceed actual hours (#38134) --- erpnext/projects/doctype/timesheet/timesheet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 11156f4b50..8e464b5c6b 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -69,7 +69,7 @@ class Timesheet(Document): def update_billing_hours(self, args): if args.is_billable: - if flt(args.billing_hours) == 0.0: + if flt(args.billing_hours) == 0.0 or flt(args.billing_hours) > flt(args.hours): args.billing_hours = args.hours else: args.billing_hours = 0 From 3a51a3f37ecd70c13cee558a0b882d06e812a21c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 17 Nov 2023 17:34:21 +0530 Subject: [PATCH 045/202] refactor: convert payment reconciliation tool to virtual doctype --- .../payment_reconciliation/payment_reconciliation.json | 6 +++--- .../payment_reconciliation_allocation.json | 3 ++- .../payment_reconciliation_invoice.json | 3 ++- .../payment_reconciliation_payment.json | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json index b88791d3f9..ccb9e648cb 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json @@ -212,9 +212,10 @@ ], "hide_toolbar": 1, "icon": "icon-resize-horizontal", + "is_virtual": 1, "issingle": 1, "links": [], - "modified": "2023-08-15 05:35:50.109290", + "modified": "2023-11-17 17:33:55.701726", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation", @@ -239,6 +240,5 @@ ], "sort_field": "modified", "sort_order": "DESC", - "states": [], - "track_changes": 1 + "states": [] } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json index 5b8556e7c8..491c67818d 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json @@ -159,9 +159,10 @@ "label": "Difference Posting Date" } ], + "is_virtual": 1, "istable": 1, "links": [], - "modified": "2023-10-23 10:44:56.066303", + "modified": "2023-11-17 17:33:38.612615", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Allocation", diff --git a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json index c4dbd7e844..7c9d49e773 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json +++ b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json @@ -71,9 +71,10 @@ "label": "Exchange Rate" } ], + "is_virtual": 1, "istable": 1, "links": [], - "modified": "2022-11-08 18:18:02.502149", + "modified": "2023-11-17 17:33:45.455166", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Invoice", diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json index 17f3900880..d199236ae9 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json @@ -107,9 +107,10 @@ "options": "Cost Center" } ], + "is_virtual": 1, "istable": 1, "links": [], - "modified": "2023-09-03 07:43:29.965353", + "modified": "2023-11-17 17:33:34.818530", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Payment", From 9c7b19e0b7732189c9db12e2c67b12a67fe562b3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 18 Nov 2023 07:48:15 +0530 Subject: [PATCH 046/202] refactor: virtual doctype methods --- .../payment_reconciliation.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 43167be15a..6673e8de28 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -29,6 +29,58 @@ class PaymentReconciliation(Document): self.accounting_dimension_filter_conditions = [] self.ple_posting_date_filter = [] + def load_from_db(self): + # 'modified' attribute is required for `run_doc_method` to work properly. + doc_dict = frappe._dict( + { + "modified": None, + "company": None, + "party": None, + "party_type": None, + "receivable_payable_account": None, + "default_advance_account": None, + "from_invoice_date": None, + "to_invoice_date": None, + "invoice_limit": 50, + "from_payment_date": None, + "to_payment_date": None, + "payment_limit": 50, + "minimum_invoice_amount": None, + "minimum_payment_amount": None, + "maximum_invoice_amount": None, + "maximum_payment_amount": None, + "bank_cash_account": None, + "cost_center": None, + "payment_name": None, + "invoice_name": None, + } + ) + super(Document, self).__init__(doc_dict) + + def save(self): + return + + @staticmethod + def get_list(args): + pass + + @staticmethod + def get_count(args): + pass + + @staticmethod + def get_stats(args): + pass + + def db_insert(self, *args, **kwargs): + pass + + def db_update(self, *args, **kwargs): + pass + + def delete(self): + pass + @frappe.whitelist() def get_unreconciled_entries(self): self.get_nonreconciled_payment_entries() From b5dd0c8630c59cc38011039e7c7a21976b53ebd8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 18 Nov 2023 08:07:36 +0530 Subject: [PATCH 047/202] chore: remove reconciliation defaults from patch --- erpnext/patches.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 0aeadce6c8..2935a16d8e 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -344,8 +344,6 @@ erpnext.patches.v14_0.create_accounting_dimensions_in_sales_order_item erpnext.patches.v15_0.update_sre_from_voucher_details erpnext.patches.v14_0.rename_over_order_allowance_field erpnext.patches.v14_0.migrate_delivery_stop_lock_field -execute:frappe.db.set_single_value("Payment Reconciliation", "invoice_limit", 50) -execute:frappe.db.set_single_value("Payment Reconciliation", "payment_limit", 50) erpnext.patches.v14_0.add_default_for_repost_settings erpnext.patches.v15_0.rename_daily_depreciation_to_depreciation_amount_based_on_num_days_in_month erpnext.patches.v15_0.rename_depreciation_amount_based_on_num_days_in_month_to_daily_prorata_based From f31002636bf21a3599ee5a7372db4d0cb3dbfad9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 18 Nov 2023 08:10:09 +0530 Subject: [PATCH 048/202] chore: clear singles table and reconciliation related tables --- erpnext/patches.txt | 1 + .../clear_reconciliation_values_from_singles.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 erpnext/patches/v14_0/clear_reconciliation_values_from_singles.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 2935a16d8e..1e988c5a00 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -345,6 +345,7 @@ erpnext.patches.v15_0.update_sre_from_voucher_details erpnext.patches.v14_0.rename_over_order_allowance_field erpnext.patches.v14_0.migrate_delivery_stop_lock_field erpnext.patches.v14_0.add_default_for_repost_settings +erpnext.patches.v14_0.clear_reconciliation_values_from_singles erpnext.patches.v15_0.rename_daily_depreciation_to_depreciation_amount_based_on_num_days_in_month erpnext.patches.v15_0.rename_depreciation_amount_based_on_num_days_in_month_to_daily_prorata_based erpnext.patches.v15_0.set_reserved_stock_in_bin diff --git a/erpnext/patches/v14_0/clear_reconciliation_values_from_singles.py b/erpnext/patches/v14_0/clear_reconciliation_values_from_singles.py new file mode 100644 index 0000000000..c1f5b60a40 --- /dev/null +++ b/erpnext/patches/v14_0/clear_reconciliation_values_from_singles.py @@ -0,0 +1,17 @@ +from frappe import qb + + +def execute(): + """ + Clear `tabSingles` and Payment Reconciliation tables of values + """ + singles = qb.DocType("Singles") + qb.from_(singles).delete().where(singles.doctype == "Payment Reconciliation").run() + doctypes = [ + "Payment Reconciliation Invoice", + "Payment Reconciliation Payment", + "Payment Reconciliation Allocation", + ] + for x in doctypes: + dt = qb.DocType(x) + qb.from_(dt).delete().run() From 434c2a1815f27c59de5cd94528bc371593bdd402 Mon Sep 17 00:00:00 2001 From: PatrickDenis-stack <77415730+PatrickDenis-stack@users.noreply.github.com> Date: Sat, 18 Nov 2023 11:16:06 +0100 Subject: [PATCH 049/202] fix: attributes were mandatory for manufacturers --- erpnext/stock/doctype/item/item.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index c13d3ebe0f..6e93f5624f 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -504,7 +504,7 @@ "fieldtype": "Table", "hidden": 1, "label": "Variant Attributes", - "mandatory_depends_on": "has_variants", + "mandatory_depends_on": "eval:(doc.has_variants || doc.variant_of) && doc.variant_based_on==='Item Attribute'", "options": "Item Variant Attribute" }, { From 45299fe4b3e23774920d7c35f7fb66e786cf5aa5 Mon Sep 17 00:00:00 2001 From: Vishakh Desai Date: Sat, 18 Nov 2023 17:10:01 +0530 Subject: [PATCH 050/202] fix: pass check permission in render_address --- erpnext/accounts/party.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 371474e0a6..5c18e506f5 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -236,7 +236,9 @@ def set_address_details( if shipping_address: party_details.update( shipping_address=shipping_address, - shipping_address_display=render_address(shipping_address), + shipping_address_display=render_address( + shipping_address, check_permissions=not ignore_permissions + ), **get_fetch_values(doctype, "shipping_address", shipping_address) ) From 3a487bd33af1972d9ee8b7bb2f6277775c8e018e Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Sat, 18 Nov 2023 13:32:04 +0000 Subject: [PATCH 051/202] fix: wrong round off and rounded total --- erpnext/controllers/taxes_and_totals.py | 1 + erpnext/public/js/controllers/taxes_and_totals.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 96284d612f..f9f68a119b 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -54,6 +54,7 @@ class calculate_taxes_and_totals(object): 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.doc.rounding_adjustment = self.doc.base_rounding_adjustment = 0.0 self.set_rounded_total() self.calculate_shipping_charges() diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 6b613ce9ec..d24c4e6075 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -43,6 +43,9 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { if (this.frm.doc.apply_discount_on == "Grand Total" && this.frm.doc.is_cash_or_non_trade_discount) { this.frm.doc.grand_total -= this.frm.doc.discount_amount; this.frm.doc.base_grand_total -= this.frm.doc.base_discount_amount; + this.frm.doc.rounding_adjustment = 0; + this.frm.doc.base_rounding_adjustment = 0; + this.set_rounded_total(); } await this.calculate_shipping_charges(); From 3d1e3a9cded735c420cb6c0ceb17c62034983076 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Sat, 18 Nov 2023 14:36:20 +0000 Subject: [PATCH 052/202] fix: payment entry rounding error --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index b3ae627c6e..9a6f8ec8ac 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -853,6 +853,7 @@ frappe.ui.form.on('Payment Entry', { var allocated_positive_outstanding = paid_amount + allocated_negative_outstanding; } else if (in_list(["Customer", "Supplier"], frm.doc.party_type)) { + total_negative_outstanding = flt(total_negative_outstanding, precision("outstanding_amount")) if(paid_amount > total_negative_outstanding) { if(total_negative_outstanding == 0) { frappe.msgprint( From 969616ed095ccf74693c66729c015852fb0e8f5e Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 18 Nov 2023 15:43:23 +0100 Subject: [PATCH 053/202] fix: update modified timestamp Was missing in 434c2a1815f27c59de5cd94528bc371593bdd402 --- erpnext/stock/doctype/item/item.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 6e93f5624f..13f3be8c36 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -888,7 +888,7 @@ "index_web_pages_for_search": 1, "links": [], "make_attachments_public": 1, - "modified": "2023-09-11 13:46:32.688051", + "modified": "2023-09-18 15:41:32.688051", "modified_by": "Administrator", "module": "Stock", "name": "Item", From 32f622ef8061f7db50b4c8f63134f947afdcb306 Mon Sep 17 00:00:00 2001 From: Patrick Eissler <77415730+PatrickDEissler@users.noreply.github.com> Date: Sat, 18 Nov 2023 15:54:34 +0100 Subject: [PATCH 054/202] fix: valuation rate in report Item Prices (#38161) Co-authored-by: PatrickDenis-stack <77415730+PatrickDenis-stack@users.noreply.github.com> --- erpnext/stock/report/item_prices/item_prices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/item_prices/item_prices.py b/erpnext/stock/report/item_prices/item_prices.py index ab47b4a8b9..a53a9f24f5 100644 --- a/erpnext/stock/report/item_prices/item_prices.py +++ b/erpnext/stock/report/item_prices/item_prices.py @@ -202,7 +202,7 @@ def get_valuation_rate(): bin_data = ( frappe.qb.from_(bin) .select( - bin.item_code, Sum(bin.actual_qty * bin.valuation_rate) / Sum(bin.actual_qty).as_("val_rate") + bin.item_code, (Sum(bin.actual_qty * bin.valuation_rate) / Sum(bin.actual_qty)).as_("val_rate") ) .where(bin.actual_qty > 0) .groupby(bin.item_code) From ff5b1b7dedccc23ed7ba71776e5d3d9c385fd222 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Sat, 18 Nov 2023 18:45:14 +0100 Subject: [PATCH 055/202] style: remove trailing whitespace (#38183) --- erpnext/selling/doctype/customer/customer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 1db07972bb..88ed1c6667 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -633,7 +633,7 @@ def make_contact(args, is_primary_contact=1): party_type = args.customer_type if args.doctype == "Customer" else args.supplier_type party_name_key = "customer_name" if args.doctype == "Customer" else "supplier_name" - if party_type == "Individual": + if party_type == "Individual": first, middle, last = parse_full_name(args.get(party_name_key)) values.update( { @@ -648,7 +648,7 @@ def make_contact(args, is_primary_contact=1): "company_name": args.get(party_name_key), } ) - + contact = frappe.get_doc(values) if args.get("email_id"): From cc60c328fe349f7d53c77799e8e91973c2790746 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Sun, 19 Nov 2023 02:53:09 +0000 Subject: [PATCH 056/202] fix: test case for rounded total with cash disc --- .../sales_invoice/test_sales_invoice.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 5a41336b2f..017bfa9654 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -789,6 +789,28 @@ class TestSalesInvoice(FrappeTestCase): w = self.make() self.assertEqual(w.outstanding_amount, w.base_rounded_total) + def test_rounded_total_with_cash_discount(self): + si = frappe.copy_doc(test_records[2]) + + item = copy.deepcopy(si.get("items")[0]) + item.update( + { + "qty": 1, + "rate": 14960.66, + } + ) + + si.set("items", [item]) + si.set("taxes", []) + si.apply_discount_on = "Grand Total" + si.is_cash_or_non_trade_discount = 1 + si.discount_amount = 1 + si.insert() + + self.assertEqual(si.grand_total, 14959.66) + self.assertEqual(si.rounded_total, 14960) + self.assertEqual(si.rounding_adjustment, 0.34) + def test_payment(self): w = self.make() From 97090ff3679104d77a031f29d4acafb8b7ac1580 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 18 Nov 2023 09:04:36 +0530 Subject: [PATCH 057/202] refactor: provision to set `remarks` length in accounts settings --- .../accounts_settings/accounts_settings.json | 37 ++++++++++++++++++- .../report/general_ledger/general_ledger.py | 7 +++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 061bab320e..fd052d0476 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -66,7 +66,12 @@ "show_balance_in_coa", "banking_tab", "enable_party_matching", - "enable_fuzzy_matching" + "enable_fuzzy_matching", + "reports_tab", + "remarks_section", + "general_ledger_remarks_length", + "column_break_lvjk", + "receivable_payable_remarks_length" ], "fields": [ { @@ -422,6 +427,34 @@ "fieldname": "round_row_wise_tax", "fieldtype": "Check", "label": "Round Tax Amount Row-wise" + }, + { + "fieldname": "reports_tab", + "fieldtype": "Tab Break", + "label": "Reports" + }, + { + "default": "0", + "description": "Truncates 'Remarks' column to set character length", + "fieldname": "general_ledger_remarks_length", + "fieldtype": "Int", + "label": "General Ledger" + }, + { + "default": "0", + "description": "Truncates 'Remarks' column to set character length", + "fieldname": "receivable_payable_remarks_length", + "fieldtype": "Int", + "label": "Accounts Receivable/Payable" + }, + { + "fieldname": "column_break_lvjk", + "fieldtype": "Column Break" + }, + { + "fieldname": "remarks_section", + "fieldtype": "Section Break", + "label": "Remarks Column Length" } ], "icon": "icon-cog", @@ -429,7 +462,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-08-28 00:12:02.740633", + "modified": "2023-11-20 09:37:47.650347", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 94cd293615..fa557a133f 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -164,7 +164,12 @@ def get_gl_entries(filters, accounting_dimensions): credit_in_account_currency """ if filters.get("show_remarks"): - select_fields += """,remarks""" + if remarks_length := frappe.db.get_single_value( + "Accounts Settings", "general_ledger_remarks_length" + ): + select_fields += f",substr(remarks, 1, {remarks_length}) as 'remarks'" + else: + select_fields += """,remarks""" order_by_statement = "order by posting_date, account, creation" From a9bf906545dc7c89613c7f6211c35e62b8d7b989 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sat, 18 Nov 2023 10:35:56 +0530 Subject: [PATCH 058/202] refactor: add substring logic in ar/ap report --- .../report/accounts_receivable/accounts_receivable.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 706d743849..0e62ad61cc 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -7,7 +7,7 @@ from collections import OrderedDict import frappe from frappe import _, qb, scrub from frappe.query_builder import Criterion -from frappe.query_builder.functions import Date, Sum +from frappe.query_builder.functions import Date, Substring, Sum from frappe.utils import cint, cstr, flt, getdate, nowdate from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( @@ -764,7 +764,12 @@ class ReceivablePayableReport(object): ) if self.filters.get("show_remarks"): - query = query.select(ple.remarks) + if remarks_length := frappe.db.get_single_value( + "Accounts Settings", "receivable_payable_remarks_length" + ): + query = query.select(Substring(ple.remarks, 1, remarks_length).as_("remarks")) + else: + query = query.select(ple.remarks) if self.filters.get("group_by_party"): query = query.orderby(self.ple.party, self.ple.posting_date) From f6e93f084aadf82f444edb112cc9832b53294b15 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 20 Nov 2023 10:23:35 +0530 Subject: [PATCH 059/202] fix: TypeError in Subcontracting Receipt --- .../doctype/serial_and_batch_bundle/serial_and_batch_bundle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 0a4cae7b34..4b8d9657af 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -406,7 +406,7 @@ class SerialandBatchBundle(Document): if abs(abs(flt(self.total_qty, precision)) - abs(flt(row.get(qty_field), precision))) > 0.01: self.throw_error_message( - f"Total quantity {abs(self.total_qty)} in the Serial and Batch Bundle {bold(self.name)} does not match with the quantity {abs(row.get(qty_field))} for the Item {bold(self.item_code)} in the {self.voucher_type} # {self.voucher_no}" + f"Total quantity {abs(flt(self.total_qty))} in the Serial and Batch Bundle {bold(self.name)} does not match with the quantity {abs(flt(row.get(qty_field)))} for the Item {bold(self.item_code)} in the {self.voucher_type} # {self.voucher_no}" ) def set_is_outward(self): From 331ad62f3c27a54e9d6bb49f1b70b169b633b3a6 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 20 Nov 2023 12:03:54 +0530 Subject: [PATCH 060/202] fix(ux): enable `Quick Entry` for `Task` --- erpnext/projects/doctype/task/task.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json index 25a5455ac1..4d2d225242 100644 --- a/erpnext/projects/doctype/task/task.json +++ b/erpnext/projects/doctype/task/task.json @@ -57,6 +57,7 @@ ], "fields": [ { + "allow_in_quick_entry": 1, "fieldname": "subject", "fieldtype": "Data", "in_global_search": 1, @@ -66,6 +67,7 @@ "search_index": 1 }, { + "allow_in_quick_entry": 1, "bold": 1, "fieldname": "project", "fieldtype": "Link", @@ -396,7 +398,7 @@ "is_tree": 1, "links": [], "max_attachments": 5, - "modified": "2023-09-28 13:52:05.861175", + "modified": "2023-11-20 11:42:41.884069", "modified_by": "Administrator", "module": "Projects", "name": "Task", @@ -416,6 +418,7 @@ "write": 1 } ], + "quick_entry": 1, "search_fields": "subject", "show_name_in_global_search": 1, "show_preview_popup": 1, From 2f3fc12c08218ca06fbb911781090e619a88cf22 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 20 Nov 2023 12:05:25 +0530 Subject: [PATCH 061/202] fix: add route options for new `Task` --- erpnext/projects/doctype/timesheet/timesheet.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index d1d07a79d6..eb7a97e615 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -111,6 +111,7 @@ frappe.ui.form.on("Timesheet", { frm.trigger('setup_filters'); frm.trigger('set_dynamic_field_label'); + frm.trigger('set_route_options_for_new_task'); }, customer: function(frm) { @@ -172,6 +173,14 @@ frappe.ui.form.on("Timesheet", { frm.refresh_fields(); }, + set_route_options_for_new_task: (frm) => { + let task_field = frm.get_docfield('time_logs', 'task'); + + if (task_field) { + task_field.get_route_options_for_new_doc = (row) => ({'project': row.doc.project}); + } + }, + make_invoice: function(frm) { let fields = [{ "fieldtype": "Link", From ee0c64215d160f0bd493bcefc9e94a5a90d318d2 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 20 Nov 2023 11:52:26 +0530 Subject: [PATCH 062/202] refactor: set default for 'update_billed_amount_in_delivery_note' --- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 4 ++-- erpnext/controllers/sales_and_purchase_return.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index cd725b9862..d1677832ed 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -2156,7 +2156,7 @@ "label": "Use Company default Cost Center for Round off" }, { - "default": "0", + "default": "1", "depends_on": "eval: doc.is_return", "fieldname": "update_billed_amount_in_delivery_note", "fieldtype": "Check", @@ -2173,7 +2173,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2023-11-03 14:39:38.012346", + "modified": "2023-11-20 11:51:43.555197", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 165e17b2d7..e91212b031 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -356,6 +356,7 @@ def make_return_doc( if doc.doctype == "Sales Invoice" or doc.doctype == "POS Invoice": doc.consolidated_invoice = "" doc.set("payments", []) + doc.update_billed_amount_in_delivery_note = True for data in source.payments: paid_amount = 0.00 base_paid_amount = 0.00 From 83a13e22b7f4aa8ba2c406389af4e7fa8aad55d0 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 20 Nov 2023 12:27:43 +0530 Subject: [PATCH 063/202] refactor: add flag to POS Invoice --- erpnext/accounts/doctype/pos_invoice/pos_invoice.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index f6047079ff..955b66a1b8 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -18,6 +18,7 @@ "is_pos", "is_return", "update_billed_amount_in_sales_order", + "update_billed_amount_in_delivery_note", "column_break1", "company", "posting_date", @@ -1550,12 +1551,19 @@ "fieldtype": "Currency", "label": "Amount Eligible for Commission", "read_only": 1 + }, + { + "default": "1", + "depends_on": "eval: doc.is_return && doc.return_against", + "fieldname": "update_billed_amount_in_delivery_note", + "fieldtype": "Check", + "label": "Update Billed Amount in Delivery Note" } ], "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2023-06-03 16:23:41.083409", + "modified": "2023-11-20 12:27:12.848149", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", From fb06ad7330fd31bf1def7b87a6c3b787650f1555 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 20 Nov 2023 13:26:02 +0530 Subject: [PATCH 064/202] refactor: update scheduled job for bulk transaction --- erpnext/hooks.py | 2 +- erpnext/utilities/bulk_transaction.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 5483a10b57..b22a3f76cb 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -421,7 +421,7 @@ scheduler_events = { "hourly_long": [ "erpnext.accounts.doctype.process_subscription.process_subscription.create_subscription_process", "erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries", - "erpnext.bulk_transaction.doctype.bulk_transaction_log.bulk_transaction_log.retry_failing_transaction", + "erpnext.utilities.bulk_transaction.retry", ], "daily": [ "erpnext.support.doctype.issue.issue.auto_close_tickets", diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index 57c2f9d787..df21b61139 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -30,7 +30,10 @@ def transaction_processing(data, from_doctype, to_doctype): @frappe.whitelist() -def retry(date: str | None): +def retry(date: str | None = None): + if not date: + date = today() + if date: failed_docs = frappe.db.get_all( "Bulk Transaction Log Detail", From f34ffc20620de442b1a0c9f3d0eb4eb0ff689831 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 20 Nov 2023 11:10:56 +0000 Subject: [PATCH 065/202] fix: exclude `invoice_doctypes` from party advance --- erpnext/accounts/party.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 5c18e506f5..1efe35c206 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -195,7 +195,7 @@ def set_address_details( company_address=None, shipping_address=None, *, - ignore_permissions=False + ignore_permissions=False, ): billing_address_field = ( "customer_address" if party_type == "Lead" else party_type.lower() + "_address" @@ -239,7 +239,7 @@ def set_address_details( shipping_address_display=render_address( shipping_address, check_permissions=not ignore_permissions ), - **get_fetch_values(doctype, "shipping_address", shipping_address) + **get_fetch_values(doctype, "shipping_address", shipping_address), ) if party_details.company_address: @@ -250,7 +250,7 @@ def set_address_details( party_details.company_address_display or render_address(party_details.company_address, check_permissions=False) ), - **get_fetch_values(doctype, "billing_address", party_details.company_address) + **get_fetch_values(doctype, "billing_address", party_details.company_address), ) # shipping address - if not already set @@ -258,7 +258,7 @@ def set_address_details( party_details.update( shipping_address=party_details.billing_address, shipping_address_display=party_details.billing_address_display, - **get_fetch_values(doctype, "shipping_address", party_details.billing_address) + **get_fetch_values(doctype, "shipping_address", party_details.billing_address), ) party_address, shipping_address = ( @@ -981,6 +981,9 @@ def get_partywise_advanced_payment_amount( if party: query = query.where(ple.party == party) + if invoice_doctypes := frappe.get_hooks("invoice_doctypes"): + query = query.where(ple.voucher_type.notin(invoice_doctypes)) + data = query.run() if data: return frappe._dict(data) From 9903049c7ac7310ca9e3f69c30dc355c2e13bfd5 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Mon, 20 Nov 2023 22:27:16 +0530 Subject: [PATCH 066/202] fix: set default asset quantity as 1 [dev] (#38223) * fix: make default asset quantity as 1 * fix: get rate_of_depreciation from asset category for asset auto-creation * chore: create asset depr schedules on PR submit, not asset submit * fix: set default asset quantity as 1 * chore: move patch from v15 to v14 --- erpnext/assets/doctype/asset/asset.json | 3 +- erpnext/assets/doctype/asset/asset.py | 35 +++++++++++-------- erpnext/controllers/buying_controller.py | 2 +- erpnext/patches.txt | 1 + .../v14_0/update_zero_asset_quantity_field.py | 6 ++++ 5 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 erpnext/patches/v14_0/update_zero_asset_quantity_field.py diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index d6b9c461cb..540a4f5549 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -481,6 +481,7 @@ "read_only": 1 }, { + "default": "1", "fieldname": "asset_quantity", "fieldtype": "Int", "label": "Asset Quantity", @@ -571,7 +572,7 @@ "link_fieldname": "target_asset" } ], - "modified": "2023-11-15 17:40:17.315203", + "modified": "2023-11-20 20:57:37.010467", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 3c570d1af0..7b7953b6ce 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -46,12 +46,28 @@ class Asset(AccountsController): self.validate_item() self.validate_cost_center() self.set_missing_values() - self.validate_finance_books() - if not self.split_from: - self.prepare_depreciation_data() - update_draft_asset_depr_schedules(self) self.validate_gross_and_purchase_amount() self.validate_expected_value_after_useful_life() + self.validate_finance_books() + + if not self.split_from: + self.prepare_depreciation_data() + + if self.calculate_depreciation: + update_draft_asset_depr_schedules(self) + + if frappe.db.exists("Asset", self.name): + asset_depr_schedules_names = make_draft_asset_depr_schedules_if_not_present(self) + + if asset_depr_schedules_names: + asset_depr_schedules_links = get_comma_separated_links( + asset_depr_schedules_names, "Asset Depreciation Schedule" + ) + frappe.msgprint( + _( + "Asset Depreciation Schedules created:
{0}

Please check, edit if needed, and submit the Asset." + ).format(asset_depr_schedules_links) + ) self.status = self.get_status() @@ -61,17 +77,7 @@ class Asset(AccountsController): if not self.booked_fixed_asset and self.validate_make_gl_entry(): self.make_gl_entries() if self.calculate_depreciation and not self.split_from: - asset_depr_schedules_names = make_draft_asset_depr_schedules_if_not_present(self) convert_draft_asset_depr_schedules_into_active(self) - if asset_depr_schedules_names: - asset_depr_schedules_links = get_comma_separated_links( - asset_depr_schedules_names, "Asset Depreciation Schedule" - ) - frappe.msgprint( - _( - "Asset Depreciation Schedules created:
{0}

Please check, edit if needed, and submit the Asset." - ).format(asset_depr_schedules_links) - ) self.set_status() add_asset_activity(self.name, _("Asset submitted")) @@ -823,6 +829,7 @@ def get_item_details(item_code, asset_category, gross_purchase_amount): "expected_value_after_useful_life": flt(gross_purchase_amount) * flt(d.salvage_value_percentage / 100), "depreciation_start_date": d.depreciation_start_date or nowdate(), + "rate_of_depreciation": d.rate_of_depreciation, } ) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index a470b47a45..68ad97d7ba 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -758,7 +758,7 @@ class BuyingController(SubcontractingController): "calculate_depreciation": 0, "purchase_receipt_amount": purchase_amount, "gross_purchase_amount": purchase_amount, - "asset_quantity": row.qty if is_grouped_asset else 0, + "asset_quantity": row.qty if is_grouped_asset else 1, "purchase_receipt": self.name if self.doctype == "Purchase Receipt" else None, "purchase_invoice": self.name if self.doctype == "Purchase Invoice" else None, } diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 6c10dd9bbb..0badab56ea 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -351,5 +351,6 @@ erpnext.patches.v15_0.rename_daily_depreciation_to_depreciation_amount_based_on_ erpnext.patches.v15_0.rename_depreciation_amount_based_on_num_days_in_month_to_daily_prorata_based erpnext.patches.v15_0.set_reserved_stock_in_bin erpnext.patches.v14_0.create_accounting_dimensions_in_supplier_quotation +erpnext.patches.v14_0.update_zero_asset_quantity_field # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger diff --git a/erpnext/patches/v14_0/update_zero_asset_quantity_field.py b/erpnext/patches/v14_0/update_zero_asset_quantity_field.py new file mode 100644 index 0000000000..0480f9b7aa --- /dev/null +++ b/erpnext/patches/v14_0/update_zero_asset_quantity_field.py @@ -0,0 +1,6 @@ +import frappe + + +def execute(): + asset = frappe.qb.DocType("Asset") + frappe.qb.update(asset).set(asset.asset_quantity, 1).where(asset.asset_quantity == 0).run() From 56e991b7f49e4677605f74b1de7d00ab40bf09cc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 21 Nov 2023 11:46:45 +0530 Subject: [PATCH 067/202] test: prevent rounding loss based validation error --- .../test_payment_reconciliation.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index 71bc498b49..d7a73f0ce7 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -1137,6 +1137,40 @@ class TestPaymentReconciliation(FrappeTestCase): self.assertEqual(pay.unallocated_amount, 1000) self.assertEqual(pay.difference_amount, 0) + def test_rounding_of_unallocated_amount(self): + self.supplier = "_Test Supplier USD" + pi = self.create_purchase_invoice(qty=1, rate=10, do_not_submit=True) + pi.supplier = self.supplier + pi.currency = "USD" + pi.conversion_rate = 80 + pi.credit_to = self.creditors_usd + pi.save().submit() + + pe = get_payment_entry(pi.doctype, pi.name) + pe.target_exchange_rate = 78.726500000 + pe.received_amount = 26.75 + pe.paid_amount = 2105.93 + pe.references = [] + pe.save().submit() + + # unallocated_amount will have some rounding loss - 26.749950 + self.assertNotEqual(pe.unallocated_amount, 26.75) + + pr = frappe.get_doc("Payment Reconciliation") + pr.company = self.company + pr.party_type = "Supplier" + pr.party = self.supplier + pr.receivable_payable_account = self.creditors_usd + pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate() + pr.get_unreconciled_entries() + + invoices = [invoice.as_dict() for invoice in pr.invoices] + payments = [payment.as_dict() for payment in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + + # Should not raise frappe.exceptions.ValidationError: Payment Entry has been modified after you pulled it. Please pull it again. + pr.reconcile() + def make_customer(customer_name, currency=None): if not frappe.db.exists("Customer", customer_name): From ac91030b31f1108b7e32844f12a3a6c916c0120f Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 21 Nov 2023 13:18:34 +0530 Subject: [PATCH 068/202] fix(Timesheet): warn user if billing hours > actual hours instead of resetting (#38239) * revert: "fix(Timesheet): reset billing hours equal to hours if they exceed actual hours" This reverts commit 0ec8034507996f06eaf8ca13a414d10b34038c6c. * fix: warn user if billing hours > actual hours --- erpnext/projects/doctype/timesheet/timesheet.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 8e464b5c6b..b9d801ce90 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -69,8 +69,14 @@ class Timesheet(Document): def update_billing_hours(self, args): if args.is_billable: - if flt(args.billing_hours) == 0.0 or flt(args.billing_hours) > flt(args.hours): + if flt(args.billing_hours) == 0.0: args.billing_hours = args.hours + elif flt(args.billing_hours) > flt(args.hours): + frappe.msgprint( + _("Warning - Row {0}: Billing Hours are more than Actual Hours").format(args.idx), + indicator="orange", + alert=True, + ) else: args.billing_hours = 0 From 5c308a4f9aa1a27cbd216addbe495b9bf69735b1 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 21 Nov 2023 14:42:26 +0530 Subject: [PATCH 069/202] fix: valuation rate for FG item for subcontracting receipt (#38244) --- .../serial_and_batch_bundle.py | 2 +- .../test_subcontracting_receipt.py | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 4b8d9657af..abdbeb496b 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -246,7 +246,7 @@ class SerialandBatchBundle(Document): valuation_field = "rate" child_table = "Subcontracting Receipt Supplied Item" else: - valuation_field = "rm_supp_cost" + valuation_field = "rate" child_table = "Subcontracting Receipt Item" precision = frappe.get_precision(child_table, valuation_field) or 2 diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 6191a8ca94..f0e4e00074 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -667,6 +667,104 @@ class TestSubcontractingReceipt(FrappeTestCase): "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0 ) + def test_subcontracting_receipt_valuation_for_fg_with_auto_created_serial_batch_bundle(self): + set_backflush_based_on("BOM") + + fg_item = make_item( + properties={ + "is_stock_item": 1, + "is_sub_contracted_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "BSSNGS-.####", + } + ).name + + rm_item1 = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "BNGS-.####", + } + ).name + + rm_item2 = make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "has_serial_no": 1, + "create_new_batch": 1, + "batch_number_series": "BNGS-.####", + "serial_no_series": "BNSS-.####", + } + ).name + + rm_item3 = make_item( + properties={ + "is_stock_item": 1, + "has_serial_no": 1, + "serial_no_series": "BSSSS-.####", + } + ).name + + bom = make_bom(item=fg_item, raw_materials=[rm_item1, rm_item2, rm_item3]) + + rm_batch_no = None + for row in bom.items: + make_stock_entry( + item_code=row.item_code, + qty=1, + target="_Test Warehouse 1 - _TC", + rate=300, + ) + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 1", + "qty": 1, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 1, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 1 + ) + scr = make_subcontracting_receipt(sco.name) + scr.save() + scr.submit() + scr.reload() + + for row in scr.supplied_items: + self.assertEqual(row.rate, 300.00) + self.assertTrue(row.serial_and_batch_bundle) + auto_created_serial_batch = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_no": scr.name, "voucher_detail_no": row.name}, + "auto_created_serial_and_batch_bundle", + ) + + self.assertTrue(auto_created_serial_batch) + + self.assertEqual(scr.items[0].rm_cost_per_qty, 900) + self.assertEqual(scr.items[0].service_cost_per_qty, 100) + self.assertEqual(scr.items[0].rate, 1000) + valuation_rate = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_no": scr.name, "voucher_detail_no": scr.items[0].name}, + "valuation_rate", + ) + + self.assertEqual(flt(valuation_rate), flt(1000)) + + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0 + ) + def test_subcontracting_receipt_raw_material_rate(self): # Step - 1: Set Backflush Based On as "BOM" set_backflush_based_on("BOM") From 6518582ed3be49dd3bc6a62745dae3e6faed2658 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 21 Nov 2023 15:14:55 +0530 Subject: [PATCH 070/202] fix: unset discount amount based on coupon code --- erpnext/public/js/utils/sales_common.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/public/js/utils/sales_common.js b/erpnext/public/js/utils/sales_common.js index 1d6daa554b..5514963c96 100644 --- a/erpnext/public/js/utils/sales_common.js +++ b/erpnext/public/js/utils/sales_common.js @@ -369,6 +369,11 @@ erpnext.sales_common = { } } } + + coupon_code() { + this.frm.set_value("discount_amount", 0); + this.frm.set_value("additional_discount_percentage", 0); + } }; } } From 9006c9b7478ceee5f7662d62e8eb02a08a309906 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 21 Nov 2023 16:44:01 +0530 Subject: [PATCH 071/202] chore: rename 'unreconcile payments' to 'unreconcile payment' --- .../{unreconcile_payments => unreconcile_payment}/__init__.py | 0 .../test_unreconcile_payment.py} | 2 +- .../unreconcile_payment.js} | 2 +- .../unreconcile_payment.json} | 2 +- .../unreconcile_payment.py} | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename erpnext/accounts/doctype/{unreconcile_payments => unreconcile_payment}/__init__.py (100%) rename erpnext/accounts/doctype/{unreconcile_payments/test_unreconcile_payments.py => unreconcile_payment/test_unreconcile_payment.py} (99%) rename erpnext/accounts/doctype/{unreconcile_payments/unreconcile_payments.js => unreconcile_payment/unreconcile_payment.js} (94%) rename erpnext/accounts/doctype/{unreconcile_payments/unreconcile_payments.json => unreconcile_payment/unreconcile_payment.json} (98%) rename erpnext/accounts/doctype/{unreconcile_payments/unreconcile_payments.py => unreconcile_payment/unreconcile_payment.py} (99%) diff --git a/erpnext/accounts/doctype/unreconcile_payments/__init__.py b/erpnext/accounts/doctype/unreconcile_payment/__init__.py similarity index 100% rename from erpnext/accounts/doctype/unreconcile_payments/__init__.py rename to erpnext/accounts/doctype/unreconcile_payment/__init__.py diff --git a/erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py b/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py similarity index 99% rename from erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py rename to erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py index 78e04bff81..0f1a351176 100644 --- a/erpnext/accounts/doctype/unreconcile_payments/test_unreconcile_payments.py +++ b/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py @@ -10,7 +10,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal from erpnext.accounts.test.accounts_mixin import AccountsTestMixin -class TestUnreconcilePayments(AccountsTestMixin, FrappeTestCase): +class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase): def setUp(self): self.create_company() self.create_customer() diff --git a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.js b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.js similarity index 94% rename from erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.js rename to erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.js index c522567637..70cefb13b5 100644 --- a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.js +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.js @@ -1,7 +1,7 @@ // Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -frappe.ui.form.on("Unreconcile Payments", { +frappe.ui.form.on("Unreconcile Payment", { refresh(frm) { frm.set_query("voucher_type", function() { return { diff --git a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.json b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json similarity index 98% rename from erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.json rename to erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json index f29e61b6ef..17e0b4ddd3 100644 --- a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.json +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json @@ -61,7 +61,7 @@ "modified": "2023-08-28 17:42:50.261377", "modified_by": "Administrator", "module": "Accounts", - "name": "Unreconcile Payments", + "name": "Unreconcile Payment", "naming_rule": "Expression", "owner": "Administrator", "permissions": [ diff --git a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py similarity index 99% rename from erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py rename to erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py index 4f9fb50d46..9abd752350 100644 --- a/erpnext/accounts/doctype/unreconcile_payments/unreconcile_payments.py +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py @@ -15,7 +15,7 @@ from erpnext.accounts.utils import ( ) -class UnreconcilePayments(Document): +class UnreconcilePayment(Document): def validate(self): self.supported_types = ["Payment Entry", "Journal Entry"] if not self.voucher_type in self.supported_types: From e2bb4e2baa9059afb27f685beb88172a615097a4 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Tue, 21 Nov 2023 22:32:43 +0530 Subject: [PATCH 072/202] fix: set asset's valuation_rate according to asset quantity (#38254) --- .../doctype/purchase_receipt/purchase_receipt.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index d905fe5ea6..a5940f07d6 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -731,12 +731,18 @@ class PurchaseReceipt(BuyingController): def update_assets(self, item, valuation_rate): assets = frappe.db.get_all( - "Asset", filters={"purchase_receipt": self.name, "item_code": item.item_code} + "Asset", + filters={"purchase_receipt": self.name, "item_code": item.item_code}, + fields=["name", "asset_quantity"], ) for asset in assets: - frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(valuation_rate)) - frappe.db.set_value("Asset", asset.name, "purchase_receipt_amount", flt(valuation_rate)) + frappe.db.set_value( + "Asset", asset.name, "gross_purchase_amount", flt(valuation_rate) * asset.asset_quantity + ) + frappe.db.set_value( + "Asset", asset.name, "purchase_receipt_amount", flt(valuation_rate) * asset.asset_quantity + ) def update_status(self, status): self.set_status(update=True, status=status) From 74f9e34182563b5dd3ef71d93b66596a12be5e91 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 21 Nov 2023 16:51:06 +0530 Subject: [PATCH 073/202] chore: update new unreconcile doctype name in JS and PY files --- .../doctype/journal_entry/journal_entry.js | 2 +- .../doctype/payment_entry/payment_entry.js | 4 ++-- .../doctype/payment_entry/payment_entry.py | 2 +- .../doctype/purchase_invoice/purchase_invoice.js | 2 +- .../doctype/sales_invoice/sales_invoice.js | 4 ++-- .../doctype/sales_invoice/sales_invoice.py | 2 +- .../test_unreconcile_payment.py | 8 ++++---- .../unreconcile_payment/unreconcile_payment.json | 4 ++-- .../unreconcile_payment/unreconcile_payment.py | 2 +- erpnext/controllers/accounts_controller.py | 6 +++--- erpnext/public/js/utils/unreconcile.js | 14 +++++++------- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index 22b6880ad5..9684a0d9d1 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -51,7 +51,7 @@ frappe.ui.form.on("Journal Entry", { }, __('Make')); } - erpnext.accounts.unreconcile_payments.add_unreconcile_btn(frm); + erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm); }, before_save: function(frm) { if ((frm.doc.docstatus == 0) && (!frm.doc.is_system_generated)) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 9a6f8ec8ac..26112409b7 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -9,7 +9,7 @@ erpnext.accounts.taxes.setup_tax_filters("Advance Taxes and Charges"); frappe.ui.form.on('Payment Entry', { onload: function(frm) { - frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger','Repost Accounting Ledger', 'Unreconcile Payments', 'Unreconcile Payment Entries']; + frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice', 'Journal Entry', 'Repost Payment Ledger','Repost Accounting Ledger', 'Unreconcile Payment', 'Unreconcile Payment Entries']; if(frm.doc.__islocal) { if (!frm.doc.paid_from) frm.set_value("paid_from_account_currency", null); @@ -160,7 +160,7 @@ frappe.ui.form.on('Payment Entry', { }, __('Actions')); } - erpnext.accounts.unreconcile_payments.add_unreconcile_btn(frm); + erpnext.accounts.unreconcile_payment.add_unreconcile_btn(frm); }, validate_company: (frm) => { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index ef304bc110..0344e3de9f 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -148,7 +148,7 @@ class PaymentEntry(AccountsController): "Repost Payment Ledger Items", "Repost Accounting Ledger", "Repost Accounting Ledger Items", - "Unreconcile Payments", + "Unreconcile Payment", "Unreconcile Payment Entries", ) super(PaymentEntry, self).on_cancel() diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 2eaa33767c..4b0df12f45 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -180,7 +180,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. } this.frm.set_df_property("tax_withholding_category", "hidden", doc.apply_tds ? 0 : 1); - erpnext.accounts.unreconcile_payments.add_unreconcile_btn(me.frm); + erpnext.accounts.unreconcile_payment.add_unreconcile_btn(me.frm); } unblock_invoice() { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index b1a7b10eea..6763e446a5 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -37,7 +37,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e super.onload(); this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice', 'Timesheet', 'POS Invoice Merge Log', - 'POS Closing Entry', 'Journal Entry', 'Payment Entry', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payments", "Unreconcile Payment Entries"]; + 'POS Closing Entry', 'Journal Entry', 'Payment Entry', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries"]; if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) { // show debit_to in print format @@ -184,7 +184,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e } } - erpnext.accounts.unreconcile_payments.add_unreconcile_btn(me.frm); + erpnext.accounts.unreconcile_payment.add_unreconcile_btn(me.frm); } make_maintenance_schedule() { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index fa95ccdc57..20b7382138 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -395,7 +395,7 @@ class SalesInvoice(SellingController): "Repost Payment Ledger Items", "Repost Accounting Ledger", "Repost Accounting Ledger Items", - "Unreconcile Payments", + "Unreconcile Payment", "Unreconcile Payment Entries", "Payment Ledger Entry", "Serial and Batch Bundle", diff --git a/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py b/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py index 0f1a351176..f404d9981a 100644 --- a/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py +++ b/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py @@ -73,7 +73,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase): unreconcile = frappe.get_doc( { - "doctype": "Unreconcile Payments", + "doctype": "Unreconcile Payment", "company": self.company, "voucher_type": pe.doctype, "voucher_no": pe.name, @@ -138,7 +138,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase): unreconcile = frappe.get_doc( { - "doctype": "Unreconcile Payments", + "doctype": "Unreconcile Payment", "company": self.company, "voucher_type": pe2.doctype, "voucher_no": pe2.name, @@ -196,7 +196,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase): unreconcile = frappe.get_doc( { - "doctype": "Unreconcile Payments", + "doctype": "Unreconcile Payment", "company": self.company, "voucher_type": pe.doctype, "voucher_no": pe.name, @@ -281,7 +281,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase): unreconcile = frappe.get_doc( { - "doctype": "Unreconcile Payments", + "doctype": "Unreconcile Payment", "company": self.company, "voucher_type": pe2.doctype, "voucher_no": pe2.name, diff --git a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json index 17e0b4ddd3..f906dc6cec 100644 --- a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json @@ -21,7 +21,7 @@ "fieldtype": "Link", "label": "Amended From", "no_copy": 1, - "options": "Unreconcile Payments", + "options": "Unreconcile Payment", "print_hide": 1, "read_only": 1 }, @@ -90,4 +90,4 @@ "sort_order": "DESC", "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py index 9abd752350..77906a7833 100644 --- a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py @@ -142,7 +142,7 @@ def create_unreconcile_doc_for_selection(selections=None): selections = frappe.json.loads(selections) # assuming each row is a unique voucher for row in selections: - unrecon = frappe.new_doc("Unreconcile Payments") + unrecon = frappe.new_doc("Unreconcile Payment") unrecon.company = row.get("company") unrecon.voucher_type = row.get("voucher_type") unrecon.voucher_no = row.get("voucher_no") diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 38c1e820d2..d12d50d2e7 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -239,7 +239,7 @@ class AccountsController(TransactionBase): references_map.setdefault(x.parent, []).append(x.name) for doc, rows in references_map.items(): - unreconcile_doc = frappe.get_doc("Unreconcile Payments", doc) + unreconcile_doc = frappe.get_doc("Unreconcile Payment", doc) for row in rows: unreconcile_doc.remove(unreconcile_doc.get("allocations", {"name": row})[0]) @@ -248,9 +248,9 @@ class AccountsController(TransactionBase): unreconcile_doc.save(ignore_permissions=True) # delete docs upon parent doc deletion - unreconcile_docs = frappe.db.get_all("Unreconcile Payments", filters={"voucher_no": self.name}) + unreconcile_docs = frappe.db.get_all("Unreconcile Payment", filters={"voucher_no": self.name}) for x in unreconcile_docs: - _doc = frappe.get_doc("Unreconcile Payments", x.name) + _doc = frappe.get_doc("Unreconcile Payment", x.name) if _doc.docstatus == 1: _doc.cancel() _doc.delete() diff --git a/erpnext/public/js/utils/unreconcile.js b/erpnext/public/js/utils/unreconcile.js index fa00ed2362..79490a162d 100644 --- a/erpnext/public/js/utils/unreconcile.js +++ b/erpnext/public/js/utils/unreconcile.js @@ -1,6 +1,6 @@ frappe.provide('erpnext.accounts'); -erpnext.accounts.unreconcile_payments = { +erpnext.accounts.unreconcile_payment = { add_unreconcile_btn(frm) { if (frm.doc.docstatus == 1) { if(((frm.doc.doctype == "Journal Entry") && (frm.doc.voucher_type != "Journal Entry")) @@ -10,7 +10,7 @@ erpnext.accounts.unreconcile_payments = { } frappe.call({ - "method": "erpnext.accounts.doctype.unreconcile_payments.unreconcile_payments.doc_has_references", + "method": "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.doc_has_references", "args": { "doctype": frm.doc.doctype, "docname": frm.doc.name @@ -18,7 +18,7 @@ erpnext.accounts.unreconcile_payments = { callback: function(r) { if (r.message) { frm.add_custom_button(__("UnReconcile"), function() { - erpnext.accounts.unreconcile_payments.build_unreconcile_dialog(frm); + erpnext.accounts.unreconcile_payment.build_unreconcile_dialog(frm); }, __('Actions')); } } @@ -74,7 +74,7 @@ erpnext.accounts.unreconcile_payments = { // get linked payments frappe.call({ - "method": "erpnext.accounts.doctype.unreconcile_payments.unreconcile_payments.get_linked_payments_for_doc", + "method": "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.get_linked_payments_for_doc", "args": { "company": frm.doc.company, "doctype": frm.doc.doctype, @@ -96,8 +96,8 @@ erpnext.accounts.unreconcile_payments = { let selected_allocations = values.allocations.filter(x=>x.__checked); if (selected_allocations.length > 0) { - let selection_map = erpnext.accounts.unreconcile_payments.build_selection_map(frm, selected_allocations); - erpnext.accounts.unreconcile_payments.create_unreconcile_docs(selection_map); + let selection_map = erpnext.accounts.unreconcile_payment.build_selection_map(frm, selected_allocations); + erpnext.accounts.unreconcile_payment.create_unreconcile_docs(selection_map); d.hide(); } else { @@ -115,7 +115,7 @@ erpnext.accounts.unreconcile_payments = { create_unreconcile_docs(selection_map) { frappe.call({ - "method": "erpnext.accounts.doctype.unreconcile_payments.unreconcile_payments.create_unreconcile_doc_for_selection", + "method": "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.create_unreconcile_doc_for_selection", "args": { "selections": selection_map }, From 8b04c1d4f6356bc332c5dd8f6f8711d778e030cd Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 22 Nov 2023 09:59:32 +0530 Subject: [PATCH 074/202] refactor: optimize outstanding vouchers query --- erpnext/accounts/utils.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 7d91309fcc..6d2a47f73e 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1833,6 +1833,28 @@ class QueryPaymentLedger(object): Table("outstanding").amount_in_account_currency >= self.max_outstanding ) + if self.limit and self.get_invoices: + outstanding_vouchers = ( + qb.from_(ple) + .select( + ple.against_voucher_no.as_("voucher_no"), + Sum(ple.amount_in_account_currency).as_("amount_in_account_currency"), + ) + .where(ple.delinked == 0) + .where(Criterion.all(filter_on_against_voucher_no)) + .where(Criterion.all(self.common_filter)) + .groupby(ple.against_voucher_type, ple.against_voucher_no, ple.party_type, ple.party) + .orderby(ple.posting_date, ple.voucher_no) + .having(qb.Field("amount_in_account_currency") > 0) + .limit(self.limit) + .run() + ) + if outstanding_vouchers: + filter_on_voucher_no.append(ple.voucher_no.isin([x[0] for x in outstanding_vouchers])) + filter_on_against_voucher_no.append( + ple.against_voucher_no.isin([x[0] for x in outstanding_vouchers]) + ) + # build query for voucher amount query_voucher_amount = ( qb.from_(ple) From b11ae4b54c42cd7f09db65c576ac75f7faf2f0c8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 22 Nov 2023 10:26:50 +0530 Subject: [PATCH 075/202] chore: remove dead link --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 44bd729688..710187ad2f 100644 --- a/README.md +++ b/README.md @@ -73,8 +73,6 @@ New passwords will be created for the ERPNext "Administrator" user, the MariaDB 1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines) 1. [Report Security Vulnerabilities](https://erpnext.com/security) 1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines) -1. [Translations](https://translate.erpnext.com) - ## License From 9c889b37fb3e6572043c7a28706e43d051e2ff46 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 20 Nov 2023 18:33:56 +0530 Subject: [PATCH 076/202] fix(ux): no need to select rows to reserve the stock --- erpnext/selling/doctype/sales_order/sales_order.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 3ad18daf19..01cbbe743d 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -214,7 +214,6 @@ frappe.ui.form.on("Sales Order", { label: __("Items to Reserve"), allow_bulk_edit: false, cannot_add_rows: true, - cannot_delete_rows: true, data: [], fields: [ { @@ -260,7 +259,7 @@ frappe.ui.form.on("Sales Order", { ], primary_action_label: __("Reserve Stock"), primary_action: () => { - var data = {items: dialog.fields_dict.items.grid.get_selected_children()}; + var data = {items: dialog.fields_dict.items.grid.data}; if (data.items && data.items.length > 0) { frappe.call({ @@ -278,9 +277,6 @@ frappe.ui.form.on("Sales Order", { } }); } - else { - frappe.msgprint(__("Please select items to reserve.")); - } dialog.hide(); }, @@ -316,7 +312,6 @@ frappe.ui.form.on("Sales Order", { label: __("Reserved Stock"), allow_bulk_edit: false, cannot_add_rows: true, - cannot_delete_rows: true, in_place_edit: true, data: [], fields: [ @@ -360,7 +355,7 @@ frappe.ui.form.on("Sales Order", { ], primary_action_label: __("Unreserve Stock"), primary_action: () => { - var data = {sr_entries: dialog.fields_dict.sr_entries.grid.get_selected_children()}; + var data = {sr_entries: dialog.fields_dict.sr_entries.grid.data}; if (data.sr_entries && data.sr_entries.length > 0) { frappe.call({ @@ -377,9 +372,6 @@ frappe.ui.form.on("Sales Order", { } }); } - else { - frappe.msgprint(__("Please select items to unreserve.")); - } dialog.hide(); }, From 73586fd9b2f9392d18f65a063b14ef2de2629615 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 11:37:14 +0530 Subject: [PATCH 077/202] fix: use field `sales_order_item` instead `name` --- erpnext/selling/doctype/sales_order/sales_order.js | 6 +++--- erpnext/stock/doctype/pick_list/pick_list.py | 2 +- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 2 +- .../stock_reservation_entry/stock_reservation_entry.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 01cbbe743d..81b0d016ae 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -217,9 +217,9 @@ frappe.ui.form.on("Sales Order", { data: [], fields: [ { - fieldname: "name", + fieldname: "sales_order_item", fieldtype: "Data", - label: __("Name"), + label: __("Sales Order Item"), reqd: 1, read_only: 1, }, @@ -288,7 +288,7 @@ frappe.ui.form.on("Sales Order", { if (unreserved_qty > 0) { dialog.fields_dict.items.df.data.push({ - 'name': item.name, + 'sales_order_item': item.name, 'item_code': item.item_code, 'warehouse': item.warehouse, 'qty_to_reserve': (unreserved_qty / flt(item.conversion_factor)) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index ed20209577..3350a688e8 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -233,7 +233,7 @@ class PickList(Document): for location in self.locations: if location.warehouse and location.sales_order and location.sales_order_item: item_details = { - "name": location.sales_order_item, + "sales_order_item": location.sales_order_item, "item_code": location.item_code, "warehouse": location.warehouse, "qty_to_reserve": (flt(location.picked_qty) - flt(location.stock_reserved_qty)), diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index d905fe5ea6..9bc7e58f80 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -775,7 +775,7 @@ class PurchaseReceipt(BuyingController): for item in self.items: if item.sales_order and item.sales_order_item: item_details = { - "name": item.sales_order_item, + "sales_order_item": item.sales_order_item, "item_code": item.item_code, "warehouse": item.warehouse, "qty_to_reserve": item.stock_qty, diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py index 09542826f3..df3e288c4c 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -869,7 +869,7 @@ def create_stock_reservation_entries_for_so_items( items = [] if items_details: for item in items_details: - so_item = frappe.get_doc("Sales Order Item", item.get("name")) + so_item = frappe.get_doc("Sales Order Item", item.get("sales_order_item")) so_item.warehouse = item.get("warehouse") so_item.qty_to_reserve = ( flt(item.get("qty_to_reserve")) From 2a41da94d443dee51e615b395d18ad161d4e87fc Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 21 Nov 2023 11:34:53 +0530 Subject: [PATCH 078/202] fix(ux): no need to select rows to unreserve the stock --- erpnext/selling/doctype/sales_order/sales_order.js | 10 +++++----- .../stock_reservation_entry/stock_reservation_entry.py | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 81b0d016ae..97b214e33e 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -304,7 +304,7 @@ frappe.ui.form.on("Sales Order", { cancel_stock_reservation_entries(frm) { const dialog = new frappe.ui.Dialog({ title: __("Stock Unreservation"), - size: "large", + size: "extra-large", fields: [ { fieldname: "sr_entries", @@ -316,9 +316,9 @@ frappe.ui.form.on("Sales Order", { data: [], fields: [ { - fieldname: "name", + fieldname: "sre", fieldtype: "Link", - label: __("SRE"), + label: __("Stock Reservation Entry"), options: "Stock Reservation Entry", reqd: 1, read_only: 1, @@ -362,7 +362,7 @@ frappe.ui.form.on("Sales Order", { doc: frm.doc, method: "cancel_stock_reservation_entries", args: { - sre_list: data.sr_entries, + sre_list: data.sr_entries.map(item => item.sre), }, freeze: true, freeze_message: __('Unreserving Stock...'), @@ -388,7 +388,7 @@ frappe.ui.form.on("Sales Order", { r.message.forEach(sre => { if (flt(sre.reserved_qty) > flt(sre.delivered_qty)) { dialog.fields_dict.sr_entries.df.data.push({ - 'name': sre.name, + 'sre': sre.name, 'item_code': sre.item_code, 'warehouse': sre.warehouse, 'qty': (flt(sre.reserved_qty) - flt(sre.delivered_qty)) diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py index df3e288c4c..cbfa4e0a43 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -1053,12 +1053,14 @@ def cancel_stock_reservation_entries( from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None, from_voucher_no: str = None, from_voucher_detail_no: str = None, - sre_list: list[dict] = None, + sre_list: list = None, notify: bool = True, ) -> None: """Cancel Stock Reservation Entries.""" if not sre_list: + sre_list = {} + if voucher_type and voucher_no: sre_list = get_stock_reservation_entries_for_voucher( voucher_type, voucher_no, voucher_detail_no, fields=["name"] @@ -1082,9 +1084,11 @@ def cancel_stock_reservation_entries( sre_list = query.run(as_dict=True) + sre_list = [d.name for d in sre_list] + if sre_list: for sre in sre_list: - frappe.get_doc("Stock Reservation Entry", sre["name"]).cancel() + frappe.get_doc("Stock Reservation Entry", sre).cancel() if notify: msg = _("Stock Reservation Entries Cancelled") From 0ca7527f7abddcab59edce434d0e68e1deebfc33 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 22 Nov 2023 14:02:01 +0530 Subject: [PATCH 079/202] fix: patch - Duplicate entry quality inspection parameter (#38262) --- erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py b/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py index e53bdf8f19..08ddbbf337 100644 --- a/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py +++ b/erpnext/patches/v13_0/convert_qi_parameter_to_link_field.py @@ -21,6 +21,9 @@ def execute(): params = set({x.casefold(): x for x in params}.values()) for parameter in params: + if frappe.db.exists("Quality Inspection Parameter", parameter): + continue + frappe.get_doc( {"doctype": "Quality Inspection Parameter", "parameter": parameter, "description": parameter} ).insert(ignore_permissions=True) From f9713eeb5690f9e71e01c6c570012f561a633c73 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 15:22:42 +0530 Subject: [PATCH 080/202] fix: skip fixed assets in parent --- .../doctype/product_bundle/product_bundle.py | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index ac83c0f046..4b401e7e67 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -59,6 +59,8 @@ class ProductBundle(Document): """Validates, main Item is not a stock item""" if frappe.db.get_value("Item", self.new_item_code, "is_stock_item"): frappe.throw(_("Parent Item {0} must not be a Stock Item").format(self.new_item_code)) + if frappe.db.get_value("Item", self.new_item_code, "is_fixed_asset"): + frappe.throw(_("Parent Item {0} must not be a Fixed Asset").format(self.new_item_code)) def validate_child_items(self): for item in self.items: @@ -73,12 +75,17 @@ class ProductBundle(Document): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def get_new_item_code(doctype, txt, searchfield, start, page_len, filters): - from erpnext.controllers.queries import get_match_cond - - return frappe.db.sql( - """select name, item_name, description from tabItem - where is_stock_item=0 and name not in (select name from `tabProduct Bundle`) - and %s like %s %s limit %s offset %s""" - % (searchfield, "%s", get_match_cond(doctype), "%s", "%s"), - ("%%%s%%" % txt, page_len, start), - ) + product_bundles = frappe.db.get_list("Product Bundle", pluck="name") + item = frappe.qb.DocType("Item") + return ( + frappe.qb.from_(item) + .select("*") + .where( + (item.is_stock_item == 0) + & (item.is_fixed_asset == 0) + & (item.name.notin(product_bundles)) + & (item[searchfield].like(f"%{txt}%")) + ) + .limit(page_len) + .offset(start) + ).run() From ee76af76812fe04d86653fd1955ad133c8cb5df8 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 15:23:17 +0530 Subject: [PATCH 081/202] feat: add disabled field in product bundle --- .../product_bundle/product_bundle.json | 398 +++++------------- 1 file changed, 101 insertions(+), 297 deletions(-) diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.json b/erpnext/selling/doctype/product_bundle/product_bundle.json index 56155fb750..c4f21b61b9 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.json +++ b/erpnext/selling/doctype/product_bundle/product_bundle.json @@ -1,315 +1,119 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "beta": 0, - "creation": "2013-06-20 11:53:21", - "custom": 0, - "description": "Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. \n\nThe package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".\n\nFor Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Product Bundle Item.\n\nNote: BOM = Bill of Materials", - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 0, + "actions": [], + "allow_import": 1, + "creation": "2013-06-20 11:53:21", + "description": "Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. \n\nThe package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".\n\nFor Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Product Bundle Item.\n\nNote: BOM = Bill of Materials", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "basic_section", + "new_item_code", + "description", + "column_break_eonk", + "disabled", + "item_section", + "items", + "section_break_4", + "about" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "basic_section", - "fieldtype": "Section Break", - "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": "", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, - "unique": 0 - }, + "fieldname": "basic_section", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "new_item_code", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Parent Item", - "length": 0, - "no_copy": 1, - "oldfieldname": "new_item_code", - "oldfieldtype": "Data", - "options": "Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "new_item_code", + "fieldtype": "Link", + "in_global_search": 1, + "in_list_view": 1, + "label": "Parent Item", + "no_copy": 1, + "oldfieldname": "new_item_code", + "oldfieldtype": "Data", + "options": "Item", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "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, - "unique": 0 - }, + "fieldname": "description", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Description" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "List items that form the package.", - "fieldname": "item_section", - "fieldtype": "Section Break", - "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": "Items", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, - "unique": 0 - }, + "description": "List items that form the package.", + "fieldname": "item_section", + "fieldtype": "Section Break", + "label": "Items" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "items", - "fieldtype": "Table", - "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": "Items", - "length": 0, - "no_copy": 0, - "oldfieldname": "sales_bom_items", - "oldfieldtype": "Table", - "options": "Product Bundle Item", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "items", + "fieldtype": "Table", + "label": "Items", + "oldfieldname": "sales_bom_items", + "oldfieldtype": "Table", + "options": "Product Bundle Item", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_4", - "fieldtype": "Section Break", - "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, - "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, - "unique": 0 - }, + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "about", - "fieldtype": "HTML", - "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": "", - "length": 0, - "no_copy": 0, - "options": "

About Product Bundle

\n\n

Aggregate group of Items into another Item. This is useful if you are bundling a certain Items into a package and you maintain stock of the packed Items and not the aggregate Item.

\n

The package Item will have Is Stock Item as No and Is Sales Item as Yes.

\n

Example:

\n

If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Product Bundle Item.

", - "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, - "unique": 0 + "fieldname": "about", + "fieldtype": "HTML", + "options": "

About Product Bundle

\n\n

Aggregate group of Items into another Item. This is useful if you are bundling a certain Items into a package and you maintain stock of the packed Items and not the aggregate Item.

\n

The package Item will have Is Stock Item as No and Is Sales Item as Yes.

\n

Example:

\n

If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Product Bundle Item.

" + }, + { + "default": "0", + "fieldname": "disabled", + "fieldtype": "Check", + "label": "Disabled" + }, + { + "fieldname": "column_break_eonk", + "fieldtype": "Column Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-sitemap", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2020-09-18 17:26:09.703215", - "modified_by": "Administrator", - "module": "Selling", - "name": "Product Bundle", - "owner": "Administrator", + ], + "icon": "fa fa-sitemap", + "idx": 1, + "links": [], + "modified": "2023-11-22 15:20:46.805114", + "modified_by": "Administrator", + "module": "Selling", + "name": "Product Bundle", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Stock Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Stock User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - }, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Stock User" + }, { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales User", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_order": "ASC", - "track_changes": 0, - "track_seen": 0 + ], + "sort_field": "modified", + "sort_order": "ASC", + "states": [] } \ No newline at end of file From 874774fe6c81c854fb3ade03e93f003c0fc8dd8a Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 15:24:56 +0530 Subject: [PATCH 082/202] fix: filter bundle items based on disabled check --- erpnext/stock/doctype/packed_item/packed_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index a9e9ad1a63..8b6f7158e0 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -111,7 +111,7 @@ def get_product_bundle_items(item_code): product_bundle_item.uom, product_bundle_item.description, ) - .where(product_bundle.new_item_code == item_code) + .where((product_bundle.new_item_code == item_code) & (product_bundle.disabled == 0)) .orderby(product_bundle_item.idx) ) return query.run(as_dict=True) From 627165dc7c6c1cd83d746b97c82210abeb9a2e29 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 15:26:45 +0530 Subject: [PATCH 083/202] fix: Supplier `Primary Contact` --- erpnext/buying/doctype/supplier/supplier.py | 27 +++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index 31bf439dbb..b052f564a4 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -165,16 +165,17 @@ class Supplier(TransactionBase): @frappe.validate_and_sanitize_search_inputs def get_supplier_primary_contact(doctype, txt, searchfield, start, page_len, filters): supplier = filters.get("supplier") - return frappe.db.sql( - """ - SELECT - `tabContact`.name from `tabContact`, - `tabDynamic Link` - WHERE - `tabContact`.name = `tabDynamic Link`.parent - and `tabDynamic Link`.link_name = %(supplier)s - and `tabDynamic Link`.link_doctype = 'Supplier' - and `tabContact`.name like %(txt)s - """, - {"supplier": supplier, "txt": "%%%s%%" % txt}, - ) + contact = frappe.qb.DocType("Contact") + dynamic_link = frappe.qb.DocType("Dynamic Link") + + return ( + frappe.qb.from_(contact) + .join(dynamic_link) + .on(contact.name == dynamic_link.parent) + .select(contact.name, contact.email_id) + .where( + (dynamic_link.link_name == supplier) + & (dynamic_link.link_doctype == "Supplier") + & (contact.name.like("%{0}%".format(txt))) + ) + ).run(as_dict=False) From 3543f86c639cf7383c37a5ed9a61d5787c9ebad4 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 16:04:05 +0530 Subject: [PATCH 084/202] fix: has_product_bundle util to only check for enabled bundles --- erpnext/controllers/selling_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index d34fbeb0da..c3211b1d1c 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -352,7 +352,7 @@ class SellingController(StockController): def has_product_bundle(self, item_code): return frappe.db.sql( """select name from `tabProduct Bundle` - where new_item_code=%s and docstatus != 2""", + where new_item_code=%s and disabled=0""", item_code, ) From 67f43d37df9e77c3e59562117fa44ea76273a536 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 16:10:49 +0530 Subject: [PATCH 085/202] fix: validation for existing bundles --- erpnext/selling/doctype/product_bundle/product_bundle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index 4b401e7e67..2fd9cc1301 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -64,7 +64,7 @@ class ProductBundle(Document): def validate_child_items(self): for item in self.items: - if frappe.db.exists("Product Bundle", item.item_code): + if frappe.db.exists("Product Bundle", {"name": item.item_code, "disabled": 0}): frappe.throw( _( "Row #{0}: Child Item should not be a Product Bundle. Please remove Item {1} and Save" @@ -75,7 +75,7 @@ class ProductBundle(Document): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def get_new_item_code(doctype, txt, searchfield, start, page_len, filters): - product_bundles = frappe.db.get_list("Product Bundle", pluck="name") + product_bundles = frappe.db.get_list("Product Bundle", {"disabled": 0}, pluck="name") item = frappe.qb.DocType("Item") return ( frappe.qb.from_(item) From 8bdb61cb87802723a0db1aaa29c30c15c740ec6b Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 16:17:23 +0530 Subject: [PATCH 086/202] fix: condition in other bundle utils --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 2 +- erpnext/selling/doctype/sales_order/sales_order.py | 8 +++++--- erpnext/stock/get_item_details.py | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index e36e97bc4b..9091a77f99 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -556,7 +556,7 @@ def get_stock_availability(item_code, warehouse): return bin_qty - pos_sales_qty, is_stock_item else: is_stock_item = True - if frappe.db.exists("Product Bundle", item_code): + if frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}): return get_bundle_availability(item_code, warehouse), is_stock_item else: is_stock_item = False diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index a97198aa78..a23599b180 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -688,7 +688,9 @@ def make_material_request(source_name, target_doc=None): "Sales Order Item": { "doctype": "Material Request Item", "field_map": {"name": "sales_order_item", "parent": "sales_order"}, - "condition": lambda item: not frappe.db.exists("Product Bundle", item.item_code) + "condition": lambda item: not frappe.db.exists( + "Product Bundle", {"name": item.item_code, "disabled": 0} + ) and get_remaining_qty(item) > 0, "postprocess": update_item, }, @@ -1309,7 +1311,7 @@ def set_delivery_date(items, sales_order): def is_product_bundle(item_code): - return frappe.db.exists("Product Bundle", item_code) + return frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}) @frappe.whitelist() @@ -1521,7 +1523,7 @@ def get_work_order_items(sales_order, for_raw_material_request=0): product_bundle_parents = [ pb.new_item_code for pb in frappe.get_all( - "Product Bundle", {"new_item_code": ["in", item_codes]}, ["new_item_code"] + "Product Bundle", {"new_item_code": ["in", item_codes], "disabled": 0}, ["new_item_code"] ) ] diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index c766cab0a1..d1a9cf26ac 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -149,7 +149,7 @@ def remove_standard_fields(details): def set_valuation_rate(out, args): - if frappe.db.exists("Product Bundle", args.item_code, cache=True): + if frappe.db.exists("Product Bundle", {"name": args.item_code, "disabled": 0}, cache=True): valuation_rate = 0.0 bundled_items = frappe.get_doc("Product Bundle", args.item_code) From 362f377f6127e9262ab7829a427d0a2051a77b2f Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 16:26:09 +0530 Subject: [PATCH 087/202] fix: skip disabled bundles for non-report utils --- erpnext/stock/doctype/delivery_note/delivery_note.py | 4 ++-- erpnext/stock/doctype/item/item.py | 8 ++++++-- erpnext/stock/doctype/packed_item/packed_item.py | 2 +- erpnext/stock/doctype/pick_list/pick_list.py | 8 ++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 66dd33a400..f240136e9c 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -615,7 +615,7 @@ class DeliveryNote(SellingController): items_list = [item.item_code for item in self.items] return frappe.db.get_all( "Product Bundle", - filters={"new_item_code": ["in", items_list]}, + filters={"new_item_code": ["in", items_list], "disabled": 0}, pluck="name", ) @@ -938,7 +938,7 @@ def make_packing_slip(source_name, target_doc=None): }, "postprocess": update_item, "condition": lambda item: ( - not frappe.db.exists("Product Bundle", {"new_item_code": item.item_code}) + not frappe.db.exists("Product Bundle", {"new_item_code": item.item_code, "disabled": 0}) and flt(item.packed_qty) < flt(item.qty) ), }, diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index d8935fe203..cb34497f28 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -512,8 +512,12 @@ class Item(Document): def validate_duplicate_product_bundles_before_merge(self, old_name, new_name): "Block merge if both old and new items have product bundles." - old_bundle = frappe.get_value("Product Bundle", filters={"new_item_code": old_name}) - new_bundle = frappe.get_value("Product Bundle", filters={"new_item_code": new_name}) + old_bundle = frappe.get_value( + "Product Bundle", filters={"new_item_code": old_name, "disabled": 0} + ) + new_bundle = frappe.get_value( + "Product Bundle", filters={"new_item_code": new_name, "disabled": 0} + ) if old_bundle and new_bundle: bundle_link = get_link_to_form("Product Bundle", old_bundle) diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 8b6f7158e0..35701c90de 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -55,7 +55,7 @@ def make_packing_list(doc): def is_product_bundle(item_code: str) -> bool: - return bool(frappe.db.exists("Product Bundle", {"new_item_code": item_code})) + return bool(frappe.db.exists("Product Bundle", {"new_item_code": item_code, "disabled": 0})) def get_indexed_packed_items_table(doc): diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index ed20209577..644df3d29a 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -368,7 +368,9 @@ class PickList(Document): frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx)) if not cint( frappe.get_cached_value("Item", item.item_code, "is_stock_item") - ) and not frappe.db.exists("Product Bundle", {"new_item_code": item.item_code}): + ) and not frappe.db.exists( + "Product Bundle", {"new_item_code": item.item_code, "disabled": 0} + ): continue item_code = item.item_code reference = item.sales_order_item or item.material_request_item @@ -507,7 +509,9 @@ class PickList(Document): # bundle_item_code: Dict[component, qty] product_bundle_qty_map = {} for bundle_item_code in bundles: - bundle = frappe.get_last_doc("Product Bundle", {"new_item_code": bundle_item_code}) + bundle = frappe.get_last_doc( + "Product Bundle", {"new_item_code": bundle_item_code, "disabled": 0} + ) product_bundle_qty_map[bundle_item_code] = {item.item_code: item.qty for item in bundle.items} return product_bundle_qty_map From 16573378870bb9c6e80f39e80fa43e5b2cc0a69f Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 16:45:14 +0530 Subject: [PATCH 088/202] chore: linting issues --- erpnext/controllers/selling_controller.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index c3211b1d1c..5575a24b35 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -350,11 +350,12 @@ class SellingController(StockController): return il def has_product_bundle(self, item_code): - return frappe.db.sql( - """select name from `tabProduct Bundle` - where new_item_code=%s and disabled=0""", - item_code, - ) + product_bundle = frappe.qb.DocType("Product Bundle") + return ( + frappe.qb.from_(product_bundle) + .select(product_bundle.name) + .where((product_bundle.new_item_code == item_code) & (product_bundle.disabled == 0)) + ).run() def get_already_delivered_qty(self, current_docname, so, so_detail): delivered_via_dn = frappe.db.sql( From 52305e3000decb84aad1a99557e13a0bb2b68ec4 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 18:38:33 +0530 Subject: [PATCH 089/202] fix: annual income and expenses in digest --- erpnext/accounts/utils.py | 3 +++ erpnext/setup/doctype/email_digest/email_digest.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 7d91309fcc..dbad2bacb6 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -183,6 +183,7 @@ def get_balance_on( cost_center=None, ignore_account_permission=False, account_type=None, + start_date=None, ): if not account and frappe.form_dict.get("account"): account = frappe.form_dict.get("account") @@ -196,6 +197,8 @@ def get_balance_on( cost_center = frappe.form_dict.get("cost_center") cond = ["is_cancelled=0"] + if start_date: + cond.append("posting_date >= %s" % frappe.db.escape(cstr(start_date))) if date: cond.append("posting_date <= %s" % frappe.db.escape(cstr(date))) else: diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 4fc20e6103..b9e225728e 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -382,9 +382,10 @@ class EmailDigest(Document): """Get income to date""" balance = 0.0 count = 0 + fy_start_date = get_fiscal_year().get("year_start_date") for account in self.get_root_type_accounts(root_type): - balance += get_balance_on(account, date=self.future_to_date) + balance += get_balance_on(account, date=self.future_to_date, start_date=fy_start_date) count += get_count_on(account, fieldname, date=self.future_to_date) if fieldname == "income": From 728cc9f725264e057d9331362b256ea8d0f80b83 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 22 Nov 2023 19:28:57 +0530 Subject: [PATCH 090/202] fix: fiscal year using future date --- erpnext/setup/doctype/email_digest/email_digest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index b9e225728e..6ed44fff68 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -382,7 +382,7 @@ class EmailDigest(Document): """Get income to date""" balance = 0.0 count = 0 - fy_start_date = get_fiscal_year().get("year_start_date") + fy_start_date = get_fiscal_year(self.future_to_date)[1] for account in self.get_root_type_accounts(root_type): balance += get_balance_on(account, date=self.future_to_date, start_date=fy_start_date) From f258ab5e98f323303276aeca98dcc644f6611a70 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 23 Nov 2023 10:39:41 +0530 Subject: [PATCH 091/202] chore: move reconciliation cleanup patch to pre-model --- erpnext/patches.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a71d71b83a..8e091d4a5d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -259,6 +259,7 @@ erpnext.patches.v14_0.update_reference_due_date_in_journal_entry erpnext.patches.v15_0.saudi_depreciation_warning erpnext.patches.v15_0.delete_saudi_doctypes erpnext.patches.v14_0.show_loan_management_deprecation_warning +erpnext.patches.v14_0.clear_reconciliation_values_from_singles execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Details", force=True) [post_model_sync] @@ -345,7 +346,6 @@ erpnext.patches.v15_0.update_sre_from_voucher_details erpnext.patches.v14_0.rename_over_order_allowance_field erpnext.patches.v14_0.migrate_delivery_stop_lock_field erpnext.patches.v14_0.add_default_for_repost_settings -erpnext.patches.v14_0.clear_reconciliation_values_from_singles erpnext.patches.v15_0.rename_daily_depreciation_to_depreciation_amount_based_on_num_days_in_month erpnext.patches.v15_0.rename_depreciation_amount_based_on_num_days_in_month_to_daily_prorata_based erpnext.patches.v15_0.set_reserved_stock_in_bin From 24fcd67f8bcf8cc8b387856983b97d8778eac084 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 23 Nov 2023 11:44:34 +0530 Subject: [PATCH 092/202] chore: index to speed up queries on JE child table reference --- .../journal_entry_account/journal_entry_account.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index 3ba8cea94b..3132fe9b12 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -203,7 +203,8 @@ "fieldtype": "Select", "label": "Reference Type", "no_copy": 1, - "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement\nPayment Entry" + "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nLoan\nPayroll Entry\nEmployee Advance\nExchange Rate Revaluation\nInvoice Discounting\nFees\nFull and Final Statement\nPayment Entry", + "search_index": 1 }, { "fieldname": "reference_name", @@ -211,7 +212,8 @@ "in_list_view": 1, "label": "Reference Name", "no_copy": 1, - "options": "reference_type" + "options": "reference_type", + "search_index": 1 }, { "depends_on": "eval:doc.reference_type&&!in_list(doc.reference_type, ['Expense Claim', 'Asset', 'Employee Loan', 'Employee Advance'])", @@ -278,13 +280,14 @@ "fieldtype": "Data", "hidden": 1, "label": "Reference Detail No", - "no_copy": 1 + "no_copy": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-06-16 14:11:13.507807", + "modified": "2023-11-23 11:44:25.841187", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", From 816b1b6bd52b4f6adcb35d4039ad75892b0976ff Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Thu, 23 Nov 2023 13:48:46 +0530 Subject: [PATCH 093/202] fix: don't depreciate assets with no schedule on scrapping (#38276) fix: don't depreciate non-depreciable assets on scrapping --- erpnext/assets/doctype/asset/depreciation.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 84a428ca54..66930c0e7c 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -509,6 +509,9 @@ def restore_asset(asset_name): def depreciate_asset(asset_doc, date, notes): + if not asset_doc.calculate_depreciation: + return + asset_doc.flags.ignore_validate_update_after_submit = True make_new_active_asset_depr_schedules_and_cancel_current_ones( @@ -521,6 +524,9 @@ def depreciate_asset(asset_doc, date, notes): def reset_depreciation_schedule(asset_doc, date, notes): + if not asset_doc.calculate_depreciation: + return + asset_doc.flags.ignore_validate_update_after_submit = True make_new_active_asset_depr_schedules_and_cancel_current_ones( From b206b0583b2998382c0ce1a63c867f09a6a0b03a Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Thu, 23 Nov 2023 15:10:47 +0530 Subject: [PATCH 094/202] fix: fetch item_tax_template values if fields with fetch_from exisit --- erpnext/controllers/accounts_controller.py | 1 + erpnext/public/js/controllers/transaction.js | 1 + erpnext/stock/get_item_details.py | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index d12d50d2e7..e68894fa77 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -625,6 +625,7 @@ class AccountsController(TransactionBase): args["doctype"] = self.doctype args["name"] = self.name + args["child_doctype"] = item.doctype args["child_docname"] = item.name args["ignore_pricing_rule"] = ( self.ignore_pricing_rule if hasattr(self, "ignore_pricing_rule") else 0 diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 2c40f4964b..6dc24faa96 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -512,6 +512,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe cost_center: item.cost_center, tax_category: me.frm.doc.tax_category, item_tax_template: item.item_tax_template, + child_doctype: item.doctype, child_docname: item.name, is_old_subcontracting_flow: me.frm.doc.is_old_subcontracting_flow, } diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index c766cab0a1..5143067f74 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -8,6 +8,7 @@ import frappe from frappe import _, throw from frappe.model import child_table_fields, default_fields from frappe.model.meta import get_field_precision +from frappe.model.utils import get_fetch_values from frappe.query_builder.functions import IfNull, Sum from frappe.utils import add_days, add_months, cint, cstr, flt, getdate @@ -571,6 +572,9 @@ def get_item_tax_template(args, item, out): item_tax_template = _get_item_tax_template(args, item_group_doc.taxes, out) item_group = item_group_doc.parent_item_group + if args.child_doctype and item_tax_template: + out.update(get_fetch_values(args.child_doctype, "item_tax_template", item_tax_template)) + def _get_item_tax_template(args, taxes, out=None, for_validate=False): if out is None: From 1efff268b036dd27f7472bc7ec494aafac9edbc8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 23 Nov 2023 16:56:35 +0530 Subject: [PATCH 095/202] chore: speed up Purchase Invoice cancellation --- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index d1677832ed..f2094874e0 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -1615,7 +1615,8 @@ "hide_seconds": 1, "label": "Inter Company Invoice Reference", "options": "Purchase Invoice", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "fieldname": "customer_group", @@ -2173,7 +2174,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2023-11-20 11:51:43.555197", + "modified": "2023-11-23 16:56:29.679499", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", From 628ea42b63217fcf64c9803fdfdad09c610b00c3 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 16:07:00 +0530 Subject: [PATCH 096/202] feat: add field `Action on Purchase Order Submission` --- .../doctype/buying_settings/buying_settings.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 059999245d..b20257cfb7 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -28,7 +28,9 @@ "subcontract", "backflush_raw_materials_of_subcontract_based_on", "column_break_11", - "over_transfer_allowance" + "over_transfer_allowance", + "section_break_xcug", + "purchase_order_submit_action" ], "fields": [ { @@ -172,6 +174,16 @@ "fieldname": "blanket_order_allowance", "fieldtype": "Float", "label": "Blanket Order Allowance (%)" + }, + { + "fieldname": "section_break_xcug", + "fieldtype": "Section Break" + }, + { + "fieldname": "purchase_order_submit_action", + "fieldtype": "Select", + "label": "Purchase Order Submit Action", + "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" } ], "icon": "fa fa-cog", @@ -179,7 +191,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-10-25 14:03:32.520418", + "modified": "2023-11-22 16:05:33.262940", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", From 9ec6f1e1d63ccb8087cb3f95c6a100b02d22ba79 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 17:06:19 +0530 Subject: [PATCH 097/202] feat: auto create SCO on PO submission --- .../buying_settings/buying_settings.json | 8 +++--- .../doctype/purchase_order/purchase_order.py | 26 +++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index b20257cfb7..2791e32730 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -30,7 +30,7 @@ "column_break_11", "over_transfer_allowance", "section_break_xcug", - "purchase_order_submit_action" + "action_on_purchase_order_submission" ], "fields": [ { @@ -180,9 +180,9 @@ "fieldtype": "Section Break" }, { - "fieldname": "purchase_order_submit_action", + "fieldname": "action_on_purchase_order_submission", "fieldtype": "Select", - "label": "Purchase Order Submit Action", + "label": "Action on Purchase Order Submission", "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" } ], @@ -191,7 +191,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-22 16:05:33.262940", + "modified": "2023-11-22 17:42:28.978582", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 961697c0ac..86a652b487 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -357,6 +357,8 @@ class PurchaseOrder(BuyingController): update_linked_doc(self.doctype, self.name, self.inter_company_order_reference) + self.auto_create_subcontracting_order() + def on_cancel(self): self.ignore_linked_doctypes = ("GL Entry", "Payment Ledger Entry") super(PurchaseOrder, self).on_cancel() @@ -484,6 +486,16 @@ class PurchaseOrder(BuyingController): return result + def auto_create_subcontracting_order(self): + if self.is_subcontracted and not self.is_old_subcontracting_flow: + if action := frappe.db.get_single_value( + "Buying Settings", "action_on_purchase_order_submission" + ): + if action == "Create Subcontracting Order": + make_subcontracting_order(self.name, save=True) + elif action == "Create and Submit Subcontracting Order": + make_subcontracting_order(self.name, submit=True) + def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): """get last purchase rate for an item""" @@ -686,8 +698,18 @@ def make_inter_company_sales_order(source_name, target_doc=None): @frappe.whitelist() -def make_subcontracting_order(source_name, target_doc=None): - return get_mapped_subcontracting_order(source_name, target_doc) +def make_subcontracting_order(source_name, target_doc=None, save=False, submit=False): + target_doc = get_mapped_subcontracting_order(source_name, target_doc) + + if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): + target_doc.save() + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): + try: + target_doc.submit() + except Exception as e: + target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + + return target_doc def get_mapped_subcontracting_order(source_name, target_doc=None): From 762906f24023af3f0fdba70c5dbf61951f45dd68 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 22 Nov 2023 17:47:49 +0530 Subject: [PATCH 098/202] feat: add field `Action on Subcontracting Receipt Submission` --- .../doctype/buying_settings/buying_settings.json | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 2791e32730..bb2476d8f2 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -30,7 +30,9 @@ "column_break_11", "over_transfer_allowance", "section_break_xcug", - "action_on_purchase_order_submission" + "action_on_purchase_order_submission", + "column_break_izrr", + "action_on_subcontracting_receipt_submission" ], "fields": [ { @@ -184,6 +186,16 @@ "fieldtype": "Select", "label": "Action on Purchase Order Submission", "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" + }, + { + "fieldname": "column_break_izrr", + "fieldtype": "Column Break" + }, + { + "fieldname": "action_on_subcontracting_receipt_submission", + "fieldtype": "Select", + "label": "Action on Subcontracting Receipt Submission", + "options": "\nCreate Purchase Receipt\nCreate and Submit Purchase Receipt" } ], "icon": "fa fa-cog", @@ -191,7 +203,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-22 17:42:28.978582", + "modified": "2023-11-22 17:46:26.474708", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", From 745e3bfb733bdbce034b9b1fb3cd83a502a423a7 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 11:40:46 +0530 Subject: [PATCH 099/202] chore: notify user on SCO creation --- .../doctype/purchase_order/purchase_order.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 86a652b487..5db048ee62 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -8,7 +8,7 @@ import frappe from frappe import _, msgprint from frappe.desk.notifications import clear_doctype_notifications from frappe.model.mapper import get_mapped_doc -from frappe.utils import cint, cstr, flt +from frappe.utils import cint, cstr, flt, get_link_to_form from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( unlink_inter_company_doc, @@ -492,9 +492,9 @@ class PurchaseOrder(BuyingController): "Buying Settings", "action_on_purchase_order_submission" ): if action == "Create Subcontracting Order": - make_subcontracting_order(self.name, save=True) + make_subcontracting_order(self.name, save=True, notify=True) elif action == "Create and Submit Subcontracting Order": - make_subcontracting_order(self.name, submit=True) + make_subcontracting_order(self.name, submit=True, notify=True) def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): @@ -698,17 +698,29 @@ def make_inter_company_sales_order(source_name, target_doc=None): @frappe.whitelist() -def make_subcontracting_order(source_name, target_doc=None, save=False, submit=False): +def make_subcontracting_order( + source_name, target_doc=None, save=False, submit=False, notify=False +): target_doc = get_mapped_subcontracting_order(source_name, target_doc) if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): target_doc.save() + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): try: target_doc.submit() except Exception as e: target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + if notify: + frappe.msgprint( + _("Subcontracting Order {0} created.").format( + get_link_to_form(target_doc.doctype, target_doc.name) + ), + indicator="green", + alert=True, + ) + return target_doc From 45d5cff47d7fc53fcf710afac281907ba9ab9e00 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 13:39:49 +0530 Subject: [PATCH 100/202] feat: add field `Purchase Order Item` in SCO Service Item --- .../subcontracting_order_service_item.json | 268 +++++++++--------- 1 file changed, 139 insertions(+), 129 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json index f213313ef6..dc18543b04 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json @@ -1,131 +1,141 @@ { - "actions": [], - "autoname": "hash", - "creation": "2022-04-01 19:23:05.728354", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "item_code", - "column_break_2", - "item_name", - "section_break_4", - "qty", - "column_break_6", - "rate", - "column_break_8", - "amount", - "section_break_10", - "fg_item", - "column_break_12", - "fg_item_qty" - ], - "fields": [ - { - "bold": 1, - "columns": 2, - "fieldname": "item_code", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Item Code", - "options": "Item", - "reqd": 1, - "search_index": 1 - }, - { - "fetch_from": "item_code.item_name", - "fieldname": "item_name", - "fieldtype": "Data", - "in_global_search": 1, - "in_list_view": 1, - "label": "Item Name", - "print_hide": 1, - "reqd": 1 - }, - { - "bold": 1, - "columns": 1, - "fieldname": "qty", - "fieldtype": "Float", - "in_list_view": 1, - "label": "Quantity", - "print_width": "60px", - "reqd": 1, - "width": "60px" - }, - { - "bold": 1, - "columns": 2, - "fetch_from": "item_code.standard_rate", - "fetch_if_empty": 1, - "fieldname": "rate", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Rate", - "options": "currency", - "reqd": 1 - }, - { - "columns": 2, - "fieldname": "amount", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Amount", - "options": "currency", - "read_only": 1, - "reqd": 1 - }, - { - "fieldname": "fg_item", - "fieldtype": "Link", - "label": "Finished Good Item", - "options": "Item", - "reqd": 1 - }, - { - "default": "1", - "fieldname": "fg_item_qty", - "fieldtype": "Float", - "label": "Finished Good Item Quantity", - "reqd": 1 - }, - { - "fieldname": "column_break_2", - "fieldtype": "Column Break" - }, - { - "fieldname": "section_break_4", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_6", - "fieldtype": "Column Break" - }, - { - "fieldname": "column_break_8", - "fieldtype": "Column Break" - }, - { - "fieldname": "section_break_10", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_12", - "fieldtype": "Column Break" - } - ], - "istable": 1, - "links": [], - "modified": "2022-04-07 11:43:43.094867", - "modified_by": "Administrator", - "module": "Subcontracting", - "name": "Subcontracting Order Service Item", - "naming_rule": "Random", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "search_fields": "item_name", - "sort_field": "modified", - "sort_order": "DESC", - "states": [] + "actions": [], + "autoname": "hash", + "creation": "2022-04-01 19:23:05.728354", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "item_code", + "column_break_2", + "item_name", + "section_break_4", + "qty", + "column_break_6", + "rate", + "column_break_8", + "amount", + "section_break_10", + "fg_item", + "column_break_12", + "fg_item_qty", + "purchase_order_item" + ], + "fields": [ + { + "bold": 1, + "columns": 2, + "fieldname": "item_code", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Item Code", + "options": "Item", + "reqd": 1, + "search_index": 1 + }, + { + "fetch_from": "item_code.item_name", + "fieldname": "item_name", + "fieldtype": "Data", + "in_global_search": 1, + "in_list_view": 1, + "label": "Item Name", + "print_hide": 1, + "reqd": 1 + }, + { + "bold": 1, + "columns": 1, + "fieldname": "qty", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Quantity", + "print_width": "60px", + "reqd": 1, + "width": "60px" + }, + { + "bold": 1, + "columns": 2, + "fetch_from": "item_code.standard_rate", + "fetch_if_empty": 1, + "fieldname": "rate", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Rate", + "options": "currency", + "reqd": 1 + }, + { + "columns": 2, + "fieldname": "amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Amount", + "options": "currency", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "fg_item", + "fieldtype": "Link", + "label": "Finished Good Item", + "options": "Item", + "reqd": 1 + }, + { + "default": "1", + "fieldname": "fg_item_qty", + "fieldtype": "Float", + "label": "Finished Good Item Quantity", + "reqd": 1 + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_10", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, + { + "fieldname": "purchase_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Purchase Order Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 + } + ], + "istable": 1, + "links": [], + "modified": "2023-11-23 17:05:04.561948", + "modified_by": "Administrator", + "module": "Subcontracting", + "name": "Subcontracting Order Service Item", + "naming_rule": "Random", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "search_fields": "item_name", + "sort_field": "modified", + "sort_order": "DESC", + "states": [] } \ No newline at end of file From 7e4dd33ab0da2800fdb4aeb89ef9d183bff19d4d Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 13:40:41 +0530 Subject: [PATCH 101/202] fix: hold PO item ref in SCO Service Item --- erpnext/buying/doctype/purchase_order/purchase_order.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 5db048ee62..7f764e939e 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -747,7 +747,9 @@ def get_mapped_subcontracting_order(source_name, target_doc=None): }, "Purchase Order Item": { "doctype": "Subcontracting Order Service Item", - "field_map": {}, + "field_map": { + "name": "purchase_order_item", + }, "field_no_map": [], }, }, From a2ede7d6d5241665d996447a1c9e2d1447190066 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 16:59:42 +0530 Subject: [PATCH 102/202] feat: add field `Purchase Order Item` in SCO Item --- .../subcontracting_order/subcontracting_order.py | 13 +++++-------- .../subcontracting_order_item.json | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index faf0cadb75..376a936e68 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -123,8 +123,6 @@ class SubcontractingOrder(SubcontractingController): stock_bin.update_reserved_qty_for_sub_contracting() def populate_items_table(self): - items = [] - for si in self.service_items: if si.fg_item: item = frappe.get_doc("Item", si.fg_item) @@ -134,7 +132,8 @@ class SubcontractingOrder(SubcontractingController): ) or item.default_bom ) - items.append( + self.append( + "items", { "item_code": item.item_code, "item_name": item.item_name, @@ -143,6 +142,7 @@ class SubcontractingOrder(SubcontractingController): "qty": si.fg_item_qty, "stock_uom": item.stock_uom, "bom": bom, + "purchase_order_item": si.purchase_order_item, }, ) else: @@ -151,11 +151,8 @@ class SubcontractingOrder(SubcontractingController): si.item_name or si.item_code ) ) - else: - for item in items: - self.append("items", item) - else: - self.set_missing_values() + + self.set_missing_values() def update_status(self, status=None, update_modified=True): if self.docstatus >= 1 and not status: diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json index 46c229bfd3..911e903d23 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -45,7 +45,8 @@ "dimension_col_break", "project", "section_break_34", - "page_break" + "page_break", + "purchase_order_item" ], "fields": [ { @@ -332,13 +333,22 @@ "fieldtype": "Link", "label": "Project", "options": "Project" + }, + { + "fieldname": "purchase_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Purchase Order Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:38:37.640677", + "modified": "2023-11-23 16:56:22.182698", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Item", From e1cea2578151ee0f43e1809a7f99d2e90bf774a6 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 17:48:34 +0530 Subject: [PATCH 103/202] fix: maintain PO and PO Item ref in SCR Item --- .../subcontracting_order.py | 8 +++--- .../subcontracting_receipt_item.json | 25 +++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 376a936e68..cc99085486 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -194,9 +194,11 @@ def make_subcontracting_receipt(source_name, target_doc=None): def get_mapped_subcontracting_receipt(source_name, target_doc=None): - def update_item(obj, target, source_parent): - target.qty = flt(obj.qty) - flt(obj.received_qty) - target.amount = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.rate) + def update_item(source, target, source_parent): + target.purchase_order = source_parent.purchase_order + target.purchase_order_item = source.purchase_order_item + target.qty = flt(source.qty) - flt(source.received_qty) + target.amount = (flt(source.qty) - flt(source.received_qty)) * flt(source.rate) target_doc = get_mapped_doc( "Subcontracting Order", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json index 26a29dd811..35a79a9308 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json @@ -63,7 +63,9 @@ "dimension_col_break", "project", "section_break_80", - "page_break" + "page_break", + "purchase_order", + "purchase_order_item" ], "fields": [ { @@ -517,12 +519,31 @@ "label": "Reference Name", "no_copy": 1, "read_only": 1 + }, + { + "fieldname": "purchase_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Purchase Order Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 + }, + { + "fieldname": "purchase_order", + "fieldtype": "Link", + "hidden": 1, + "label": "Purchase Order", + "no_copy": 1, + "options": "Purchase Order", + "read_only": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:38:26.459669", + "modified": "2023-11-23 17:38:55.134685", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Receipt Item", From 3be345e6056f36baa6eef75818a7cdc63826b5f8 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Thu, 23 Nov 2023 14:02:27 +0100 Subject: [PATCH 104/202] feat: add Bank Transaction to connections in Journal and Payment Entry (#38297) * feat(Payment Entry): Bank Transaction connection * feat(Journal Entry): Bank Transaction connection --- .../doctype/journal_entry/journal_entry.json | 12 ++++++++++-- .../doctype/payment_entry/payment_entry.json | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json index 2eb54a54d5..906760ec31 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.json +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json @@ -548,8 +548,16 @@ "icon": "fa fa-file-text", "idx": 176, "is_submittable": 1, - "links": [], - "modified": "2023-08-10 14:32:22.366895", + "links": [ + { + "is_child_table": 1, + "link_doctype": "Bank Transaction Payments", + "link_fieldname": "payment_entry", + "parent_doctype": "Bank Transaction", + "table_fieldname": "payment_entries" + } + ], + "modified": "2023-11-23 12:11:04.128015", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 4d50a35ed4..aa181564b0 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -750,8 +750,16 @@ ], "index_web_pages_for_search": 1, "is_submittable": 1, - "links": [], - "modified": "2023-11-08 21:51:03.482709", + "links": [ + { + "is_child_table": 1, + "link_doctype": "Bank Transaction Payments", + "link_fieldname": "payment_entry", + "parent_doctype": "Bank Transaction", + "table_fieldname": "payment_entries" + } + ], + "modified": "2023-11-23 12:07:20.887885", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", From 040cc8d22f700a1823425d1534b91d50289d2489 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 23 Nov 2023 22:16:27 +0530 Subject: [PATCH 105/202] feat: auto create PR on SCR submission --- .../subcontracting_receipt.py | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 8d705aa97d..a38acb27d4 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -3,7 +3,8 @@ import frappe from frappe import _ -from frappe.utils import cint, flt, getdate, nowdate +from frappe.model.mapper import get_mapped_doc +from frappe.utils import cint, flt, get_link_to_form, getdate, nowdate import erpnext from erpnext.accounts.utils import get_account_currency @@ -80,6 +81,7 @@ class SubcontractingReceipt(SubcontractingController): self.make_gl_entries() self.repost_future_sle_and_gle() self.update_status() + self.auto_create_purchase_receipt() def on_update(self): for table_field in ["items", "supplied_items"]: @@ -528,9 +530,96 @@ class SubcontractingReceipt(SubcontractingController): + "\n".join(warehouse_with_no_account) ) + def auto_create_purchase_receipt(self): + if action := frappe.db.get_single_value( + "Buying Settings", "action_on_subcontracting_receipt_submission" + ): + if action == "Create Purchase Receipt": + make_purchase_receipt(self, save=True, notify=True) + elif action == "Create and Submit Purchase Receipt": + make_purchase_receipt(self, submit=True, notify=True) + @frappe.whitelist() def make_subcontract_return(source_name, target_doc=None): from erpnext.controllers.sales_and_purchase_return import make_return_doc return make_return_doc("Subcontracting Receipt", source_name, target_doc) + + +def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, notify=False): + if isinstance(subcontracting_receipt, str): + subcontracting_receipt = frappe.get_doc("Subcontracting Receipt", subcontracting_receipt) + + if not subcontracting_receipt.is_return: + purchase_receipt = frappe.new_doc("Purchase Receipt") + purchase_receipt.is_subcontracted = 1 + purchase_receipt.is_old_subcontracting_flow = 0 + + purchase_receipt = get_mapped_doc( + "Subcontracting Receipt", + subcontracting_receipt.name, + { + "Subcontracting Receipt": { + "doctype": "Purchase Receipt", + "field_map": { + "posting_date": "posting_date", + "posting_time": "posting_time", + "supplier_warehouse": "supplier_warehouse", + }, + "field_no_map": ["total_qty", "total"], + }, + }, + purchase_receipt, + ignore_child_tables=True, + ) + + po_items_details = {} + for item in subcontracting_receipt.items: + if item.purchase_order and item.purchase_order_item: + if item.purchase_order not in po_items_details: + po_doc = frappe.get_doc("Purchase Order", item.purchase_order) + po_items_details[item.purchase_order] = {po_item.name: po_item for po_item in po_doc.items} + + if po_item := po_items_details[item.purchase_order].get(item.purchase_order_item): + conversion_factor = flt(po_item.qty) / flt(po_item.fg_item_qty) + item_row = { + "item_code": po_item.item_code, + "item_name": po_item.item_name, + "qty": item.qty * conversion_factor, + "rejected_qty": item.rejected_qty * conversion_factor, + "uom": po_item.uom, + "rate": po_item.rate, + "warehouse": item.warehouse, + "rejected_warehouse": item.rejected_warehouse, + "purchase_order": item.purchase_order, + "purchase_order_item": item.purchase_order_item, + } + purchase_receipt.append("items", item_row) + + if not purchase_receipt.items: + frappe.throw( + _("Purchase Order Item reference is missing in Subcontracting Receipt {0}").format( + subcontracting_receipt.name + ) + ) + + if (save or submit) and frappe.has_permission(purchase_receipt.doctype, "create"): + purchase_receipt.save() + + if submit and frappe.has_permission(purchase_receipt.doctype, "submit", purchase_receipt): + try: + purchase_receipt.submit() + except Exception as e: + purchase_receipt.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + + if notify: + frappe.msgprint( + _("Purchase Receipt {0} created.").format( + get_link_to_form(purchase_receipt.doctype, purchase_receipt.name) + ), + indicator="green", + alert=True, + ) + + return purchase_receipt From 64b44a360af8c2d3a6a9cb99e03358b97cdf9fa5 Mon Sep 17 00:00:00 2001 From: NandhiniDevi <95607404+Nandhinidevi123@users.noreply.github.com> Date: Thu, 23 Nov 2023 22:40:17 +0530 Subject: [PATCH 106/202] add flt() for None type error (#38299) --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 85ef6f76d2..1cff4c7f2d 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -868,7 +868,7 @@ class JournalEntry(AccountsController): party_account_currency = d.account_currency elif frappe.get_cached_value("Account", d.account, "account_type") in ["Bank", "Cash"]: - bank_amount += d.debit_in_account_currency or d.credit_in_account_currency + bank_amount += flt(d.debit_in_account_currency) or flt(d.credit_in_account_currency) bank_account_currency = d.account_currency if party_type and pay_to_recd_from: From 3f6d80503335a33bf2bff53a19870a6cdba00044 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Thu, 23 Nov 2023 12:12:12 -0500 Subject: [PATCH 107/202] fix: display all item rate stop messages (#38289) --- erpnext/utilities/transaction_base.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 7eba35dedd..b083614a5f 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -98,6 +98,7 @@ class TransactionBase(StatusUpdater): "Selling Settings", "None", ["maintain_same_rate_action", "role_to_override_stop_action"] ) + stop_actions = [] for ref_dt, ref_dn_field, ref_link_field in ref_details: reference_names = [d.get(ref_link_field) for d in self.get("items") if d.get(ref_link_field)] reference_details = self.get_reference_details(reference_names, ref_dt + " Item") @@ -108,7 +109,7 @@ class TransactionBase(StatusUpdater): if abs(flt(d.rate - ref_rate, d.precision("rate"))) >= 0.01: if action == "Stop": if role_allowed_to_override not in frappe.get_roles(): - frappe.throw( + stop_actions.append( _("Row #{0}: Rate must be same as {1}: {2} ({3} / {4})").format( d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate ) @@ -121,6 +122,8 @@ class TransactionBase(StatusUpdater): title=_("Warning"), indicator="orange", ) + if stop_actions: + frappe.throw(stop_actions, as_list=True) def get_reference_details(self, reference_names, reference_doctype): return frappe._dict( From aa17110bde44603574d4532afaa6cf1181423ac5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 23 Nov 2023 17:39:48 +0530 Subject: [PATCH 108/202] perf: optimize total_purchase_cost update --- .../purchase_invoice/purchase_invoice.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index d7c2361b4d..e83525dbac 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1281,13 +1281,21 @@ class PurchaseInvoice(BuyingController): self.update_advance_tax_references(cancel=1) def update_project(self): - project_list = [] + projects = frappe._dict() for d in self.items: - if d.project and d.project not in project_list: - project = frappe.get_doc("Project", d.project) - project.update_purchase_costing() - project.db_update() - project_list.append(d.project) + if d.project: + if self.docstatus == 1: + projects[d.project] = projects.get(d.project, 0) + d.base_net_amount + elif self.docstatus == 2: + projects[d.project] = projects.get(d.project, 0) - d.base_net_amount + + pj = frappe.qb.DocType("Project") + for proj, value in projects.items(): + res = ( + frappe.qb.from_(pj).select(pj.total_purchase_cost).where(pj.name == proj).for_update().run() + ) + current_purchase_cost = res and res[0][0] or 0 + frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value) def validate_supplier_invoice(self): if self.bill_date: From f09c5f32cf4bd80dabb030d5910a2290365805ec Mon Sep 17 00:00:00 2001 From: NandhiniDevi <95607404+Nandhinidevi123@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:17:35 +0530 Subject: [PATCH 109/202] add flt() for None type error --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 34a753f267..1dbde93d20 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -489,7 +489,7 @@ class JournalEntry(AccountsController): ).format(d.reference_name, d.account) ) else: - dr_or_cr = "debit" if d.credit > 0 else "credit" + dr_or_cr = "debit" if flt(d.credit) > 0 else "credit" valid = False for jvd in against_entries: if flt(jvd[dr_or_cr]) > 0: From bcbe6c4a531986836a0a2497e05bdbe1a327407a Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 23 Nov 2023 17:53:42 +0530 Subject: [PATCH 110/202] refactor: provide UI button to recalculate when needed --- erpnext/projects/doctype/project/project.js | 20 +++++++++++ erpnext/projects/doctype/project/project.py | 37 ++++++++++++++++----- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index f366f77556..2dac399d88 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -68,6 +68,10 @@ frappe.ui.form.on("Project", { frm.events.create_duplicate(frm); }, __("Actions")); + frm.add_custom_button(__('Update Total Purchase Cost'), () => { + frm.events.update_total_purchase_cost(frm); + }, __("Actions")); + frm.trigger("set_project_status_button"); @@ -92,6 +96,22 @@ frappe.ui.form.on("Project", { }, + update_total_purchase_cost: function(frm) { + frappe.call({ + method: "erpnext.projects.doctype.project.project.recalculate_project_total_purchase_cost", + args: {project: frm.doc.name}, + freeze: true, + freeze_message: __('Recalculating Purchase Cost against this Project...'), + callback: function(r) { + if (r && !r.exc) { + frappe.msgprint(__('Total Purchase Cost has been updated')); + frm.refresh(); + } + } + + }); + }, + set_project_status_button: function(frm) { frm.add_custom_button(__('Set Project Status'), () => { let d = new frappe.ui.Dialog({ diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index e9aed1afb4..4f2e39539d 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -4,11 +4,11 @@ import frappe from email_reply_parser import EmailReplyParser -from frappe import _ +from frappe import _, qb from frappe.desk.reportview import get_match_cond from frappe.model.document import Document from frappe.query_builder import Interval -from frappe.query_builder.functions import Count, CurDate, Date, UnixTimestamp +from frappe.query_builder.functions import Count, CurDate, Date, Sum, UnixTimestamp from frappe.utils import add_days, flt, get_datetime, get_time, get_url, nowtime, today from frappe.utils.user import is_website_user @@ -249,12 +249,7 @@ class Project(Document): self.per_gross_margin = (self.gross_margin / flt(self.total_billed_amount)) * 100 def update_purchase_costing(self): - total_purchase_cost = frappe.db.sql( - """select sum(base_net_amount) - from `tabPurchase Invoice Item` where project = %s and docstatus=1""", - self.name, - ) - + total_purchase_cost = calculate_total_purchase_cost(self.name) self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0 def update_sales_amount(self): @@ -695,3 +690,29 @@ def get_holiday_list(company=None): def get_users_email(doc): return [d.email for d in doc.users if frappe.db.get_value("User", d.user, "enabled")] + + +def calculate_total_purchase_cost(project: str | None = None): + if project: + pitem = qb.DocType("Purchase Invoice Item") + frappe.qb.DocType("Purchase Invoice Item") + total_purchase_cost = ( + qb.from_(pitem) + .select(Sum(pitem.base_net_amount)) + .where((pitem.project == project) & (pitem.docstatus == 1)) + .run(as_list=True) + ) + return total_purchase_cost + return None + + +@frappe.whitelist() +def recalculate_project_total_purchase_cost(project: str | None = None): + if project: + total_purchase_cost = calculate_total_purchase_cost(project) + frappe.db.set_value( + "Project", + project, + "total_purchase_cost", + (total_purchase_cost and total_purchase_cost[0][0] or 0), + ) From 0fe6dcd74288d5f2df1ffc37485e22ee96329b9e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 24 Nov 2023 10:53:00 +0530 Subject: [PATCH 111/202] refactor: make update_project_cost optional through Buying Settings --- .../doctype/buying_settings/buying_settings.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 059999245d..0af93bfc90 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -17,6 +17,7 @@ "po_required", "pr_required", "blanket_order_allowance", + "project_update_frequency", "column_break_12", "maintain_same_rate", "set_landed_cost_based_on_purchase_invoice_rate", @@ -172,6 +173,14 @@ "fieldname": "blanket_order_allowance", "fieldtype": "Float", "label": "Blanket Order Allowance (%)" + }, + { + "default": "Each Transaction", + "description": "How often should Project be updated of Total Purchase Cost ?", + "fieldname": "project_update_frequency", + "fieldtype": "Select", + "label": "Update frequency of Project", + "options": "Each Transaction\nManual" } ], "icon": "fa fa-cog", @@ -179,7 +188,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-10-25 14:03:32.520418", + "modified": "2023-11-24 10:55:51.287327", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", From dd016e6ced432b6f8754042fbad808b1cba56cec Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 24 Nov 2023 10:54:31 +0530 Subject: [PATCH 112/202] refactor: update project costing based on frequency --- .../doctype/purchase_invoice/purchase_invoice.py | 11 +++++++++-- erpnext/patches.txt | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index e83525dbac..c6ae9377a0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -527,7 +527,11 @@ class PurchaseInvoice(BuyingController): if self.update_stock == 1: self.repost_future_sle_and_gle() - self.update_project() + if ( + frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction" + ): + self.update_project() + update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference) self.update_advance_tax_references() @@ -1262,7 +1266,10 @@ class PurchaseInvoice(BuyingController): if self.update_stock == 1: self.repost_future_sle_and_gle() - self.update_project() + if ( + frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction" + ): + self.update_project() self.db_set("status", "Cancelled") unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a71d71b83a..4991b48216 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -351,5 +351,6 @@ erpnext.patches.v15_0.rename_depreciation_amount_based_on_num_days_in_month_to_d erpnext.patches.v15_0.set_reserved_stock_in_bin erpnext.patches.v14_0.create_accounting_dimensions_in_supplier_quotation erpnext.patches.v14_0.update_zero_asset_quantity_field +execute:frappe.db.set_single_value("Buying Settings", "project_update_frequency", "Each Transaction") # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger From ca8a5b45ba58b62cd661dae508af9b0e26ff7973 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 24 Nov 2023 12:09:09 +0530 Subject: [PATCH 113/202] feat: add `Purchase Order` link in SCR connections --- .../subcontracting_receipt_dashboard.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py index deb8342b83..f6e1356ed9 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py @@ -9,11 +9,15 @@ def get_data(): }, "internal_links": { "Subcontracting Order": ["items", "subcontracting_order"], + "Purchase Order": ["items", "purchase_order"], "Project": ["items", "project"], "Quality Inspection": ["items", "quality_inspection"], }, "transactions": [ - {"label": _("Reference"), "items": ["Subcontracting Order", "Quality Inspection", "Project"]}, + { + "label": _("Reference"), + "items": ["Subcontracting Order", "Purchase Order", "Quality Inspection", "Project"], + }, {"label": _("Returns"), "items": ["Subcontracting Receipt"]}, ], } From 98cba5ed30ed2c8f5191d7cfaac54b16997cf09e Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 24 Nov 2023 12:14:38 +0530 Subject: [PATCH 114/202] feat: add `Subcontracting Receipt` link in PO connections --- .../doctype/purchase_order/purchase_order_dashboard.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py index 05b5a8e7b8..36fe079fc9 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order_dashboard.py @@ -22,7 +22,10 @@ def get_data(): "label": _("Reference"), "items": ["Material Request", "Supplier Quotation", "Project", "Auto Repeat"], }, - {"label": _("Sub-contracting"), "items": ["Subcontracting Order", "Stock Entry"]}, + { + "label": _("Sub-contracting"), + "items": ["Subcontracting Order", "Subcontracting Receipt", "Stock Entry"], + }, {"label": _("Internal"), "items": ["Sales Order"]}, ], } From dd80d3b9b94c970d5070e1a5fac03cf9f1fbc455 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 24 Nov 2023 12:17:05 +0530 Subject: [PATCH 115/202] fix: dont show `View` button on cancelled SCR --- .../doctype/subcontracting_receipt/subcontracting_receipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 36001eb78f..5585a4a84b 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -24,7 +24,7 @@ frappe.ui.form.on('Subcontracting Receipt', { }, refresh: (frm) => { - if (frm.doc.docstatus > 0) { + if (frm.doc.docstatus === 1) { frm.add_custom_button(__('Stock Ledger'), () => { frappe.route_options = { voucher_no: frm.doc.name, From 86aeacf3936cdf2e792c458ef7b281e2764a48f6 Mon Sep 17 00:00:00 2001 From: NandhiniDevi <95607404+Nandhinidevi123@users.noreply.github.com> Date: Fri, 24 Nov 2023 14:18:44 +0530 Subject: [PATCH 116/202] add condition --- .../chart_of_accounts_importer/chart_of_accounts_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py index d6e1be4123..8dd0da9797 100644 --- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py +++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py @@ -112,7 +112,7 @@ def generate_data_from_csv(file_doc, as_dict=False): if as_dict: data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)}) else: - if not row[1]: + if not row[1] and len(row) > 1: row[1] = row[0] row[3] = row[2] data.append(row) From 477d9fa87e3cd7476f19930d60d23e347e46e658 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Fri, 24 Nov 2023 22:27:01 +0100 Subject: [PATCH 117/202] feat: new Report "Lost Quotations" (#38309) --- .../crm/doctype/competitor/competitor.json | 13 +- .../report/lost_quotations/__init__.py | 0 .../report/lost_quotations/lost_quotations.js | 40 ++++++ .../lost_quotations/lost_quotations.json | 30 +++++ .../report/lost_quotations/lost_quotations.py | 98 ++++++++++++++ .../quotation_lost_reason.json | 123 +++++++----------- 6 files changed, 228 insertions(+), 76 deletions(-) create mode 100644 erpnext/selling/report/lost_quotations/__init__.py create mode 100644 erpnext/selling/report/lost_quotations/lost_quotations.js create mode 100644 erpnext/selling/report/lost_quotations/lost_quotations.json create mode 100644 erpnext/selling/report/lost_quotations/lost_quotations.py diff --git a/erpnext/crm/doctype/competitor/competitor.json b/erpnext/crm/doctype/competitor/competitor.json index 280441f16f..fd6da23921 100644 --- a/erpnext/crm/doctype/competitor/competitor.json +++ b/erpnext/crm/doctype/competitor/competitor.json @@ -29,8 +29,16 @@ } ], "index_web_pages_for_search": 1, - "links": [], - "modified": "2021-10-21 12:43:59.106807", + "links": [ + { + "is_child_table": 1, + "link_doctype": "Competitor Detail", + "link_fieldname": "competitor", + "parent_doctype": "Quotation", + "table_fieldname": "competitors" + } + ], + "modified": "2023-11-23 19:33:54.284279", "modified_by": "Administrator", "module": "CRM", "name": "Competitor", @@ -64,5 +72,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/selling/report/lost_quotations/__init__.py b/erpnext/selling/report/lost_quotations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/selling/report/lost_quotations/lost_quotations.js b/erpnext/selling/report/lost_quotations/lost_quotations.js new file mode 100644 index 0000000000..78e76cbf02 --- /dev/null +++ b/erpnext/selling/report/lost_quotations/lost_quotations.js @@ -0,0 +1,40 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.query_reports["Lost Quotations"] = { + filters: [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company"), + }, + { + label: "Timespan", + fieldtype: "Select", + fieldname: "timespan", + options: [ + "Last Week", + "Last Month", + "Last Quarter", + "Last 6 months", + "Last Year", + "This Week", + "This Month", + "This Quarter", + "This Year", + ], + default: "This Year", + reqd: 1, + }, + { + fieldname: "group_by", + label: __("Group By"), + fieldtype: "Select", + options: ["Lost Reason", "Competitor"], + default: "Lost Reason", + reqd: 1, + }, + ], +}; diff --git a/erpnext/selling/report/lost_quotations/lost_quotations.json b/erpnext/selling/report/lost_quotations/lost_quotations.json new file mode 100644 index 0000000000..8915bab595 --- /dev/null +++ b/erpnext/selling/report/lost_quotations/lost_quotations.json @@ -0,0 +1,30 @@ +{ + "add_total_row": 0, + "columns": [], + "creation": "2023-11-23 18:00:19.141922", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "letter_head": null, + "letterhead": null, + "modified": "2023-11-23 19:27:28.854108", + "modified_by": "Administrator", + "module": "Selling", + "name": "Lost Quotations", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Quotation", + "report_name": "Lost Quotations", + "report_type": "Script Report", + "roles": [ + { + "role": "Sales User" + }, + { + "role": "Sales Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/selling/report/lost_quotations/lost_quotations.py b/erpnext/selling/report/lost_quotations/lost_quotations.py new file mode 100644 index 0000000000..7c0bfbdd52 --- /dev/null +++ b/erpnext/selling/report/lost_quotations/lost_quotations.py @@ -0,0 +1,98 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from typing import Literal + +import frappe +from frappe import _ +from frappe.model.docstatus import DocStatus +from frappe.query_builder.functions import Coalesce, Count, Round, Sum +from frappe.utils.data import get_timespan_date_range + + +def execute(filters=None): + columns = get_columns(filters.get("group_by")) + from_date, to_date = get_timespan_date_range(filters.get("timespan").lower()) + data = get_data(filters.get("company"), from_date, to_date, filters.get("group_by")) + return columns, data + + +def get_columns(group_by: Literal["Lost Reason", "Competitor"]): + return [ + { + "fieldname": "lost_reason" if group_by == "Lost Reason" else "competitor", + "label": _("Lost Reason") if group_by == "Lost Reason" else _("Competitor"), + "fieldtype": "Link", + "options": "Quotation Lost Reason" if group_by == "Lost Reason" else "Competitor", + "width": 200, + }, + { + "filedname": "lost_quotations", + "label": _("Lost Quotations"), + "fieldtype": "Int", + "width": 150, + }, + { + "filedname": "lost_quotations_pct", + "label": _("Lost Quotations %"), + "fieldtype": "Percent", + "width": 200, + }, + { + "fieldname": "lost_value", + "label": _("Lost Value"), + "fieldtype": "Currency", + "width": 150, + }, + { + "filedname": "lost_value_pct", + "label": _("Lost Value %"), + "fieldtype": "Percent", + "width": 200, + }, + ] + + +def get_data( + company: str, from_date: str, to_date: str, group_by: Literal["Lost Reason", "Competitor"] +): + """Return quotation value grouped by lost reason or competitor""" + if group_by == "Lost Reason": + fieldname = "lost_reason" + dimension = frappe.qb.DocType("Quotation Lost Reason Detail") + elif group_by == "Competitor": + fieldname = "competitor" + dimension = frappe.qb.DocType("Competitor Detail") + else: + frappe.throw(_("Invalid Group By")) + + q = frappe.qb.DocType("Quotation") + + lost_quotation_condition = ( + (q.status == "Lost") + & (q.docstatus == DocStatus.submitted()) + & (q.transaction_date >= from_date) + & (q.transaction_date <= to_date) + & (q.company == company) + ) + + from_lost_quotations = frappe.qb.from_(q).where(lost_quotation_condition) + total_quotations = from_lost_quotations.select(Count(q.name)) + total_value = from_lost_quotations.select(Sum(q.base_net_total)) + + query = ( + frappe.qb.from_(q) + .select( + Coalesce(dimension[fieldname], _("Not Specified")), + Count(q.name).distinct(), + Round((Count(q.name).distinct() / total_quotations * 100), 2), + Sum(q.base_net_total), + Round((Sum(q.base_net_total) / total_value * 100), 2), + ) + .left_join(dimension) + .on(dimension.parent == q.name) + .where(lost_quotation_condition) + .groupby(dimension[fieldname]) + ) + + return query.run() diff --git a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json index 5d778eec0b..0eae08e870 100644 --- a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json +++ b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json @@ -1,83 +1,58 @@ { - "allow_copy": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "field:order_lost_reason", - "beta": 0, - "creation": "2013-01-10 16:34:24", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, + "actions": [], + "allow_import": 1, + "autoname": "field:order_lost_reason", + "creation": "2013-01-10 16:34:24", + "doctype": "DocType", + "document_type": "Setup", + "engine": "InnoDB", + "field_order": [ + "order_lost_reason" + ], "fields": [ { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "order_lost_reason", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Quotation Lost Reason", - "length": 0, - "no_copy": 0, - "oldfieldname": "order_lost_reason", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "fieldname": "order_lost_reason", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Quotation Lost Reason", + "oldfieldname": "order_lost_reason", + "oldfieldtype": "Data", + "reqd": 1, + "unique": 1 } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-flag", - "idx": 1, - "image_view": 0, - "in_create": 0, - - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2016-07-25 05:24:25.533953", - "modified_by": "Administrator", - "module": "Setup", - "name": "Quotation Lost Reason", - "owner": "Administrator", + ], + "icon": "fa fa-flag", + "idx": 1, + "links": [ + { + "is_child_table": 1, + "link_doctype": "Quotation Lost Reason Detail", + "link_fieldname": "lost_reason", + "parent_doctype": "Quotation", + "table_fieldname": "lost_reasons" + } + ], + "modified": "2023-11-23 19:31:02.743353", + "modified_by": "Administrator", + "module": "Setup", + "name": "Quotation Lost Reason", + "naming_rule": "By fieldname", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales Master Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Master Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "track_seen": 0 + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [] } \ No newline at end of file From d8245cef723575eaf52c2e39d25a6f9c83ce9ba0 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sun, 26 Nov 2023 16:13:39 +0530 Subject: [PATCH 118/202] fix: job card overlap validation (#38345) --- .../doctype/job_card/job_card.py | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index db6bc80838..f303531aee 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -185,7 +185,8 @@ class JobCard(Document): # override capacity for employee production_capacity = 1 - if time_logs and production_capacity > len(time_logs): + overlap_count = self.get_overlap_count(time_logs) + if time_logs and production_capacity > overlap_count: return {} if self.workstation_type and time_logs: @@ -195,6 +196,37 @@ class JobCard(Document): return time_logs[-1] + @staticmethod + def get_overlap_count(time_logs): + count = 1 + + # Check overlap exists or not between the overlapping time logs with the current Job Card + for idx, row in enumerate(time_logs): + next_idx = idx + if idx + 1 < len(time_logs): + next_idx = idx + 1 + next_row = time_logs[next_idx] + if row.name == next_row.name: + continue + + if ( + ( + get_datetime(next_row.from_time) >= get_datetime(row.from_time) + and get_datetime(next_row.from_time) <= get_datetime(row.to_time) + ) + or ( + get_datetime(next_row.to_time) >= get_datetime(row.from_time) + and get_datetime(next_row.to_time) <= get_datetime(row.to_time) + ) + or ( + get_datetime(next_row.from_time) <= get_datetime(row.from_time) + and get_datetime(next_row.to_time) >= get_datetime(row.to_time) + ) + ): + count += 1 + + return count + def get_time_logs(self, args, doctype, check_next_available_slot=False): jc = frappe.qb.DocType("Job Card") jctl = frappe.qb.DocType(doctype) @@ -211,7 +243,14 @@ class JobCard(Document): query = ( frappe.qb.from_(jctl) .from_(jc) - .select(jc.name.as_("name"), jctl.from_time, jctl.to_time, jc.workstation, jc.workstation_type) + .select( + jc.name.as_("name"), + jctl.name.as_("row_name"), + jctl.from_time, + jctl.to_time, + jc.workstation, + jc.workstation_type, + ) .where( (jctl.parent == jc.name) & (Criterion.any(time_conditions)) From 284a40aa63d09163e24b089cf0dcc517b8e62a91 Mon Sep 17 00:00:00 2001 From: Monolithon Administrator <5338127+monolithonadmin@users.noreply.github.com> Date: Sun, 26 Nov 2023 13:47:10 +0100 Subject: [PATCH 119/202] fix: Add name to Hungary - Chart of Accounts for Microenterprises json (#38278) Co-authored-by: Deepesh Garg --- ..._of_accounts_for_microenterprises_with_account_number.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/hu_chart_of_accounts_for_microenterprises_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/hu_chart_of_accounts_for_microenterprises_with_account_number.json index 2cd6c0fc61..4013bb0926 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/hu_chart_of_accounts_for_microenterprises_with_account_number.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/hu_chart_of_accounts_for_microenterprises_with_account_number.json @@ -1,4 +1,6 @@ { + "country_code": "hu", + "name": "Hungary - Chart of Accounts for Microenterprises", "tree": { "SZ\u00c1MLAOSZT\u00c1LY BEFEKTETETT ESZK\u00d6Z\u00d6K": { "account_number": 1, @@ -1651,4 +1653,4 @@ } } } -} \ No newline at end of file +} From 5426b93387c8a4599b11d5e064d4d8b37078aca1 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Sun, 26 Nov 2023 14:07:55 +0100 Subject: [PATCH 120/202] refactor: bank transaction (#38182) --- .../bank_reconciliation_tool.py | 4 +- .../bank_transaction/bank_transaction.json | 17 ++- .../bank_transaction/bank_transaction.py | 139 ++++++++---------- 3 files changed, 77 insertions(+), 83 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 7e2f763137..c2ddb39964 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -424,7 +424,9 @@ def reconcile_vouchers(bank_transaction_name, vouchers): vouchers = json.loads(vouchers) transaction = frappe.get_doc("Bank Transaction", bank_transaction_name) transaction.add_payment_entries(vouchers) - return frappe.get_doc("Bank Transaction", bank_transaction_name) + transaction.save() + + return transaction @frappe.whitelist() diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json index b32022e6fd..0328d51b89 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json @@ -13,6 +13,7 @@ "status", "bank_account", "company", + "amended_from", "section_break_4", "deposit", "withdrawal", @@ -25,10 +26,10 @@ "transaction_id", "transaction_type", "section_break_14", + "column_break_oufv", "payment_entries", "section_break_18", "allocated_amount", - "amended_from", "column_break_17", "unallocated_amount", "party_section", @@ -138,10 +139,12 @@ "fieldtype": "Section Break" }, { + "allow_on_submit": 1, "fieldname": "allocated_amount", "fieldtype": "Currency", "label": "Allocated Amount", - "options": "currency" + "options": "currency", + "read_only": 1 }, { "fieldname": "amended_from", @@ -157,10 +160,12 @@ "fieldtype": "Column Break" }, { + "allow_on_submit": 1, "fieldname": "unallocated_amount", "fieldtype": "Currency", "label": "Unallocated Amount", - "options": "currency" + "options": "currency", + "read_only": 1 }, { "fieldname": "party_section", @@ -225,11 +230,15 @@ "fieldname": "bank_party_account_number", "fieldtype": "Data", "label": "Party Account No. (Bank Statement)" + }, + { + "fieldname": "column_break_oufv", + "fieldtype": "Column Break" } ], "is_submittable": 1, "links": [], - "modified": "2023-06-06 13:58:12.821411", + "modified": "2023-11-18 18:32:47.203694", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Transaction", diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 4649d23162..51c823a459 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -2,78 +2,73 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.utils import flt from erpnext.controllers.status_updater import StatusUpdater class BankTransaction(StatusUpdater): - def after_insert(self): - self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) + def before_validate(self): + self.update_allocated_amount() - def on_submit(self): - self.clear_linked_payment_entries() + def validate(self): + self.validate_duplicate_references() + + def validate_duplicate_references(self): + """Make sure the same voucher is not allocated twice within the same Bank Transaction""" + if not self.payment_entries: + return + + pe = [] + for row in self.payment_entries: + reference = (row.payment_document, row.payment_entry) + if reference in pe: + frappe.throw( + _("{0} {1} is allocated twice in this Bank Transaction").format( + row.payment_document, row.payment_entry + ) + ) + pe.append(reference) + + def update_allocated_amount(self): + self.allocated_amount = ( + sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0 + ) + self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount + + def before_submit(self): + self.allocate_payment_entries() self.set_status() if frappe.db.get_single_value("Accounts Settings", "enable_party_matching"): self.auto_set_party() - _saving_flag = False - - # nosemgrep: frappe-semgrep-rules.rules.frappe-modifying-but-not-comitting - def on_update_after_submit(self): - "Run on save(). Avoid recursion caused by multiple saves" - if not self._saving_flag: - self._saving_flag = True - self.clear_linked_payment_entries() - self.update_allocations() - self._saving_flag = False + def before_update_after_submit(self): + self.validate_duplicate_references() + self.allocate_payment_entries() + self.update_allocated_amount() def on_cancel(self): - self.clear_linked_payment_entries(for_cancel=True) - self.set_status(update=True) + for payment_entry in self.payment_entries: + self.clear_linked_payment_entry(payment_entry, for_cancel=True) - def update_allocations(self): - "The doctype does not allow modifications after submission, so write to the db direct" - if self.payment_entries: - allocated_amount = sum(p.allocated_amount for p in self.payment_entries) - else: - allocated_amount = 0.0 - - amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.db_set("allocated_amount", flt(allocated_amount)) - self.db_set("unallocated_amount", amount - flt(allocated_amount)) - self.reload() self.set_status(update=True) def add_payment_entries(self, vouchers): "Add the vouchers with zero allocation. Save() will perform the allocations and clearance" if 0.0 >= self.unallocated_amount: - frappe.throw(frappe._("Bank Transaction {0} is already fully reconciled").format(self.name)) + frappe.throw(_("Bank Transaction {0} is already fully reconciled").format(self.name)) - added = False for voucher in vouchers: - # Can't add same voucher twice - found = False - for pe in self.payment_entries: - if ( - pe.payment_document == voucher["payment_doctype"] - and pe.payment_entry == voucher["payment_name"] - ): - found = True - - if not found: - pe = { + self.append( + "payment_entries", + { "payment_document": voucher["payment_doctype"], "payment_entry": voucher["payment_name"], "allocated_amount": 0.0, # Temporary - } - child = self.append("payment_entries", pe) - added = True - - # runs on_update_after_submit - if added: - self.save() + }, + ) def allocate_payment_entries(self): """Refactored from bank reconciliation tool. @@ -90,6 +85,7 @@ class BankTransaction(StatusUpdater): - clear means: set the latest transaction date as clearance date """ remaining_amount = self.unallocated_amount + to_remove = [] for payment_entry in self.payment_entries: if payment_entry.allocated_amount == 0.0: unallocated_amount, should_clear, latest_transaction = get_clearance_details( @@ -99,49 +95,39 @@ class BankTransaction(StatusUpdater): if 0.0 == unallocated_amount: if should_clear: latest_transaction.clear_linked_payment_entry(payment_entry) - self.db_delete_payment_entry(payment_entry) + to_remove.append(payment_entry) elif remaining_amount <= 0.0: - self.db_delete_payment_entry(payment_entry) + to_remove.append(payment_entry) - elif 0.0 < unallocated_amount and unallocated_amount <= remaining_amount: - payment_entry.db_set("allocated_amount", unallocated_amount) + elif 0.0 < unallocated_amount <= remaining_amount: + payment_entry.allocated_amount = unallocated_amount remaining_amount -= unallocated_amount if should_clear: latest_transaction.clear_linked_payment_entry(payment_entry) - elif 0.0 < unallocated_amount and unallocated_amount > remaining_amount: - payment_entry.db_set("allocated_amount", remaining_amount) + elif 0.0 < unallocated_amount: + payment_entry.allocated_amount = remaining_amount remaining_amount = 0.0 elif 0.0 > unallocated_amount: - self.db_delete_payment_entry(payment_entry) - frappe.throw(frappe._("Voucher {0} is over-allocated by {1}").format(unallocated_amount)) + frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount)) - self.reload() - - def db_delete_payment_entry(self, payment_entry): - frappe.db.delete("Bank Transaction Payments", {"name": payment_entry.name}) + for payment_entry in to_remove: + self.remove(to_remove) @frappe.whitelist() def remove_payment_entries(self): for payment_entry in self.payment_entries: self.remove_payment_entry(payment_entry) - # runs on_update_after_submit - self.save() + + self.save() # runs before_update_after_submit def remove_payment_entry(self, payment_entry): "Clear payment entry and clearance" self.clear_linked_payment_entry(payment_entry, for_cancel=True) self.remove(payment_entry) - def clear_linked_payment_entries(self, for_cancel=False): - if for_cancel: - for payment_entry in self.payment_entries: - self.clear_linked_payment_entry(payment_entry, for_cancel) - else: - self.allocate_payment_entries() - def clear_linked_payment_entry(self, payment_entry, for_cancel=False): clearance_date = None if for_cancel else self.date set_voucher_clearance( @@ -162,11 +148,10 @@ class BankTransaction(StatusUpdater): deposit=self.deposit, ).match() - if result: - party_type, party = result - frappe.db.set_value( - "Bank Transaction", self.name, field={"party_type": party_type, "party": party} - ) + if not result: + return + + self.party_type, self.party = result @frappe.whitelist() @@ -198,9 +183,7 @@ def get_clearance_details(transaction, payment_entry): if gle["gl_account"] == gl_bank_account: if gle["amount"] <= 0.0: frappe.throw( - frappe._("Voucher {0} value is broken: {1}").format( - payment_entry.payment_entry, gle["amount"] - ) + _("Voucher {0} value is broken: {1}").format(payment_entry.payment_entry, gle["amount"]) ) unmatched_gles -= 1 @@ -221,7 +204,7 @@ def get_clearance_details(transaction, payment_entry): def get_related_bank_gl_entries(doctype, docname): # nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql - result = frappe.db.sql( + return frappe.db.sql( """ SELECT ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount, @@ -239,7 +222,6 @@ def get_related_bank_gl_entries(doctype, docname): dict(doctype=doctype, docname=docname), as_dict=True, ) - return result def get_total_allocated_amount(doctype, docname): @@ -365,6 +347,7 @@ def set_voucher_clearance(doctype, docname, clearance_date, self): if clearance_date: vouchers = [{"payment_doctype": "Bank Transaction", "payment_name": self.name}] bt.add_payment_entries(vouchers) + bt.save() else: for pe in bt.payment_entries: if pe.payment_document == self.doctype and pe.payment_entry == self.name: From d9b3b9585472656c820fa241f32ed707f7df5c54 Mon Sep 17 00:00:00 2001 From: NandhiniDevi <95607404+Nandhinidevi123@users.noreply.github.com> Date: Sun, 26 Nov 2023 18:40:31 +0530 Subject: [PATCH 121/202] fix : Payment Reco Issue and chart of account importer (#38321) fix : Payment Reco Issue and chart of account importer --- .../chart_of_accounts_importer/chart_of_accounts_importer.py | 2 +- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py index 5a1c139bde..1e64eeeae6 100644 --- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py +++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py @@ -113,7 +113,7 @@ def generate_data_from_csv(file_doc, as_dict=False): if as_dict: data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)}) else: - if not row[1]: + if not row[1] and len(row) > 1: row[1] = row[0] row[3] = row[2] data.append(row) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 1cff4c7f2d..0ad20c31c1 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -508,7 +508,7 @@ class JournalEntry(AccountsController): ).format(d.reference_name, d.account) ) else: - dr_or_cr = "debit" if d.credit > 0 else "credit" + dr_or_cr = "debit" if flt(d.credit) > 0 else "credit" valid = False for jvd in against_entries: if flt(jvd[dr_or_cr]) > 0: From 592ce45da7659dcf4ca148f5924dbe0d783956bf Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 27 Nov 2023 08:51:22 +0530 Subject: [PATCH 122/202] refactor: handle rounding loss on AR/AP reports --- .../report/accounts_receivable/accounts_receivable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 0e62ad61cc..7948e5f465 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -285,8 +285,8 @@ class ReceivablePayableReport(object): must_consider = False if self.filters.get("for_revaluation_journals"): - if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) or ( - (abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision) + if (abs(row.outstanding) > 0.0 / 10**self.currency_precision) or ( + (abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision) ): must_consider = True else: From b9f5a1c85dc29acc22e704d866178a98f3035c1d Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 27 Nov 2023 09:05:22 +0530 Subject: [PATCH 123/202] fix: Negative Qty and Rates in SO/PO (#38252) * fix: Don't allow negative qty in SO/PO * fix: Type casting for safe comparisons * fix: Grammar in error message * fix: Negative rates should be allowed via Update Items in SO/PO * fix: Use `non_negative` property in docfield & emove code validation --- .../purchase_order/test_purchase_order.py | 17 ++++++++++- .../purchase_order_item.json | 3 +- erpnext/controllers/accounts_controller.py | 29 ++++++++++++++----- .../doctype/sales_order/test_sales_order.py | 29 +++++++++++++++++++ .../sales_order_item/sales_order_item.json | 3 +- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 55c01e8513..0f8574c84d 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -16,7 +16,7 @@ from erpnext.buying.doctype.purchase_order.purchase_order import ( make_purchase_invoice as make_pi_from_po, ) from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt -from erpnext.controllers.accounts_controller import update_child_qty_rate +from erpnext.controllers.accounts_controller import InvalidQtyError, update_child_qty_rate from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.material_request.material_request import make_purchase_order @@ -27,6 +27,21 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( class TestPurchaseOrder(FrappeTestCase): + def test_purchase_order_qty(self): + po = create_purchase_order(qty=1, do_not_save=True) + po.append( + "items", + { + "item_code": "_Test Item", + "qty": -1, + "rate": 10, + }, + ) + self.assertRaises(frappe.NonNegativeError, po.save) + + po.items[1].qty = 0 + self.assertRaises(InvalidQtyError, po.save) + def test_make_purchase_receipt(self): po = create_purchase_order(do_not_submit=True) self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name) diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 2d706f41e5..98c1b388c1 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -214,6 +214,7 @@ "fieldtype": "Float", "in_list_view": 1, "label": "Quantity", + "non_negative": 1, "oldfieldname": "qty", "oldfieldtype": "Currency", "print_width": "60px", @@ -917,7 +918,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:34:27.267382", + "modified": "2023-11-24 13:24:41.298416", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e68894fa77..f551133a28 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -71,6 +71,10 @@ class AccountMissingError(frappe.ValidationError): pass +class InvalidQtyError(frappe.ValidationError): + pass + + force_item_fields = ( "item_group", "brand", @@ -911,10 +915,16 @@ class AccountsController(TransactionBase): return flt(args.get(field, 0) / self.get("conversion_rate", 1)) def validate_qty_is_not_zero(self): - if self.doctype != "Purchase Receipt": - for item in self.items: - if not item.qty: - frappe.throw(_("Item quantity can not be zero")) + if self.doctype == "Purchase Receipt": + return + + for item in self.items: + if not flt(item.qty): + frappe.throw( + msg=_("Row #{0}: Item quantity cannot be zero").format(item.idx), + title=_("Invalid Quantity"), + exc=InvalidQtyError, + ) def validate_account_currency(self, account, account_currency=None): valid_currency = [self.company_currency] @@ -3142,16 +3152,19 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil conv_fac_precision = child_item.precision("conversion_factor") or 2 qty_precision = child_item.precision("qty") or 2 - if flt(child_item.billed_amt, rate_precision) > flt( - flt(d.get("rate"), rate_precision) * flt(d.get("qty"), qty_precision), rate_precision - ): + # Amount cannot be lesser than billed amount, except for negative amounts + row_rate = flt(d.get("rate"), rate_precision) + amount_below_billed_amt = flt(child_item.billed_amt, rate_precision) > flt( + row_rate * flt(d.get("qty"), qty_precision), rate_precision + ) + if amount_below_billed_amt and row_rate > 0.0: frappe.throw( _("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.").format( child_item.idx, child_item.item_code ) ) else: - child_item.rate = flt(d.get("rate"), rate_precision) + child_item.rate = row_rate if d.get("conversion_factor"): if child_item.stock_uom == child_item.uom: diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index d8b5878aa3..a518597aa6 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -51,6 +51,35 @@ class TestSalesOrder(FrappeTestCase): def tearDown(self): frappe.set_user("Administrator") + def test_sales_order_with_negative_rate(self): + """ + Test if negative rate is allowed in Sales Order via doc submission and update items + """ + so = make_sales_order(qty=1, rate=100, do_not_save=True) + so.append("items", {"item_code": "_Test Item", "qty": 1, "rate": -10}) + so.save() + so.submit() + + first_item = so.get("items")[0] + second_item = so.get("items")[1] + trans_item = json.dumps( + [ + { + "item_code": first_item.item_code, + "rate": first_item.rate, + "qty": first_item.qty, + "docname": first_item.name, + }, + { + "item_code": second_item.item_code, + "rate": -20, + "qty": second_item.qty, + "docname": second_item.name, + }, + ] + ) + update_child_qty_rate("Sales Order", trans_item, so.name) + def test_make_material_request(self): so = make_sales_order(do_not_submit=True) diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index b4f73003ae..d4ccfc4753 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -200,6 +200,7 @@ "fieldtype": "Float", "in_list_view": 1, "label": "Quantity", + "non_negative": 1, "oldfieldname": "qty", "oldfieldtype": "Currency", "print_width": "100px", @@ -895,7 +896,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:37:12.787893", + "modified": "2023-11-24 13:24:55.756320", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", From 5a97fa633631a3cb7dd0f4f7305cde293fd80ce2 Mon Sep 17 00:00:00 2001 From: Nandhinidevi123 Date: Mon, 27 Nov 2023 19:51:05 +0530 Subject: [PATCH 124/202] feat:add customer group filter in sales register --- erpnext/accounts/report/sales_register/sales_register.js | 6 ++++++ erpnext/accounts/report/sales_register/sales_register.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js index 1a41172a97..4578ac3f6e 100644 --- a/erpnext/accounts/report/sales_register/sales_register.js +++ b/erpnext/accounts/report/sales_register/sales_register.js @@ -22,6 +22,12 @@ frappe.query_reports["Sales Register"] = { "fieldtype": "Link", "options": "Customer" }, + { + "fieldname":"customer_group", + "label": __("Customer Group"), + "fieldtype": "Link", + "options": "Customer Group" + }, { "fieldname":"company", "label": __("Company"), diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 0ba7186fa6..ec6dd72908 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -449,6 +449,9 @@ def get_invoices(filters, additional_query_columns): if filters.get("customer"): query = query.where(si.customer == filters.customer) + if filters.get("customer_group"): + query = query.where(si.customer_group == filters.customer_group) + query = get_conditions(filters, query, "Sales Invoice") query = apply_common_conditions( filters, query, doctype="Sales Invoice", child_doctype="Sales Invoice Item" From 5a53a4b044be7e889080329056c7911970d92da8 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 27 Nov 2023 20:21:19 +0530 Subject: [PATCH 125/202] fix: make parameters of `create_subscription_process` optional (and other minor fixes) (#38360) --- .../doctype/process_subscription/process_subscription.py | 3 +-- erpnext/accounts/doctype/subscription/subscription.py | 2 +- erpnext/hooks.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/process_subscription/process_subscription.py b/erpnext/accounts/doctype/process_subscription/process_subscription.py index 99269d6a7d..0aa9970cb8 100644 --- a/erpnext/accounts/doctype/process_subscription/process_subscription.py +++ b/erpnext/accounts/doctype/process_subscription/process_subscription.py @@ -17,11 +17,10 @@ class ProcessSubscription(Document): def create_subscription_process( - subscription: str | None, posting_date: Union[str, datetime.date] | None + subscription: str | None = None, posting_date: Union[str, datetime.date] | None = None ): """Create a new Process Subscription document""" doc = frappe.new_doc("Process Subscription") doc.subscription = subscription doc.posting_date = getdate(posting_date) - doc.insert(ignore_permissions=True) doc.submit() diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 3cf7d284bb..a3d8c23418 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -676,7 +676,7 @@ def get_prorata_factor( def process_all( - subscription: str | None, posting_date: Optional["DateTimeLikeObject"] = None + subscription: str | None = None, posting_date: Optional["DateTimeLikeObject"] = None ) -> None: """ Task to updates the status of all `Subscription` apart from those that are cancelled diff --git a/erpnext/hooks.py b/erpnext/hooks.py index c6ab6f12f6..857471f1fd 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -419,7 +419,6 @@ scheduler_events = { "erpnext.projects.doctype.project.project.collect_project_status", ], "hourly_long": [ - "erpnext.accounts.doctype.process_subscription.process_subscription.create_subscription_process", "erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries", "erpnext.utilities.bulk_transaction.retry", ], @@ -450,6 +449,7 @@ scheduler_events = { "erpnext.accounts.utils.auto_create_exchange_rate_revaluation_weekly", ], "daily_long": [ + "erpnext.accounts.doctype.process_subscription.process_subscription.create_subscription_process", "erpnext.setup.doctype.email_digest.email_digest.send", "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.auto_update_latest_price_in_all_boms", "erpnext.crm.utils.open_leads_opportunities_based_on_todays_event", From ad3634be7c2607ab5c9c831ae01e5ddff7c9ba8b Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 28 Nov 2023 06:24:21 +0530 Subject: [PATCH 126/202] chore: fix flaky test case (#38369) --- .../doctype/work_order/test_work_order.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 0ae7657c42..e2c8f07980 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -921,6 +921,20 @@ class TestWorkOrder(FrappeTestCase): "Test RM Item 2 for Scrap Item Test", ] + from_time = add_days(now(), -1) + job_cards = frappe.get_all( + "Job Card Time Log", + fields=["distinct parent as name", "docstatus"], + filters={"from_time": (">", from_time)}, + order_by="creation asc", + ) + + for job_card in job_cards: + if job_card.docstatus == 1: + frappe.get_doc("Job Card", job_card.name).cancel() + + frappe.delete_doc("Job Card Time Log", job_card.name) + company = "_Test Company with perpetual inventory" for item_code in items: create_item( From add238c892364ce25f3e7483cb5fd295f9666a56 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 28 Nov 2023 08:21:45 +0530 Subject: [PATCH 127/202] fix: debit credit mismatch in multi-currecy asset purchase receipt (#38342) * fix: Debit credit mimatch in multicurrecy asset purchase receipt * test: multi currency purchase receipt * chore: update init files * test: roolback --- erpnext/assets/doctype/asset/test_asset.py | 103 ++++++------------ .../purchase_receipt/purchase_receipt.py | 2 +- erpnext/www/all-products/__init__.py | 0 erpnext/www/shop-by-category/__init__.py | 0 4 files changed, 37 insertions(+), 68 deletions(-) create mode 100644 erpnext/www/all-products/__init__.py create mode 100644 erpnext/www/shop-by-category/__init__.py diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 9e3ec6faa8..ca2b980579 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -149,12 +149,7 @@ class TestAsset(AssetSetup): ("Creditors - _TC", 0.0, 100000.0), ) - gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Purchase Invoice' and voucher_no = %s - order by account""", - pi.name, - ) + gle = get_gl_entries("Purchase Invoice", pi.name) self.assertSequenceEqual(gle, expected_gle) pi.cancel() @@ -264,12 +259,7 @@ class TestAsset(AssetSetup): ), ) - gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Journal Entry' and voucher_no = %s - order by account""", - asset.journal_entry_for_scrap, - ) + gle = get_gl_entries("Journal Entry", asset.journal_entry_for_scrap) self.assertSequenceEqual(gle, expected_gle) restore_asset(asset.name) @@ -345,13 +335,7 @@ class TestAsset(AssetSetup): ("Debtors - _TC", 25000.0, 0.0), ) - gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Sales Invoice' and voucher_no = %s - order by account""", - si.name, - ) - + gle = get_gl_entries("Sales Invoice", si.name) self.assertSequenceEqual(gle, expected_gle) si.cancel() @@ -425,13 +409,7 @@ class TestAsset(AssetSetup): ("Debtors - _TC", 40000.0, 0.0), ) - gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Sales Invoice' and voucher_no = %s - order by account""", - si.name, - ) - + gle = get_gl_entries("Sales Invoice", si.name) self.assertSequenceEqual(gle, expected_gle) def test_asset_with_maintenance_required_status_after_sale(self): @@ -572,13 +550,7 @@ class TestAsset(AssetSetup): ("CWIP Account - _TC", 5250.0, 0.0), ) - pr_gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Purchase Receipt' and voucher_no = %s - order by account""", - pr.name, - ) - + pr_gle = get_gl_entries("Purchase Receipt", pr.name) self.assertSequenceEqual(pr_gle, expected_gle) pi = make_invoice(pr.name) @@ -591,13 +563,7 @@ class TestAsset(AssetSetup): ("Creditors - _TC", 0.0, 5500.0), ) - pi_gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Purchase Invoice' and voucher_no = %s - order by account""", - pi.name, - ) - + pi_gle = get_gl_entries("Purchase Invoice", pi.name) self.assertSequenceEqual(pi_gle, expected_gle) asset = frappe.db.get_value("Asset", {"purchase_receipt": pr.name, "docstatus": 0}, "name") @@ -624,13 +590,7 @@ class TestAsset(AssetSetup): expected_gle = (("_Test Fixed Asset - _TC", 5250.0, 0.0), ("CWIP Account - _TC", 0.0, 5250.0)) - gle = frappe.db.sql( - """select account, debit, credit from `tabGL Entry` - where voucher_type='Asset' and voucher_no = %s - order by account""", - asset_doc.name, - ) - + gle = get_gl_entries("Asset", asset_doc.name) self.assertSequenceEqual(gle, expected_gle) def test_asset_cwip_toggling_cases(self): @@ -653,10 +613,7 @@ class TestAsset(AssetSetup): asset_doc.available_for_use_date = nowdate() asset_doc.calculate_depreciation = 0 asset_doc.submit() - gle = frappe.db.sql( - """select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", - asset_doc.name, - ) + gle = get_gl_entries("Asset", asset_doc.name) self.assertFalse(gle) # case 1 -- PR with cwip disabled, Asset with cwip enabled @@ -670,10 +627,7 @@ class TestAsset(AssetSetup): asset_doc.available_for_use_date = nowdate() asset_doc.calculate_depreciation = 0 asset_doc.submit() - gle = frappe.db.sql( - """select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", - asset_doc.name, - ) + gle = get_gl_entries("Asset", asset_doc.name) self.assertFalse(gle) # case 2 -- PR with cwip enabled, Asset with cwip disabled @@ -686,10 +640,7 @@ class TestAsset(AssetSetup): asset_doc.available_for_use_date = nowdate() asset_doc.calculate_depreciation = 0 asset_doc.submit() - gle = frappe.db.sql( - """select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", - asset_doc.name, - ) + gle = get_gl_entries("Asset", asset_doc.name) self.assertTrue(gle) # case 3 -- PI with cwip disabled, Asset with cwip enabled @@ -702,10 +653,7 @@ class TestAsset(AssetSetup): asset_doc.available_for_use_date = nowdate() asset_doc.calculate_depreciation = 0 asset_doc.submit() - gle = frappe.db.sql( - """select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", - asset_doc.name, - ) + gle = get_gl_entries("Asset", asset_doc.name) self.assertFalse(gle) # case 4 -- PI with cwip enabled, Asset with cwip disabled @@ -718,10 +666,7 @@ class TestAsset(AssetSetup): asset_doc.available_for_use_date = nowdate() asset_doc.calculate_depreciation = 0 asset_doc.submit() - gle = frappe.db.sql( - """select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", - asset_doc.name, - ) + gle = get_gl_entries("Asset", asset_doc.name) self.assertTrue(gle) frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip) @@ -1701,6 +1646,30 @@ class TestDepreciationBasics(AssetSetup): self.assertRaises(frappe.ValidationError, jv.insert) + def test_multi_currency_asset_pr_creation(self): + pr = make_purchase_receipt( + item_code="Macbook Pro", + qty=1, + rate=100.0, + location="Test Location", + supplier="_Test Supplier USD", + currency="USD", + ) + + pr.submit() + self.assertTrue(get_gl_entries("Purchase Receipt", pr.name)) + + +def get_gl_entries(doctype, docname): + gl_entry = frappe.qb.DocType("GL Entry") + return ( + frappe.qb.from_(gl_entry) + .select(gl_entry.account, gl_entry.debit, gl_entry.credit) + .where((gl_entry.voucher_type == doctype) & (gl_entry.voucher_no == docname)) + .orderby(gl_entry.account) + .run() + ) + def create_asset_data(): if not frappe.db.exists("Asset Category", "Computers"): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index a7aa7e2ab4..8647528ea5 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -571,7 +571,7 @@ class PurchaseReceipt(BuyingController): ) stock_value_diff = ( - flt(d.net_amount) + flt(d.base_net_amount) + flt(d.item_tax_amount / self.conversion_rate) + flt(d.landed_cost_voucher_amount) ) diff --git a/erpnext/www/all-products/__init__.py b/erpnext/www/all-products/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/www/shop-by-category/__init__.py b/erpnext/www/shop-by-category/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 729fc738af7d78a6f75cb0f794f4c4451d74cd05 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 11:08:52 +0530 Subject: [PATCH 128/202] fix: product bundle search input --- .../doctype/product_bundle/product_bundle.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index 2fd9cc1301..c934f0dffa 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -76,16 +76,19 @@ class ProductBundle(Document): @frappe.validate_and_sanitize_search_inputs def get_new_item_code(doctype, txt, searchfield, start, page_len, filters): product_bundles = frappe.db.get_list("Product Bundle", {"disabled": 0}, pluck="name") + item = frappe.qb.DocType("Item") - return ( + query = ( frappe.qb.from_(item) .select("*") .where( - (item.is_stock_item == 0) - & (item.is_fixed_asset == 0) - & (item.name.notin(product_bundles)) - & (item[searchfield].like(f"%{txt}%")) + (item.is_stock_item == 0) & (item.is_fixed_asset == 0) & (item[searchfield].like(f"%{txt}%")) ) .limit(page_len) .offset(start) - ).run() + ) + + if product_bundles: + query = query.where(item.name.notin(product_bundles)) + + return query.run() From 8c3713b649c7777e35be74b7afe437cec682359e Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 11:12:55 +0530 Subject: [PATCH 129/202] fix: don't select all fields --- erpnext/selling/doctype/product_bundle/product_bundle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index c934f0dffa..3d4ffebbfb 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -80,7 +80,7 @@ def get_new_item_code(doctype, txt, searchfield, start, page_len, filters): item = frappe.qb.DocType("Item") query = ( frappe.qb.from_(item) - .select("*") + .select(item.item_code, item.item_name) .where( (item.is_stock_item == 0) & (item.is_fixed_asset == 0) & (item[searchfield].like(f"%{txt}%")) ) From d366a91d9eae52175cd7f10f8a77b96dc09bfd00 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 13:02:27 +0530 Subject: [PATCH 130/202] fix: use checkbox instead of select field --- .../buying_settings/buying_settings.json | 28 ++++++++++--------- .../doctype/purchase_order/purchase_order.py | 9 ++---- .../subcontracting_receipt.py | 9 ++---- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index bb2476d8f2..eba9f24e34 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -30,9 +30,9 @@ "column_break_11", "over_transfer_allowance", "section_break_xcug", - "action_on_purchase_order_submission", + "auto_create_subcontracting_order", "column_break_izrr", - "action_on_subcontracting_receipt_submission" + "auto_create_purchase_receipt" ], "fields": [ { @@ -181,21 +181,23 @@ "fieldname": "section_break_xcug", "fieldtype": "Section Break" }, - { - "fieldname": "action_on_purchase_order_submission", - "fieldtype": "Select", - "label": "Action on Purchase Order Submission", - "options": "\nCreate Subcontracting Order\nCreate and Submit Subcontracting Order" - }, { "fieldname": "column_break_izrr", "fieldtype": "Column Break" }, { - "fieldname": "action_on_subcontracting_receipt_submission", - "fieldtype": "Select", - "label": "Action on Subcontracting Receipt Submission", - "options": "\nCreate Purchase Receipt\nCreate and Submit Purchase Receipt" + "default": "0", + "description": "Subcontracting Order (Draft) will be auto-created on submission of Purchase Order.", + "fieldname": "auto_create_subcontracting_order", + "fieldtype": "Check", + "label": "Auto Create Subcontracting Order" + }, + { + "default": "0", + "description": "Purchase Receipt (Draft) will be auto-created on submission of Subcontracting Receipt.", + "fieldname": "auto_create_purchase_receipt", + "fieldtype": "Check", + "label": "Auto Create Purchase Receipt" } ], "icon": "fa fa-cog", @@ -203,7 +205,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-22 17:46:26.474708", + "modified": "2023-11-28 13:01:18.403492", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 7f764e939e..f000185393 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -488,13 +488,8 @@ class PurchaseOrder(BuyingController): def auto_create_subcontracting_order(self): if self.is_subcontracted and not self.is_old_subcontracting_flow: - if action := frappe.db.get_single_value( - "Buying Settings", "action_on_purchase_order_submission" - ): - if action == "Create Subcontracting Order": - make_subcontracting_order(self.name, save=True, notify=True) - elif action == "Create and Submit Subcontracting Order": - make_subcontracting_order(self.name, submit=True, notify=True) + if frappe.db.get_single_value("Buying Settings", "auto_create_subcontracting_order"): + make_subcontracting_order(self.name, save=True, notify=True) def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index a38acb27d4..3a8ce01237 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -531,13 +531,8 @@ class SubcontractingReceipt(SubcontractingController): ) def auto_create_purchase_receipt(self): - if action := frappe.db.get_single_value( - "Buying Settings", "action_on_subcontracting_receipt_submission" - ): - if action == "Create Purchase Receipt": - make_purchase_receipt(self, save=True, notify=True) - elif action == "Create and Submit Purchase Receipt": - make_purchase_receipt(self, submit=True, notify=True) + if frappe.db.get_single_value("Buying Settings", "auto_create_purchase_receipt"): + make_purchase_receipt(self, save=True, notify=True) @frappe.whitelist() From d891bd7fac1ab9e46a94959dedcc45e18ac69de5 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 13:17:24 +0530 Subject: [PATCH 131/202] feat: Subcontracting Receipt ref in Purchase Receipt --- .../doctype/purchase_receipt/purchase_receipt.js | 8 ++++++++ .../doctype/purchase_receipt/purchase_receipt.json | 11 ++++++++++- .../subcontracting_receipt/subcontracting_receipt.py | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 6552cd7fce..8943066152 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -49,6 +49,14 @@ frappe.ui.form.on("Purchase Receipt", { } }); + frm.set_query("subcontracting_receipt", function() { + return { + filters: { + 'docstatus': 1, + 'supplier': frm.doc.supplier, + } + } + }); }, onload: function(frm) { erpnext.queries.setup_queries(frm, "Warehouse", function() { diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index c8a9e3e82e..c7ad660497 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -16,6 +16,7 @@ "supplier", "supplier_name", "supplier_delivery_note", + "subcontracting_receipt", "column_break1", "posting_date", "posting_time", @@ -1236,13 +1237,21 @@ "fieldname": "named_place", "fieldtype": "Data", "label": "Named Place" + }, + { + "depends_on": "eval: (doc.is_subcontracted && !doc.is_old_subcontracting_flow)", + "fieldname": "subcontracting_receipt", + "fieldtype": "Link", + "label": "Subcontracting Receipt", + "options": "Subcontracting Receipt", + "search_index": 1 } ], "icon": "fa fa-truck", "idx": 261, "is_submittable": 1, "links": [], - "modified": "2023-10-01 21:00:44.556816", + "modified": "2023-11-28 13:14:15.243474", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 3a8ce01237..fc9b38d2ff 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -560,6 +560,7 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "field_map": { "posting_date": "posting_date", "posting_time": "posting_time", + "name": "subcontracting_receipt", "supplier_warehouse": "supplier_warehouse", }, "field_no_map": ["total_qty", "total"], From 37b3ac795284c0ee9593753ececcfe4871e538a4 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 13:39:15 +0530 Subject: [PATCH 132/202] feat: SCR Item ref in PR Item --- .../purchase_receipt_item.json | 16 ++++++++++++++-- .../subcontracting_receipt.py | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index ce2e5d7f84..a86e63daf4 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -127,7 +127,8 @@ "section_break_80", "page_break", "sales_order", - "sales_order_item" + "sales_order_item", + "subcontracting_receipt_item" ], "fields": [ { @@ -1086,12 +1087,23 @@ "print_hide": 1, "read_only": 1, "search_index": 1 + }, + { + "fieldname": "subcontracting_receipt_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Subcontracting Receipt Item", + "no_copy": 1, + "print_hide": 1, + "read_only": 1, + "report_hide": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:38:15.251994", + "modified": "2023-11-28 13:37:29.245204", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index fc9b38d2ff..b980dbd2a3 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -590,6 +590,7 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "rejected_warehouse": item.rejected_warehouse, "purchase_order": item.purchase_order, "purchase_order_item": item.purchase_order_item, + "subcontracting_receipt_item": item.name, } purchase_receipt.append("items", item_row) From 8f00481c5f7742b120a232622fae7b3f7e3d2e86 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:35:28 +0100 Subject: [PATCH 133/202] fix: no fstring in translation (#38381) --- .../stock_and_account_value_comparison.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index b1da3ec1bd..416cf48871 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -166,4 +166,4 @@ def create_reposting_entries(rows, company): if entries: entries = ", ".join(entries) - frappe.msgprint(_(f"Reposting entries created: {entries}")) + frappe.msgprint(_("Reposting entries created: {0}").format(entries)) From 3263f2023c0a6ceabfbdd1eeb5202843d4532b76 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 20 Sep 2023 09:36:18 +0530 Subject: [PATCH 134/202] test: assert ledger entries on partial reconciliation with `Advance as Liability`, partial reconciliation should not post duplicate ledger entries for same reference --- .../purchase_invoice/test_purchase_invoice.py | 4 +- .../sales_invoice/test_sales_invoice.py | 95 ++++++++++++++++++- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 171cc0ccdf..322fc9f16b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1769,10 +1769,10 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): # Check GL Entry against payment doctype expected_gle = [ - ["Advances Paid - _TC", 0.0, 500, nowdate()], + ["Advances Paid - _TC", 500.0, 0.0, nowdate()], + ["Advances Paid - _TC", 0.0, 500.0, nowdate()], ["Cash - _TC", 0.0, 500, nowdate()], ["Creditors - _TC", 500, 0.0, nowdate()], - ["Creditors - _TC", 500, 0.0, nowdate()], ] check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry") diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 017bfa9654..840a31942a 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3371,21 +3371,21 @@ class TestSalesInvoice(FrappeTestCase): def test_advance_entries_as_liability(self): from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry - account = create_account( + advance_account = create_account( parent_account="Current Liabilities - _TC", account_name="Advances Received", company="_Test Company", account_type="Receivable", ) - set_advance_flag(company="_Test Company", flag=1, default_account=account) + set_advance_flag(company="_Test Company", flag=1, default_account=advance_account) pe = create_payment_entry( company="_Test Company", payment_type="Receive", party_type="Customer", party="_Test Customer", - paid_from="Debtors - _TC", + paid_from=advance_account, paid_to="Cash - _TC", paid_amount=1000, ) @@ -3411,9 +3411,9 @@ class TestSalesInvoice(FrappeTestCase): # Check GL Entry against payment doctype expected_gle = [ + ["Advances Received - _TC", 0.0, 1000.0, nowdate()], ["Advances Received - _TC", 500, 0.0, nowdate()], ["Cash - _TC", 1000, 0.0, nowdate()], - ["Debtors - _TC", 0.0, 1000, nowdate()], ["Debtors - _TC", 0.0, 500, nowdate()], ] @@ -3450,6 +3450,93 @@ class TestSalesInvoice(FrappeTestCase): si.items[0].rate = 10 si.save() + def test_partial_allocation_on_advance_as_liability(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry + + company = "_Test Company" + customer = "_Test Customer" + debtors_acc = "Debtors - _TC" + advance_account = create_account( + parent_account="Current Liabilities - _TC", + account_name="Advances Received", + company="_Test Company", + account_type="Receivable", + ) + + set_advance_flag(company="_Test Company", flag=1, default_account=advance_account) + + pe = create_payment_entry( + company=company, + payment_type="Receive", + party_type="Customer", + party=customer, + paid_from=advance_account, + paid_to="Cash - _TC", + paid_amount=1000, + ) + pe.submit() + + si = create_sales_invoice( + company=company, + customer=customer, + do_not_save=True, + do_not_submit=True, + rate=1000, + price_list_rate=1000, + ) + si.base_grand_total = 1000 + si.grand_total = 1000 + si.set_advances() + for advance in si.advances: + advance.allocated_amount = 200 if advance.reference_name == pe.name else 0 + si.save() + si.submit() + + self.assertEqual(si.advances[0].allocated_amount, 200) + + # Check GL Entry against partial from advance + expected_gle = [ + [advance_account, 0.0, 1000.0, nowdate()], + [advance_account, 200.0, 0.0, nowdate()], + ["Cash - _TC", 1000.0, 0.0, nowdate()], + [debtors_acc, 0.0, 200.0, nowdate()], + ] + check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry") + si.reload() + self.assertEqual(si.outstanding_amount, 800.0) + + pr = frappe.get_doc("Payment Reconciliation") + pr.company = company + pr.party_type = "Customer" + pr.party = customer + pr.receivable_payable_account = debtors_acc + pr.default_advance_account = advance_account + pr.get_unreconciled_entries() + + # allocate some more of the same advance + # self.assertEqual(len(pr.invoices), 1) + # self.assertEqual(len(pr.payments), 1) + invoices = [x.as_dict() for x in pr.invoices if x.get("invoice_number") == si.name] + payments = [x.as_dict() for x in pr.payments if x.get("reference_name") == pe.name] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.allocation[0].allocated_amount = 300 + pr.reconcile() + + si.reload() + self.assertEqual(si.outstanding_amount, 500.0) + + # Check GL Entry against multi partial allocations from advance + expected_gle = [ + [advance_account, 0.0, 1000.0, nowdate()], + [advance_account, 200.0, 0.0, nowdate()], + [advance_account, 300.0, 0.0, nowdate()], + ["Cash - _TC", 1000.0, 0.0, nowdate()], + [debtors_acc, 0.0, 200.0, nowdate()], + [debtors_acc, 0.0, 300.0, nowdate()], + ] + check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry") + set_advance_flag(company="_Test Company", flag=0, default_account="") + def set_advance_flag(company, flag, default_account): frappe.db.set_value( From 78ab11f9914725266eb8cf8b98dd81a5f544d79d Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 20 Sep 2023 13:05:04 +0530 Subject: [PATCH 135/202] refactor: post to GL and Payment Ledger on advance as liability --- erpnext/accounts/utils.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 9d32a03931..d133307d39 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -472,7 +472,9 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n # cancel advance entry doc = frappe.get_doc(voucher_type, voucher_no) frappe.flags.ignore_party_validation = True - _delete_pl_entries(voucher_type, voucher_no) + + if not (voucher_type == "Payment Entry" and doc.book_advance_payments_in_separate_party_account): + _delete_pl_entries(voucher_type, voucher_no) for entry in entries: check_if_advance_entry_modified(entry) @@ -494,16 +496,19 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n doc.save(ignore_permissions=True) # re-submit advance entry doc = frappe.get_doc(entry.voucher_type, entry.voucher_no) - gl_map = doc.build_gl_map() - create_payment_ledger_entry(gl_map, update_outstanding="No", cancel=0, adv_adj=1) + + if voucher_type == "Payment Entry" and doc.book_advance_payments_in_separate_party_account: + # both ledgers must be posted to for `Advance as Liability` + doc.make_gl_entries() + else: + gl_map = doc.build_gl_map() + create_payment_ledger_entry(gl_map, update_outstanding="No", cancel=0, adv_adj=1) # Only update outstanding for newly linked vouchers for entry in entries: update_voucher_outstanding( entry.against_voucher_type, entry.against_voucher, entry.account, entry.party_type, entry.party ) - if voucher_type == "Payment Entry": - doc.make_advance_gl_entries(entry.against_voucher_type, entry.against_voucher) frappe.flags.ignore_party_validation = False From 8052103197112d2e1abe7ac35a831267ad9549b7 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 16:28:54 +0530 Subject: [PATCH 136/202] feat: provision to create PR from SCR --- .../purchase_receipt/purchase_receipt.js | 14 ++++++ .../subcontracting_receipt.js | 47 +++++++++++-------- .../subcontracting_receipt.py | 46 +++++++++--------- .../subcontracting_receipt_dashboard.py | 2 +- 4 files changed, 68 insertions(+), 41 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 8943066152..6c9d3392e3 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -122,6 +122,20 @@ frappe.ui.form.on("Purchase Receipt", { erpnext.accounts.dimensions.update_dimension(frm, frm.doctype); }, + subcontracting_receipt: (frm) => { + if (frm.doc.is_subcontracted === 1 && frm.doc.is_old_subcontracting_flow === 0 && frm.doc.subcontracting_receipt) { + frm.set_value('items', null); + + erpnext.utils.map_current_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', + source_name: frm.doc.subcontracting_receipt, + target_doc: frm, + freeze: true, + freeze_message: __('Mapping Purchase Receipt ...'), + }); + } + }, + toggle_display_account_head: function(frm) { var enabled = erpnext.is_perpetual_inventory_enabled(frm.doc.company) frm.fields_dict["items"].grid.set_column_disp(["cost_center"], enabled); diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 5585a4a84b..762cdc96af 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -26,27 +26,36 @@ frappe.ui.form.on('Subcontracting Receipt', { refresh: (frm) => { if (frm.doc.docstatus === 1) { frm.add_custom_button(__('Stock Ledger'), () => { - frappe.route_options = { - voucher_no: frm.doc.name, - from_date: frm.doc.posting_date, - to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), - company: frm.doc.company, - show_cancelled_entries: frm.doc.docstatus === 2 - } - frappe.set_route('query-report', 'Stock Ledger'); - }, __('View')); + frappe.route_options = { + voucher_no: frm.doc.name, + from_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), + company: frm.doc.company, + show_cancelled_entries: frm.doc.docstatus === 2 + } + frappe.set_route('query-report', 'Stock Ledger'); + }, __('View')); frm.add_custom_button(__('Accounting Ledger'), () => { - frappe.route_options = { - voucher_no: frm.doc.name, - from_date: frm.doc.posting_date, - to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), - company: frm.doc.company, - group_by: 'Group by Voucher (Consolidated)', - show_cancelled_entries: frm.doc.docstatus === 2 - } - frappe.set_route('query-report', 'General Ledger'); - }, __('View')); + frappe.route_options = { + voucher_no: frm.doc.name, + from_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), + company: frm.doc.company, + group_by: 'Group by Voucher (Consolidated)', + show_cancelled_entries: frm.doc.docstatus === 2 + } + frappe.set_route('query-report', 'General Ledger'); + }, __('View')); + + frm.add_custom_button(__('Purchase Receipt'), () => { + frappe.model.open_mapped_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', + frm: frm, + freeze: true, + freeze_message: __('Creating Purchase Receipt ...') + }); + }, __('Create')); } if (!frm.doc.is_return && frm.doc.docstatus === 1 && frm.doc.per_returned < 100) { diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index b980dbd2a3..000078f241 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -542,18 +542,20 @@ def make_subcontract_return(source_name, target_doc=None): return make_return_doc("Subcontracting Receipt", source_name, target_doc) -def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, notify=False): - if isinstance(subcontracting_receipt, str): - subcontracting_receipt = frappe.get_doc("Subcontracting Receipt", subcontracting_receipt) +@frappe.whitelist() +def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False, notify=False): + if isinstance(source_name, str): + source_name = frappe.get_doc("Subcontracting Receipt", source_name) - if not subcontracting_receipt.is_return: - purchase_receipt = frappe.new_doc("Purchase Receipt") - purchase_receipt.is_subcontracted = 1 - purchase_receipt.is_old_subcontracting_flow = 0 + if not source_name.is_return: + if not target_doc: + target_doc = frappe.new_doc("Purchase Receipt") + target_doc.is_subcontracted = 1 + target_doc.is_old_subcontracting_flow = 0 - purchase_receipt = get_mapped_doc( + target_doc = get_mapped_doc( "Subcontracting Receipt", - subcontracting_receipt.name, + source_name.name, { "Subcontracting Receipt": { "doctype": "Purchase Receipt", @@ -566,12 +568,12 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "field_no_map": ["total_qty", "total"], }, }, - purchase_receipt, + target_doc, ignore_child_tables=True, ) po_items_details = {} - for item in subcontracting_receipt.items: + for item in source_name.items: if item.purchase_order and item.purchase_order_item: if item.purchase_order not in po_items_details: po_doc = frappe.get_doc("Purchase Order", item.purchase_order) @@ -592,31 +594,33 @@ def make_purchase_receipt(subcontracting_receipt, save=False, submit=False, noti "purchase_order_item": item.purchase_order_item, "subcontracting_receipt_item": item.name, } - purchase_receipt.append("items", item_row) + target_doc.append("items", item_row) - if not purchase_receipt.items: + if not target_doc.items: frappe.throw( _("Purchase Order Item reference is missing in Subcontracting Receipt {0}").format( - subcontracting_receipt.name + source_name.name ) ) - if (save or submit) and frappe.has_permission(purchase_receipt.doctype, "create"): - purchase_receipt.save() + target_doc.set_missing_values() - if submit and frappe.has_permission(purchase_receipt.doctype, "submit", purchase_receipt): + if (save or submit) and frappe.has_permission(target_doc.doctype, "create"): + target_doc.save() + + if submit and frappe.has_permission(target_doc.doctype, "submit", target_doc): try: - purchase_receipt.submit() + target_doc.submit() except Exception as e: - purchase_receipt.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) + target_doc.add_comment("Comment", _("Submit Action Failed") + "

" + str(e)) if notify: frappe.msgprint( _("Purchase Receipt {0} created.").format( - get_link_to_form(purchase_receipt.doctype, purchase_receipt.name) + get_link_to_form(target_doc.doctype, target_doc.name) ), indicator="green", alert=True, ) - return purchase_receipt + return target_doc diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py index f6e1356ed9..4d15938e4b 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py @@ -3,7 +3,7 @@ from frappe import _ def get_data(): return { - "fieldname": "subcontracting_receipt_no", + "fieldname": "subcontracting_receipt", "non_standard_fieldnames": { "Subcontracting Receipt": "return_against", }, From aee2e12f3944ae4db2dd77a31d0c544c1bacb65a Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 28 Nov 2023 17:11:35 +0530 Subject: [PATCH 137/202] chore: fix imports for renamed report --- .../report/tds_computation_summary/tds_computation_summary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 82f97f1894..2b5566fb2f 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -1,7 +1,7 @@ import frappe from frappe import _ -from erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly import ( +from erpnext.accounts.report.tax_withholding_details.tax_withholding_details import ( get_result, get_tds_docs, ) From 1763824e5f7ccaefb83aea84db47c92f9e4c9417 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 17:19:21 +0530 Subject: [PATCH 138/202] refactor: use arrow function --- .../doctype/warranty_claim/warranty_claim.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js index 358768eb46..6888f61ae8 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.js +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js @@ -4,7 +4,7 @@ frappe.provide("erpnext.support"); frappe.ui.form.on("Warranty Claim", { - setup: function(frm) { + setup: (frm) => { frm.set_query('contact_person', erpnext.queries.contact_query); frm.set_query('customer_address', erpnext.queries.address_query); frm.set_query('customer', erpnext.queries.customer); @@ -20,18 +20,22 @@ frappe.ui.form.on("Warranty Claim", { frm.add_fetch('item_code', 'item_name', 'item_name'); frm.add_fetch('item_code', 'description', 'description'); }, - onload: function(frm) { + + onload: (frm) => { if(!frm.doc.status) { frm.set_value('status', 'Open'); } }, - customer: function(frm) { + + customer: (frm) => { erpnext.utils.get_party_details(frm); }, - customer_address: function(frm) { + + customer_address: (frm) => { erpnext.utils.get_address_display(frm); }, - contact_person: function(frm) { + + contact_person: (frm) => { erpnext.utils.get_contact_details(frm); } }); @@ -57,7 +61,7 @@ erpnext.support.WarrantyClaim = class WarrantyClaim extends frappe.ui.form.Contr extend_cscript(cur_frm.cscript, new erpnext.support.WarrantyClaim({frm: cur_frm})); -cur_frm.fields_dict['serial_no'].get_query = function(doc, cdt, cdn) { +cur_frm.fields_dict['serial_no'].get_query = (doc, cdt, cdn) => { var cond = []; var filter = [ ['Serial No', 'docstatus', '!=', 2] @@ -75,7 +79,7 @@ cur_frm.fields_dict['serial_no'].get_query = function(doc, cdt, cdn) { } } -cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) { +cur_frm.fields_dict['item_code'].get_query = (doc, cdt, cdn) => { if(doc.serial_no) { return{ doctype: "Serial No", From 58114e7b24788f0244b89401235a6a20721b9603 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 28 Nov 2023 16:50:22 +0530 Subject: [PATCH 139/202] refactor: use different GL build logic for advance as liability --- .../doctype/payment_entry/payment_entry.py | 112 ++++++++++-------- erpnext/accounts/utils.py | 2 +- 2 files changed, 63 insertions(+), 51 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 0344e3de9f..63c5fa92d3 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1055,64 +1055,76 @@ class PaymentEntry(AccountsController): item=self, ) - for d in self.get("references"): - # re-defining dr_or_cr for every reference in order to avoid the last value affecting calculation of reverse - dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" - cost_center = self.cost_center - if d.reference_doctype == "Sales Invoice" and not cost_center: - cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center") - - gle = party_gl_dict.copy() - - allocated_amount_in_company_currency = self.calculate_base_allocated_amount_for_reference(d) - - if self.book_advance_payments_in_separate_party_account: - against_voucher_type = "Payment Entry" - against_voucher = self.name - else: - against_voucher_type = d.reference_doctype - against_voucher = d.reference_name - - reverse_dr_or_cr = 0 - if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]: - is_return = frappe.db.get_value(d.reference_doctype, d.reference_name, "is_return") - payable_party_types = get_party_types_from_account_type("Payable") - receivable_party_types = get_party_types_from_account_type("Receivable") - if is_return and self.party_type in receivable_party_types and (self.payment_type == "Pay"): - reverse_dr_or_cr = 1 - elif ( - is_return and self.party_type in payable_party_types and (self.payment_type == "Receive") - ): - reverse_dr_or_cr = 1 - - if is_return and not reverse_dr_or_cr: - dr_or_cr = "debit" if dr_or_cr == "credit" else "credit" - - gle.update( - { - dr_or_cr: abs(allocated_amount_in_company_currency), - dr_or_cr + "_in_account_currency": abs(d.allocated_amount), - "against_voucher_type": against_voucher_type, - "against_voucher": against_voucher, - "cost_center": cost_center, - } - ) - gl_entries.append(gle) - dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" - if self.unallocated_amount: - exchange_rate = self.get_exchange_rate() - base_unallocated_amount = self.unallocated_amount * exchange_rate + if self.book_advance_payments_in_separate_party_account: + if self.payment_type == "Receive": + amount = self.base_paid_amount + else: + amount = self.base_received_amount gle = party_gl_dict.copy() gle.update( { - dr_or_cr + "_in_account_currency": self.unallocated_amount, - dr_or_cr: base_unallocated_amount, + dr_or_cr: amount, + # TODO: handle multi currency payments + dr_or_cr + "_in_account_currency": amount, + "against_voucher_type": "Payment Entry", + "against_voucher": self.name, + "cost_center": self.cost_center, } ) - gl_entries.append(gle) + else: + for d in self.get("references"): + # re-defining dr_or_cr for every reference in order to avoid the last value affecting calculation of reverse + dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" + cost_center = self.cost_center + if d.reference_doctype == "Sales Invoice" and not cost_center: + cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center") + + gle = party_gl_dict.copy() + + allocated_amount_in_company_currency = self.calculate_base_allocated_amount_for_reference(d) + reverse_dr_or_cr = 0 + + if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]: + is_return = frappe.db.get_value(d.reference_doctype, d.reference_name, "is_return") + payable_party_types = get_party_types_from_account_type("Payable") + receivable_party_types = get_party_types_from_account_type("Receivable") + if is_return and self.party_type in receivable_party_types and (self.payment_type == "Pay"): + reverse_dr_or_cr = 1 + elif ( + is_return and self.party_type in payable_party_types and (self.payment_type == "Receive") + ): + reverse_dr_or_cr = 1 + + if is_return and not reverse_dr_or_cr: + dr_or_cr = "debit" if dr_or_cr == "credit" else "credit" + + gle.update( + { + dr_or_cr: abs(allocated_amount_in_company_currency), + dr_or_cr + "_in_account_currency": abs(d.allocated_amount), + "against_voucher_type": d.reference_doctype, + "against_voucher": d.reference_name, + "cost_center": cost_center, + } + ) + gl_entries.append(gle) + + if self.unallocated_amount: + exchange_rate = self.get_exchange_rate() + base_unallocated_amount = self.unallocated_amount * exchange_rate + + gle = party_gl_dict.copy() + gle.update( + { + dr_or_cr + "_in_account_currency": self.unallocated_amount, + dr_or_cr: base_unallocated_amount, + } + ) + + gl_entries.append(gle) def make_advance_gl_entries(self, against_voucher_type=None, against_voucher=None, cancel=0): if self.book_advance_payments_in_separate_party_account: diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index d133307d39..e2632d3de4 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -499,7 +499,7 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n if voucher_type == "Payment Entry" and doc.book_advance_payments_in_separate_party_account: # both ledgers must be posted to for `Advance as Liability` - doc.make_gl_entries() + doc.make_advance_gl_entries() else: gl_map = doc.build_gl_map() create_payment_ledger_entry(gl_map, update_outstanding="No", cancel=0, adv_adj=1) From 5fc19dab54a2672ec131dbf97974b2bde277aa76 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 28 Nov 2023 17:13:43 +0530 Subject: [PATCH 140/202] refactor: 'make_advance_gl_entries' method make_advance_gl_entries -> add_advance_gl_entries -> add_advance_gl_for_reference 'make_advance_gl_entries' - main method thats builds and post GL entries for all or one specific reference based on parameters 'add_advance_gl_entries' - build GL map for all or one specific reference. Return an array of dict. 'add_advance_gl_for_reference' - utility function to build gl entries. returns dict. --- .../doctype/payment_entry/payment_entry.py | 66 +++++++------------ 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 63c5fa92d3..c732c0a1c5 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1126,53 +1126,31 @@ class PaymentEntry(AccountsController): gl_entries.append(gle) - def make_advance_gl_entries(self, against_voucher_type=None, against_voucher=None, cancel=0): + def make_advance_gl_entries( + self, entry: object | dict = None, cancel: bool = 0, update_outstanding: str = "Yes" + ): + gl_entries = [] + self.add_advance_gl_entries(gl_entries, entry) + + if cancel: + make_reverse_gl_entries(gl_entries, partial_cancel=True) + else: + make_gl_entries(gl_entries, update_outstanding=update_outstanding) + + def add_advance_gl_entries(self, gl_entries: list, entry: object | dict | None): + """ + If 'entry' is passed, GL enties only for that reference is added. + """ if self.book_advance_payments_in_separate_party_account: - gl_entries = [] - for d in self.get("references"): - if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Journal Entry"): - if not (against_voucher_type and against_voucher) or ( - d.reference_doctype == against_voucher_type and d.reference_name == against_voucher - ): - self.make_invoice_liability_entry(gl_entries, d) + references = [x for x in self.get("references")] + if entry: + references = [x for x in self.get("references") if x.name == entry.name] - if cancel: - for entry in gl_entries: - frappe.db.set_value( - "GL Entry", - { - "voucher_no": self.name, - "voucher_type": self.doctype, - "voucher_detail_no": entry.voucher_detail_no, - "against_voucher_type": entry.against_voucher_type, - "against_voucher": entry.against_voucher, - }, - "is_cancelled", - 1, - ) + for ref in references: + if ref.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Journal Entry"): + self.add_advance_gl_for_reference(gl_entries, ref) - make_reverse_gl_entries(gl_entries=gl_entries, partial_cancel=True) - return - - # same reference added to payment entry - for gl_entry in gl_entries.copy(): - if frappe.db.exists( - "GL Entry", - { - "account": gl_entry.account, - "voucher_type": gl_entry.voucher_type, - "voucher_no": gl_entry.voucher_no, - "voucher_detail_no": gl_entry.voucher_detail_no, - "debit": gl_entry.debit, - "credit": gl_entry.credit, - "is_cancelled": 0, - }, - ): - gl_entries.remove(gl_entry) - - make_gl_entries(gl_entries) - - def make_invoice_liability_entry(self, gl_entries, invoice): + def add_advance_gl_for_reference(self, gl_entries, invoice): args_dict = { "party_type": self.party_type, "party": self.party, From ecb533c4d1971d5963f9d8ff4b038fa4b62cf516 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 28 Nov 2023 17:04:07 +0530 Subject: [PATCH 141/202] refactor: return the newly added reference upon reconciliation --- erpnext/accounts/utils.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index e2632d3de4..0dea1eb9c7 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -473,6 +473,8 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n doc = frappe.get_doc(voucher_type, voucher_no) frappe.flags.ignore_party_validation = True + # For payments with `Advance` in separate account feature enabled, only new ledger entries are posted for each reference. + # No need to cancel/delete payment ledger entries if not (voucher_type == "Payment Entry" and doc.book_advance_payments_in_separate_party_account): _delete_pl_entries(voucher_type, voucher_no) @@ -489,7 +491,7 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n entry.update({"referenced_row": referenced_row}) doc.make_exchange_gain_loss_journal([entry]) else: - update_reference_in_payment_entry( + referenced_row = update_reference_in_payment_entry( entry, doc, do_not_save=True, skip_ref_details_update_for_pe=skip_ref_details_update_for_pe ) @@ -498,8 +500,8 @@ def reconcile_against_document(args, skip_ref_details_update_for_pe=False): # n doc = frappe.get_doc(entry.voucher_type, entry.voucher_no) if voucher_type == "Payment Entry" and doc.book_advance_payments_in_separate_party_account: - # both ledgers must be posted to for `Advance as Liability` - doc.make_advance_gl_entries() + # both ledgers must be posted to for `Advance` in separate account feature + doc.make_advance_gl_entries(referenced_row, update_outstanding="No") else: gl_map = doc.build_gl_map() create_payment_ledger_entry(gl_map, update_outstanding="No", cancel=0, adv_adj=1) @@ -681,11 +683,12 @@ def update_reference_in_payment_entry( new_row.docstatus = 1 for field in list(reference_details): new_row.set(field, reference_details[field]) - + row = new_row else: new_row = payment_entry.append("references") new_row.docstatus = 1 new_row.update(reference_details) + row = new_row payment_entry.flags.ignore_validate_update_after_submit = True payment_entry.clear_unallocated_reference_document_rows() @@ -700,6 +703,7 @@ def update_reference_in_payment_entry( if not do_not_save: payment_entry.save(ignore_permissions=True) + return row def cancel_exchange_gain_loss_journal( @@ -876,7 +880,13 @@ def remove_ref_doc_link_from_pe( try: pe_doc = frappe.get_doc("Payment Entry", pe) pe_doc.set_amounts() - pe_doc.make_advance_gl_entries(against_voucher_type=ref_type, against_voucher=ref_no, cancel=1) + + # Call cancel on only removed reference + references = [ + x for x in pe_doc.references if x.reference_doctype == ref_type and x.reference_name == ref_no + ] + [pe_doc.make_advance_gl_entries(x, cancel=1) for x in references] + pe_doc.clear_unallocated_reference_document_rows() pe_doc.validate_payment_type_with_outstanding() except Exception as e: From 2633d7dca33b50d7900f1b80fb5b6514a1cc9d81 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 28 Nov 2023 17:05:29 +0530 Subject: [PATCH 142/202] refactor: 'partial' flag to only cancel unlinked ledger entries --- erpnext/accounts/general_ledger.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 70a8470614..030a41e5cd 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -597,7 +597,30 @@ def make_reverse_gl_entries( is_opening = any(d.get("is_opening") == "Yes" for d in gl_entries) validate_against_pcv(is_opening, gl_entries[0]["posting_date"], gl_entries[0]["company"]) - if not partial_cancel: + if partial_cancel: + # Partial cancel is only used by `Advance` in separate account feature. + # Only cancel GL entries for unlinked reference using `voucher_detail_no` + gle = frappe.qb.DocType("GL Entry") + for x in gl_entries: + query = ( + frappe.qb.update(gle) + .set(gle.is_cancelled, True) + .set(gle.modified, now()) + .set(gle.modified_by, frappe.session.user) + .where( + (gle.company == x.company) + & (gle.account == x.account) + & (gle.party_type == x.party_type) + & (gle.party == x.party) + & (gle.voucher_type == x.voucher_type) + & (gle.voucher_no == x.voucher_no) + & (gle.against_voucher_type == x.against_voucher_type) + & (gle.against_voucher == x.against_voucher) + & (gle.voucher_detail_no == x.voucher_detail_no) + ) + ) + query.run() + else: set_as_cancel(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"]) for entry in gl_entries: From 01044ca8e95ec4e84e63fcfe4928ca111cf3a75b Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 17:33:27 +0530 Subject: [PATCH 143/202] refactor: use DocType `Fetch From` instead of `frm.add_fetch` --- .../doctype/warranty_claim/warranty_claim.js | 11 ----------- .../warranty_claim/warranty_claim.json | 19 ++++++++++++++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js index 6888f61ae8..a653f840d8 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.js +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js @@ -8,17 +8,6 @@ frappe.ui.form.on("Warranty Claim", { frm.set_query('contact_person', erpnext.queries.contact_query); frm.set_query('customer_address', erpnext.queries.address_query); frm.set_query('customer', erpnext.queries.customer); - - frm.add_fetch('serial_no', 'item_code', 'item_code'); - frm.add_fetch('serial_no', 'item_name', 'item_name'); - frm.add_fetch('serial_no', 'description', 'description'); - frm.add_fetch('serial_no', 'maintenance_status', 'warranty_amc_status'); - frm.add_fetch('serial_no', 'warranty_expiry_date', 'warranty_expiry_date'); - frm.add_fetch('serial_no', 'amc_expiry_date', 'amc_expiry_date'); - frm.add_fetch('serial_no', 'customer', 'customer'); - frm.add_fetch('serial_no', 'customer_name', 'customer_name'); - frm.add_fetch('item_code', 'item_name', 'item_name'); - frm.add_fetch('item_code', 'description', 'description'); }, onload: (frm) => { diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.json b/erpnext/support/doctype/warranty_claim/warranty_claim.json index 01d9b01390..9af2b4606c 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.json +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.json @@ -92,7 +92,8 @@ "fieldname": "serial_no", "fieldtype": "Link", "label": "Serial No", - "options": "Serial No" + "options": "Serial No", + "search_index": 1 }, { "fieldname": "customer", @@ -128,6 +129,8 @@ "options": "fa fa-ticket" }, { + "fetch_from": "serial_no.item_code", + "fetch_if_empty": 1, "fieldname": "item_code", "fieldtype": "Link", "in_list_view": 1, @@ -140,6 +143,7 @@ }, { "depends_on": "eval:doc.item_code", + "fetch_from": "item_code.item_name", "fieldname": "item_name", "fieldtype": "Data", "label": "Item Name", @@ -149,6 +153,7 @@ }, { "depends_on": "eval:doc.item_code", + "fetch_from": "item_code.description", "fieldname": "description", "fieldtype": "Small Text", "label": "Description", @@ -164,17 +169,24 @@ "width": "50%" }, { + "fetch_from": "serial_no.maintenance_status", + "fetch_if_empty": 1, "fieldname": "warranty_amc_status", "fieldtype": "Select", "label": "Warranty / AMC Status", - "options": "\nUnder Warranty\nOut of Warranty\nUnder AMC\nOut of AMC" + "options": "\nUnder Warranty\nOut of Warranty\nUnder AMC\nOut of AMC", + "search_index": 1 }, { + "fetch_from": "serial_no.warranty_expiry_date", + "fetch_if_empty": 1, "fieldname": "warranty_expiry_date", "fieldtype": "Date", "label": "Warranty Expiry Date" }, { + "fetch_from": "serial_no.amc_expiry_date", + "fetch_if_empty": 1, "fieldname": "amc_expiry_date", "fieldtype": "Date", "label": "AMC Expiry Date" @@ -225,6 +237,7 @@ { "bold": 1, "depends_on": "customer", + "fetch_from": "customer.customer_name", "fieldname": "customer_name", "fieldtype": "Data", "in_global_search": 1, @@ -366,7 +379,7 @@ "icon": "fa fa-bug", "idx": 1, "links": [], - "modified": "2023-06-03 16:17:07.694449", + "modified": "2023-11-28 17:30:35.676410", "modified_by": "Administrator", "module": "Support", "name": "Warranty Claim", From 640dfab827f2e83b9c3ae7ff839c6f94b63b71b2 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 17:45:17 +0530 Subject: [PATCH 144/202] refactor: use `frm.set_query` to add filters --- .../doctype/warranty_claim/warranty_claim.js | 102 +++++++++--------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js index a653f840d8..32494efe53 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.js +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js @@ -5,14 +5,34 @@ frappe.provide("erpnext.support"); frappe.ui.form.on("Warranty Claim", { setup: (frm) => { - frm.set_query('contact_person', erpnext.queries.contact_query); - frm.set_query('customer_address', erpnext.queries.address_query); - frm.set_query('customer', erpnext.queries.customer); + frm.set_query("contact_person", erpnext.queries.contact_query); + frm.set_query("customer_address", erpnext.queries.address_query); + frm.set_query("customer", erpnext.queries.customer); + + frm.set_query("serial_no", () => { + let filters = { + company: frm.doc.company, + }; + + if (frm.doc.item_code) { + filters["item_code"] = frm.doc.item_code; + } + + return { filters: filters }; + }); + + frm.set_query("item_code", () => { + return { + filters: { + disabled: 0, + }, + }; + }); }, onload: (frm) => { - if(!frm.doc.status) { - frm.set_value('status', 'Open'); + if (!frm.doc.status) { + frm.set_value("status", "Open"); } }, @@ -26,64 +46,40 @@ frappe.ui.form.on("Warranty Claim", { contact_person: (frm) => { erpnext.utils.get_contact_details(frm); - } + }, }); -erpnext.support.WarrantyClaim = class WarrantyClaim extends frappe.ui.form.Controller { +erpnext.support.WarrantyClaim = class WarrantyClaim extends ( + frappe.ui.form.Controller +) { refresh() { - frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'} + frappe.dynamic_link = { + doc: this.frm.doc, + fieldname: "customer", + doctype: "Customer", + }; - if(!cur_frm.doc.__islocal && - (cur_frm.doc.status=='Open' || cur_frm.doc.status == 'Work In Progress')) { - cur_frm.add_custom_button(__('Maintenance Visit'), - this.make_maintenance_visit); + if ( + !cur_frm.doc.__islocal && + (cur_frm.doc.status == "Open" || + cur_frm.doc.status == "Work In Progress") + ) { + cur_frm.add_custom_button( + __("Maintenance Visit"), + this.make_maintenance_visit + ); } } make_maintenance_visit() { frappe.model.open_mapped_doc({ method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit", - frm: cur_frm - }) + frm: cur_frm, + }); } }; -extend_cscript(cur_frm.cscript, new erpnext.support.WarrantyClaim({frm: cur_frm})); - -cur_frm.fields_dict['serial_no'].get_query = (doc, cdt, cdn) => { - var cond = []; - var filter = [ - ['Serial No', 'docstatus', '!=', 2] - ]; - if(doc.item_code) { - cond = ['Serial No', 'item_code', '=', doc.item_code]; - filter.push(cond); - } - if(doc.customer) { - cond = ['Serial No', 'customer', '=', doc.customer]; - filter.push(cond); - } - return{ - filters:filter - } -} - -cur_frm.fields_dict['item_code'].get_query = (doc, cdt, cdn) => { - if(doc.serial_no) { - return{ - doctype: "Serial No", - fields: "item_code", - filters:{ - name: doc.serial_no - } - } - } - else{ - return{ - filters:[ - ['Item', 'docstatus', '!=', 2], - ['Item', 'disabled', '=', 0] - ] - } - } -}; +extend_cscript( + cur_frm.cscript, + new erpnext.support.WarrantyClaim({ frm: cur_frm }) +); From 592fc81260779ec42b35c88c6b8de19a598911d0 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 28 Nov 2023 18:28:48 +0530 Subject: [PATCH 145/202] fix: serial no status (#38391) --- .../delivery_note/test_delivery_note.py | 19 +++++++++++++++ erpnext/stock/doctype/serial_no/serial_no.js | 19 +++++++++++++++ .../stock/doctype/serial_no/serial_no.json | 4 ++-- .../serial_no_ledger/serial_no_ledger.py | 24 +++++++++++++++---- erpnext/stock/serial_batch_bundle.py | 6 ++++- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 137c352e99..94655747e4 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1247,6 +1247,25 @@ class TestDeliveryNote(FrappeTestCase): dn.reload() self.assertFalse(dn.items[0].target_warehouse) + def test_serial_no_status(self): + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + + item = make_item( + "Test Serial Item For Status", + {"has_serial_no": 1, "is_stock_item": 1, "serial_no_series": "TESTSERIAL.#####"}, + ) + + item_code = item.name + pi = make_purchase_receipt(qty=1, item_code=item.name) + pi.reload() + serial_no = get_serial_nos_from_bundle(pi.items[0].serial_and_batch_bundle) + + self.assertEqual(frappe.db.get_value("Serial No", serial_no, "status"), "Active") + + dn = create_delivery_note(qty=1, item_code=item_code, serial_no=serial_no) + dn.reload() + self.assertEqual(frappe.db.get_value("Serial No", serial_no, "status"), "Delivered") + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") diff --git a/erpnext/stock/doctype/serial_no/serial_no.js b/erpnext/stock/doctype/serial_no/serial_no.js index 9d5555ed63..1cb9fd1800 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.js +++ b/erpnext/stock/doctype/serial_no/serial_no.js @@ -18,3 +18,22 @@ cur_frm.cscript.onload = function() { frappe.ui.form.on("Serial No", "refresh", function(frm) { frm.toggle_enable("item_code", frm.doc.__islocal); }); + + +frappe.ui.form.on("Serial No", { + refresh(frm) { + frm.trigger("view_ledgers") + }, + + view_ledgers(frm) { + frm.add_custom_button(__("View Ledgers"), () => { + frappe.route_options = { + "item_code": frm.doc.item_code, + "serial_no": frm.doc.name, + "posting_date": frappe.datetime.now_date(), + "posting_time": frappe.datetime.now_time() + }; + frappe.set_route("query-report", "Serial No Ledger"); + }).addClass('btn-primary'); + } +}) \ No newline at end of file diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json index ed1b0af30a..b4ece00fe6 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.json +++ b/erpnext/stock/doctype/serial_no/serial_no.json @@ -269,7 +269,7 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Status", - "options": "\nActive\nInactive\nExpired", + "options": "\nActive\nInactive\nDelivered\nExpired", "read_only": 1 }, { @@ -280,7 +280,7 @@ "icon": "fa fa-barcode", "idx": 1, "links": [], - "modified": "2023-04-16 15:58:46.139887", + "modified": "2023-11-28 15:37:59.489945", "modified_by": "Administrator", "module": "Stock", "name": "Serial No", diff --git a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py index 7212b92bb3..ae12fbb3e4 100644 --- a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py +++ b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py @@ -36,21 +36,27 @@ def get_columns(filters): "fieldtype": "Link", "fieldname": "company", "options": "Company", - "width": 150, + "width": 120, }, { "label": _("Warehouse"), "fieldtype": "Link", "fieldname": "warehouse", "options": "Warehouse", - "width": 150, + "width": 120, + }, + { + "label": _("Status"), + "fieldtype": "Data", + "fieldname": "status", + "width": 120, }, { "label": _("Serial No"), "fieldtype": "Link", "fieldname": "serial_no", "options": "Serial No", - "width": 150, + "width": 130, }, { "label": _("Valuation Rate"), @@ -58,6 +64,12 @@ def get_columns(filters): "fieldname": "valuation_rate", "width": 150, }, + { + "label": _("Qty"), + "fieldtype": "Float", + "fieldname": "qty", + "width": 150, + }, ] return columns @@ -83,12 +95,16 @@ def get_data(filters): "posting_time": row.posting_time, "voucher_type": row.voucher_type, "voucher_no": row.voucher_no, + "status": "Active" if row.actual_qty > 0 else "Delivered", "company": row.company, "warehouse": row.warehouse, + "qty": 1 if row.actual_qty > 0 else -1, } ) - serial_nos = bundle_wise_serial_nos.get(row.serial_and_batch_bundle, []) + serial_nos = [{"serial_no": row.serial_no, "valuation_rate": row.valuation_rate}] + if row.serial_and_batch_bundle: + serial_nos = bundle_wise_serial_nos.get(row.serial_and_batch_bundle, []) for index, bundle_data in enumerate(serial_nos): if index == 0: diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index da98455b5c..de28be1c35 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -255,11 +255,15 @@ class SerialBatchBundle: if not serial_nos: return + status = "Inactive" + if self.sle.actual_qty < 0: + status = "Delivered" + sn_table = frappe.qb.DocType("Serial No") ( frappe.qb.update(sn_table) .set(sn_table.warehouse, warehouse) - .set(sn_table.status, "Active" if warehouse else "Inactive") + .set(sn_table.status, "Active" if warehouse else status) .where(sn_table.name.isin(serial_nos)) ).run() From 23b0b8ba36595f8d1a62e44f51967a4d9a56641f Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Tue, 28 Nov 2023 19:24:15 +0530 Subject: [PATCH 146/202] fix: create contact if existing customer doesn't have contact --- erpnext/crm/doctype/lead/lead.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index fdec88d70d..d22cc5548a 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -36,6 +36,15 @@ class Lead(SellingController, CRMNote): def before_insert(self): self.contact_doc = None if frappe.db.get_single_value("CRM Settings", "auto_creation_of_contact"): + if self.source == "Existing Customer" and self.customer: + contact = frappe.db.get_value( + "Dynamic Link", + {"link_doctype": "Customer", "link_name": self.customer}, + "parent", + ) + if contact: + self.contact_doc = frappe.get_doc("Contact", contact) + return self.contact_doc = self.create_contact() def after_insert(self): From 3e6306348ac564976fc8b0d3ef7ec12a8d9961cc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 28 Nov 2023 20:04:47 +0530 Subject: [PATCH 147/202] refactor: redefine dr_or_cr for unallocated amount --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index c732c0a1c5..e2e655befb 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1113,6 +1113,7 @@ class PaymentEntry(AccountsController): gl_entries.append(gle) if self.unallocated_amount: + dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" exchange_rate = self.get_exchange_rate() base_unallocated_amount = self.unallocated_amount * exchange_rate From 9fadf5f42678736567160bb2b06619383146d4ca Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Nov 2023 21:34:07 +0530 Subject: [PATCH 148/202] refactor: don't use `cur_frm` --- .../doctype/warranty_claim/warranty_claim.js | 55 +++++++------------ 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js index 32494efe53..10cb37f512 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.js +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js @@ -36,6 +36,26 @@ frappe.ui.form.on("Warranty Claim", { } }, + refresh: (frm) => { + frappe.dynamic_link = { + doc: frm.doc, + fieldname: "customer", + doctype: "Customer", + }; + + if ( + !frm.doc.__islocal && + ["Open", "Work In Progress"].includes(frm.doc.status) + ) { + frm.add_custom_button(__("Maintenance Visit"), () => { + frappe.model.open_mapped_doc({ + method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit", + frm: frm, + }); + }); + } + }, + customer: (frm) => { erpnext.utils.get_party_details(frm); }, @@ -48,38 +68,3 @@ frappe.ui.form.on("Warranty Claim", { erpnext.utils.get_contact_details(frm); }, }); - -erpnext.support.WarrantyClaim = class WarrantyClaim extends ( - frappe.ui.form.Controller -) { - refresh() { - frappe.dynamic_link = { - doc: this.frm.doc, - fieldname: "customer", - doctype: "Customer", - }; - - if ( - !cur_frm.doc.__islocal && - (cur_frm.doc.status == "Open" || - cur_frm.doc.status == "Work In Progress") - ) { - cur_frm.add_custom_button( - __("Maintenance Visit"), - this.make_maintenance_visit - ); - } - } - - make_maintenance_visit() { - frappe.model.open_mapped_doc({ - method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit", - frm: cur_frm, - }); - } -}; - -extend_cscript( - cur_frm.cscript, - new erpnext.support.WarrantyClaim({ frm: cur_frm }) -); From adfcdb3b652aa98db96b466371788f28ab8d26b7 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Tue, 28 Nov 2023 13:19:49 -0500 Subject: [PATCH 149/202] fix: don't consider cancelled entries --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 0344e3de9f..90109ea211 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1994,7 +1994,8 @@ def get_outstanding_on_journal_entry(name): "END as outstanding_amount " "FROM `tabGL Entry` WHERE (voucher_no=%s OR against_voucher=%s) " "AND party_type IS NOT NULL " - 'AND party_type != ""', + 'AND party_type != ""' + "AND is_cancelled = 0", (name, name), as_dict=1, ) From 2add802d0dbe61c536b5753f1d0f84b0896306cb Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 29 Nov 2023 08:59:14 +0530 Subject: [PATCH 150/202] refactor(test): advance allocation on purchase invoice --- .../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 322fc9f16b..e43ea6ecbe 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1747,6 +1747,7 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): paid_to="Creditors - _TC", paid_amount=500, ) + pe.save() # save trigger is needed for set_liability_account() to be executed pe.submit() pi = make_purchase_invoice( From 663bb8726c25005ab83a6ca4c82814b82a98a1e2 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Wed, 29 Nov 2023 09:03:47 +0530 Subject: [PATCH 151/202] fix(regional): use net figures for sales calc (#38260) --- erpnext/regional/report/uae_vat_201/uae_vat_201.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py index 59ef58bfde..6ef21e52ca 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -141,7 +141,7 @@ def get_total_emiratewise(filters): return frappe.db.sql( """ select - s.vat_emirate as emirate, sum(i.base_amount) as total, sum(i.tax_amount) + s.vat_emirate as emirate, sum(i.base_net_amount) as total, sum(i.tax_amount) from `tabSales Invoice Item` i inner join `tabSales Invoice` s on @@ -356,7 +356,7 @@ def get_zero_rated_total(filters): frappe.db.sql( """ select - sum(i.base_amount) as total + sum(i.base_net_amount) as total from `tabSales Invoice Item` i inner join `tabSales Invoice` s on @@ -383,7 +383,7 @@ def get_exempt_total(filters): frappe.db.sql( """ select - sum(i.base_amount) as total + sum(i.base_net_amount) as total from `tabSales Invoice Item` i inner join `tabSales Invoice` s on From 8e4b591ea2ad420a7c861a06414d3bee6e6ee042 Mon Sep 17 00:00:00 2001 From: Patrick Eissler <77415730+PatrickDEissler@users.noreply.github.com> Date: Wed, 29 Nov 2023 05:52:47 +0100 Subject: [PATCH 152/202] fix: make create button translatable (#38165) * fix: make all create buttons translatable * style: use double quotes --------- Co-authored-by: PatrickDenis-stack <77415730+PatrickDenis-stack@users.noreply.github.com> Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- erpnext/public/js/communication.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/communication.js b/erpnext/public/js/communication.js index 7ce8b0913c..f205d88965 100644 --- a/erpnext/public/js/communication.js +++ b/erpnext/public/js/communication.js @@ -13,7 +13,7 @@ frappe.ui.form.on("Communication", { frappe.confirm(__(confirm_msg, [__("Issue")]), () => { frm.trigger('make_issue_from_communication'); }) - }, "Create"); + }, __("Create")); } if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) { From 0255e09285d62eb9bfe80f56970e0dcaef4df17f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 29 Nov 2023 10:57:28 +0530 Subject: [PATCH 153/202] test: ledger pre and post reconciliation on advance as liability --- .../payment_entry/test_payment_entry.py | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index f4b0c55313..e77f4632b2 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -8,6 +8,7 @@ from frappe import qb from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, flt, nowdate +from erpnext.accounts.doctype.account.test_account import create_account from erpnext.accounts.doctype.payment_entry.payment_entry import ( InvalidPaymentEntry, get_outstanding_reference_documents, @@ -1358,6 +1359,140 @@ class TestPaymentEntry(FrappeTestCase): ] self.check_gl_entries() + def test_ledger_entries_for_advance_as_liability(self): + from erpnext.accounts.doctype.account.test_account import create_account + + company = "_Test Company" + + advance_account = create_account( + parent_account="Current Assets - _TC", + account_name="Advances Received", + company=company, + account_type="Liability", + ) + + frappe.db.set_value( + "Company", + company, + { + "book_advance_payments_in_separate_party_account": 1, + "default_advance_received_account": advance_account, + }, + ) + # Advance Payment + pe = create_payment_entry( + party_type="Customer", + party="_Test Customer", + payment_type="Receive", + paid_from="Debtors - _TC", + paid_to="_Test Cash - _TC", + ) + pe.save() # use save() to trigger set_liability_account() + pe.submit() + + # Normal Invoice + si = create_sales_invoice(qty=10, rate=100, customer="_Test Customer") + + pre_reconciliation_gle = [ + {"account": advance_account, "debit": 0.0, "credit": 1000.0}, + {"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0}, + ] + pre_reconciliation_ple = [ + { + "account": advance_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": -1000.0, + } + ] + + self.voucher_no = pe.name + self.expected_gle = pre_reconciliation_gle + self.expected_ple = pre_reconciliation_ple + self.check_gl_entries() + self.check_pl_entries() + + # Partially reconcile advance against invoice + pr = frappe.get_doc("Payment Reconciliation") + pr.company = company + pr.party_type = "Customer" + pr.party = "_Test Customer" + pr.receivable_payable_account = si.debit_to + pr.default_advance_account = advance_account + pr.get_unreconciled_entries() + + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + + invoices = [x.as_dict() for x in pr.get("invoices")] + payments = [x.as_dict() for x in pr.get("payments")] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.allocation[0].allocated_amount = 400 + pr.reconcile() + + # assert General and Payment Ledger entries post partial reconciliation + self.expected_gle = [ + {"account": si.debit_to, "debit": 0.0, "credit": 400.0}, + {"account": advance_account, "debit": 400.0, "credit": 0.0}, + {"account": advance_account, "debit": 0.0, "credit": 1000.0}, + {"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0}, + ] + self.expected_ple = [ + { + "account": advance_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": -1000.0, + }, + { + "account": si.debit_to, + "voucher_no": pe.name, + "against_voucher_no": si.name, + "amount": -400.0, + }, + { + "account": advance_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": 400.0, + }, + ] + self.check_gl_entries() + self.check_pl_entries() + + # Unreconcile + unrecon = ( + frappe.get_doc( + { + "doctype": "Unreconcile Payment", + "company": company, + "voucher_type": pe.doctype, + "voucher_no": pe.name, + "allocations": [{"reference_doctype": si.doctype, "reference_name": si.name}], + } + ) + .save() + .submit() + ) + + self.voucher_no = pe.name + self.expected_gle = pre_reconciliation_gle + self.expected_ple = pre_reconciliation_ple + self.check_gl_entries() + self.check_pl_entries() + + def check_pl_entries(self): + ple = frappe.qb.DocType("Payment Ledger Entry") + pl_entries = ( + frappe.qb.from_(ple) + .select(ple.account, ple.voucher_no, ple.against_voucher_no, ple.amount) + .where((ple.voucher_no == self.voucher_no) & (ple.delinked == 0)) + .orderby(ple.creation) + ).run(as_dict=True) + for row in range(len(self.expected_ple)): + for field in ["account", "voucher_no", "against_voucher_no", "amount"]: + self.assertEqual(self.expected_ple[row][field], pl_entries[row][field]) + def check_gl_entries(self): gle = frappe.qb.DocType("GL Entry") gl_entries = ( From fe5fc5bd3abfff57f85f62eac18f3ffc242baa4b Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Wed, 29 Nov 2023 12:14:12 +0530 Subject: [PATCH 154/202] feat: shift depreciation for assets (#38327) * feat: shift depreciation for assets * chore: create new asset depr schedule on shift change * refactor: move create_depr_schedule to after_insert * fix: args in get_depreciation_amount test * refactor: rename shift adjustment to shift allocation * chore: asset shift factor doctype and auto allocate shift diff * chore: use check instead of depr type, and add tests * chore: make linter happy * chore: give permissions to accounts users --- erpnext/assets/doctype/asset/asset.js | 41 ++- erpnext/assets/doctype/asset/asset.py | 1 + erpnext/assets/doctype/asset/test_asset.py | 7 +- .../asset_depreciation_schedule.js | 10 +- .../asset_depreciation_schedule.json | 11 +- .../asset_depreciation_schedule.py | 110 ++++++-- .../asset_finance_book.json | 10 +- .../asset_shift_allocation/__init__.py | 0 .../asset_shift_allocation.js | 14 + .../asset_shift_allocation.json | 111 ++++++++ .../asset_shift_allocation.py | 262 ++++++++++++++++++ .../test_asset_shift_allocation.py | 113 ++++++++ .../doctype/asset_shift_factor/__init__.py | 0 .../asset_shift_factor/asset_shift_factor.js | 8 + .../asset_shift_factor.json | 74 +++++ .../asset_shift_factor/asset_shift_factor.py | 24 ++ .../test_asset_shift_factor.py | 9 + .../depreciation_schedule.json | 9 +- ...sset_depreciation_schedules_from_assets.py | 1 + 19 files changed, 776 insertions(+), 39 deletions(-) create mode 100644 erpnext/assets/doctype/asset_shift_allocation/__init__.py create mode 100644 erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.js create mode 100644 erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.json create mode 100644 erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py create mode 100644 erpnext/assets/doctype/asset_shift_allocation/test_asset_shift_allocation.py create mode 100644 erpnext/assets/doctype/asset_shift_factor/__init__.py create mode 100644 erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.js create mode 100644 erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.json create mode 100644 erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py create mode 100644 erpnext/assets/doctype/asset_shift_factor/test_asset_shift_factor.py diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index d378fbd26a..58fd6d4ef8 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -214,30 +214,43 @@ frappe.ui.form.on('Asset', { }) }, - render_depreciation_schedule_view: function(frm, depr_schedule) { + render_depreciation_schedule_view: function(frm, asset_depr_schedule_doc) { let wrapper = $(frm.fields_dict["depreciation_schedule_view"].wrapper).empty(); let data = []; - depr_schedule.forEach((sch) => { + asset_depr_schedule_doc.depreciation_schedule.forEach((sch) => { const row = [ sch['idx'], frappe.format(sch['schedule_date'], { fieldtype: 'Date' }), frappe.format(sch['depreciation_amount'], { fieldtype: 'Currency' }), frappe.format(sch['accumulated_depreciation_amount'], { fieldtype: 'Currency' }), - sch['journal_entry'] || '' + sch['journal_entry'] || '', ]; + + if (asset_depr_schedule_doc.shift_based) { + row.push(sch['shift']); + } + data.push(row); }); + let columns = [ + {name: __("No."), editable: false, resizable: false, format: value => value, width: 60}, + {name: __("Schedule Date"), editable: false, resizable: false, width: 270}, + {name: __("Depreciation Amount"), editable: false, resizable: false, width: 164}, + {name: __("Accumulated Depreciation Amount"), editable: false, resizable: false, width: 164}, + ]; + + if (asset_depr_schedule_doc.shift_based) { + columns.push({name: __("Journal Entry"), editable: false, resizable: false, format: value => `${value}`, width: 245}); + columns.push({name: __("Shift"), editable: false, resizable: false, width: 59}); + } else { + columns.push({name: __("Journal Entry"), editable: false, resizable: false, format: value => `${value}`, width: 304}); + } + let datatable = new frappe.DataTable(wrapper.get(0), { - columns: [ - {name: __("No."), editable: false, resizable: false, format: value => value, width: 60}, - {name: __("Schedule Date"), editable: false, resizable: false, width: 270}, - {name: __("Depreciation Amount"), editable: false, resizable: false, width: 164}, - {name: __("Accumulated Depreciation Amount"), editable: false, resizable: false, width: 164}, - {name: __("Journal Entry"), editable: false, resizable: false, format: value => `${value}`, width: 304} - ], + columns: columns, data: data, layout: "fluid", serialNoColumn: false, @@ -272,8 +285,8 @@ frappe.ui.form.on('Asset', { asset_values.push(flt(frm.doc.gross_purchase_amount - frm.doc.opening_accumulated_depreciation, precision('gross_purchase_amount'))); } - let depr_schedule = (await frappe.call( - "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule", + let asset_depr_schedule_doc = (await frappe.call( + "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_asset_depr_schedule_doc", { asset_name: frm.doc.name, status: "Active", @@ -281,7 +294,7 @@ frappe.ui.form.on('Asset', { } )).message; - $.each(depr_schedule || [], function(i, v) { + $.each(asset_depr_schedule_doc.depreciation_schedule || [], function(i, v) { x_intervals.push(frappe.format(v.schedule_date, { fieldtype: 'Date' })); var asset_value = flt(frm.doc.gross_purchase_amount - v.accumulated_depreciation_amount, precision('gross_purchase_amount')); if(v.journal_entry) { @@ -296,7 +309,7 @@ frappe.ui.form.on('Asset', { }); frm.toggle_display(["depreciation_schedule_view"], 1); - frm.events.render_depreciation_schedule_view(frm, depr_schedule); + frm.events.render_depreciation_schedule_view(frm, asset_depr_schedule_doc); } else { if(frm.doc.opening_accumulated_depreciation) { x_intervals.push(frappe.format(frm.doc.creation.split(" ")[0], { fieldtype: 'Date' })); diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 7b7953b6ce..d1f03f2046 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -825,6 +825,7 @@ def get_item_details(item_code, asset_category, gross_purchase_amount): "total_number_of_depreciations": d.total_number_of_depreciations, "frequency_of_depreciation": d.frequency_of_depreciation, "daily_prorata_based": d.daily_prorata_based, + "shift_based": d.shift_based, "salvage_value_percentage": d.salvage_value_percentage, "expected_value_after_useful_life": flt(gross_purchase_amount) * flt(d.salvage_value_percentage / 100), diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index ca2b980579..dc80aa5c5c 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -1000,7 +1000,11 @@ class TestDepreciationBasics(AssetSetup): }, ) - depreciation_amount = get_depreciation_amount(asset, 100000, asset.finance_books[0]) + asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, "Active") + + depreciation_amount = get_depreciation_amount( + asset_depr_schedule_doc, asset, 100000, asset.finance_books[0] + ) self.assertEqual(depreciation_amount, 30000) def test_make_depr_schedule(self): @@ -1732,6 +1736,7 @@ def create_asset(**args): "expected_value_after_useful_life": args.expected_value_after_useful_life or 0, "depreciation_start_date": args.depreciation_start_date, "daily_prorata_based": args.daily_prorata_based or 0, + "shift_based": args.shift_based or 0, }, ) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js index 3d2dff179a..c99297d626 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.js @@ -8,11 +8,13 @@ frappe.ui.form.on('Asset Depreciation Schedule', { }, make_schedules_editable: function(frm) { - var is_editable = frm.doc.depreciation_method == "Manual" ? true : false; + var is_manual_hence_editable = frm.doc.depreciation_method === "Manual" ? true : false; + var is_shift_hence_editable = frm.doc.shift_based ? true : false; - frm.toggle_enable("depreciation_schedule", is_editable); - frm.fields_dict["depreciation_schedule"].grid.toggle_enable("schedule_date", is_editable); - frm.fields_dict["depreciation_schedule"].grid.toggle_enable("depreciation_amount", is_editable); + frm.toggle_enable("depreciation_schedule", is_manual_hence_editable || is_shift_hence_editable); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("schedule_date", is_manual_hence_editable); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("depreciation_amount", is_manual_hence_editable); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("shift", is_shift_hence_editable); } }); diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index 8d8b46321f..be35914251 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -20,6 +20,7 @@ "total_number_of_depreciations", "rate_of_depreciation", "daily_prorata_based", + "shift_based", "column_break_8", "frequency_of_depreciation", "expected_value_after_useful_life", @@ -184,12 +185,20 @@ "label": "Depreciate based on daily pro-rata", "print_hide": 1, "read_only": 1 + }, + { + "default": "0", + "depends_on": "eval:doc.depreciation_method == \"Straight Line\"", + "fieldname": "shift_based", + "fieldtype": "Check", + "label": "Depreciate based on shifts", + "read_only": 1 } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2023-11-03 21:32:15.021796", + "modified": "2023-11-29 00:57:00.461998", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 7305691f97..6e390ce6f8 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -26,6 +26,7 @@ class AssetDepreciationSchedule(Document): self.prepare_draft_asset_depr_schedule_data_from_asset_name_and_fb_name( self.asset, self.finance_book ) + self.update_shift_depr_schedule() def validate(self): self.validate_another_asset_depr_schedule_does_not_exist() @@ -73,6 +74,16 @@ class AssetDepreciationSchedule(Document): def on_cancel(self): self.db_set("status", "Cancelled") + def update_shift_depr_schedule(self): + if not self.shift_based or self.docstatus != 0: + return + + asset_doc = frappe.get_doc("Asset", self.asset) + fb_row = asset_doc.finance_books[self.finance_book_id - 1] + + self.make_depr_schedule(asset_doc, fb_row) + self.set_accumulated_depreciation(asset_doc, fb_row) + def prepare_draft_asset_depr_schedule_data_from_asset_name_and_fb_name(self, asset_name, fb_name): asset_doc = frappe.get_doc("Asset", asset_name) @@ -154,13 +165,14 @@ class AssetDepreciationSchedule(Document): self.rate_of_depreciation = row.rate_of_depreciation self.expected_value_after_useful_life = row.expected_value_after_useful_life self.daily_prorata_based = row.daily_prorata_based + self.shift_based = row.shift_based self.status = "Draft" def make_depr_schedule( self, asset_doc, row, - date_of_disposal, + date_of_disposal=None, update_asset_finance_book_row=True, value_after_depreciation=None, ): @@ -181,6 +193,8 @@ class AssetDepreciationSchedule(Document): num_of_depreciations_completed = 0 depr_schedule = [] + self.schedules_before_clearing = self.get("depreciation_schedule") + for schedule in self.get("depreciation_schedule"): if schedule.journal_entry: num_of_depreciations_completed += 1 @@ -246,6 +260,7 @@ class AssetDepreciationSchedule(Document): prev_depreciation_amount = 0 depreciation_amount = get_depreciation_amount( + self, asset_doc, value_after_depreciation, row, @@ -282,10 +297,7 @@ class AssetDepreciationSchedule(Document): ) if depreciation_amount > 0: - self.add_depr_schedule_row( - date_of_disposal, - depreciation_amount, - ) + self.add_depr_schedule_row(date_of_disposal, depreciation_amount, n) break @@ -369,10 +381,7 @@ class AssetDepreciationSchedule(Document): skip_row = True if flt(depreciation_amount, asset_doc.precision("gross_purchase_amount")) > 0: - self.add_depr_schedule_row( - schedule_date, - depreciation_amount, - ) + self.add_depr_schedule_row(schedule_date, depreciation_amount, n) # to ensure that final accumulated depreciation amount is accurate def get_adjusted_depreciation_amount( @@ -394,16 +403,22 @@ class AssetDepreciationSchedule(Document): def get_depreciation_amount_for_first_row(self): return self.get("depreciation_schedule")[0].depreciation_amount - def add_depr_schedule_row( - self, - schedule_date, - depreciation_amount, - ): + def add_depr_schedule_row(self, schedule_date, depreciation_amount, schedule_idx): + if self.shift_based: + shift = ( + self.schedules_before_clearing[schedule_idx].shift + if self.schedules_before_clearing and len(self.schedules_before_clearing) > schedule_idx + else frappe.get_cached_value("Asset Shift Factor", {"default": 1}, "shift_name") + ) + else: + shift = None + self.append( "depreciation_schedule", { "schedule_date": schedule_date, "depreciation_amount": depreciation_amount, + "shift": shift, }, ) @@ -445,6 +460,7 @@ class AssetDepreciationSchedule(Document): and i == max(straight_line_idx) - 1 and not date_of_disposal and not date_of_return + and not row.shift_based ): depreciation_amount += flt( value_after_depreciation - flt(row.expected_value_after_useful_life), @@ -527,6 +543,7 @@ def get_total_days(date, frequency): def get_depreciation_amount( + asset_depr_schedule, asset, depreciable_value, fb_row, @@ -537,7 +554,7 @@ def get_depreciation_amount( ): if fb_row.depreciation_method in ("Straight Line", "Manual"): return get_straight_line_or_manual_depr_amount( - asset, fb_row, schedule_idx, number_of_pending_depreciations + asset_depr_schedule, asset, fb_row, schedule_idx, number_of_pending_depreciations ) else: rate_of_depreciation = get_updated_rate_of_depreciation_for_wdv_and_dd( @@ -559,8 +576,11 @@ def get_updated_rate_of_depreciation_for_wdv_and_dd(asset, depreciable_value, fb def get_straight_line_or_manual_depr_amount( - asset, row, schedule_idx, number_of_pending_depreciations + asset_depr_schedule, asset, row, schedule_idx, number_of_pending_depreciations ): + if row.shift_based: + return get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx) + # if the Depreciation Schedule is being modified after Asset Repair due to increase in asset life and value if asset.flags.increase_in_asset_life: return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / ( @@ -655,6 +675,41 @@ def get_straight_line_or_manual_depr_amount( ) / flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked) +def get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx): + if asset_depr_schedule.get("__islocal") and not asset.flags.shift_allocation: + return ( + flt(asset.gross_purchase_amount) + - flt(asset.opening_accumulated_depreciation) + - flt(row.expected_value_after_useful_life) + ) / flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked) + + asset_shift_factors_map = get_asset_shift_factors_map() + shift = ( + asset_depr_schedule.schedules_before_clearing[schedule_idx].shift + if len(asset_depr_schedule.schedules_before_clearing) > schedule_idx + else None + ) + shift_factor = asset_shift_factors_map.get(shift) if shift else 0 + + shift_factors_sum = sum( + flt(asset_shift_factors_map.get(schedule.shift)) + for schedule in asset_depr_schedule.schedules_before_clearing + ) + + return ( + ( + flt(asset.gross_purchase_amount) + - flt(asset.opening_accumulated_depreciation) + - flt(row.expected_value_after_useful_life) + ) + / flt(shift_factors_sum) + ) * shift_factor + + +def get_asset_shift_factors_map(): + return dict(frappe.db.get_all("Asset Shift Factor", ["shift_name", "shift_factor"], as_list=True)) + + def get_wdv_or_dd_depr_amount( depreciable_value, rate_of_depreciation, @@ -803,7 +858,12 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones( def get_temp_asset_depr_schedule_doc( - asset_doc, row, date_of_disposal=None, date_of_return=None, update_asset_finance_book_row=False + asset_doc, + row, + date_of_disposal=None, + date_of_return=None, + update_asset_finance_book_row=False, + new_depr_schedule=None, ): current_asset_depr_schedule_doc = get_asset_depr_schedule_doc( asset_doc.name, "Active", row.finance_book @@ -818,6 +878,21 @@ def get_temp_asset_depr_schedule_doc( temp_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) + if new_depr_schedule: + temp_asset_depr_schedule_doc.depreciation_schedule = [] + + for schedule in new_depr_schedule: + temp_asset_depr_schedule_doc.append( + "depreciation_schedule", + { + "schedule_date": schedule.schedule_date, + "depreciation_amount": schedule.depreciation_amount, + "accumulated_depreciation_amount": schedule.accumulated_depreciation_amount, + "journal_entry": schedule.journal_entry, + "shift": schedule.shift, + }, + ) + temp_asset_depr_schedule_doc.prepare_draft_asset_depr_schedule_data( asset_doc, row, @@ -839,6 +914,7 @@ def get_depr_schedule(asset_name, status, finance_book=None): return asset_depr_schedule_doc.get("depreciation_schedule") +@frappe.whitelist() def get_asset_depr_schedule_doc(asset_name, status, finance_book=None): asset_depr_schedule_name = get_asset_depr_schedule_name(asset_name, status, finance_book) diff --git a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json index e597d5fe31..25ae7a492c 100644 --- a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json +++ b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json @@ -9,6 +9,7 @@ "depreciation_method", "total_number_of_depreciations", "daily_prorata_based", + "shift_based", "column_break_5", "frequency_of_depreciation", "depreciation_start_date", @@ -97,12 +98,19 @@ "fieldname": "daily_prorata_based", "fieldtype": "Check", "label": "Depreciate based on daily pro-rata" + }, + { + "default": "0", + "depends_on": "eval:doc.depreciation_method == \"Straight Line\"", + "fieldname": "shift_based", + "fieldtype": "Check", + "label": "Depreciate based on shifts" } ], "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-03 21:30:24.266601", + "modified": "2023-11-29 00:57:07.579777", "modified_by": "Administrator", "module": "Assets", "name": "Asset Finance Book", diff --git a/erpnext/assets/doctype/asset_shift_allocation/__init__.py b/erpnext/assets/doctype/asset_shift_allocation/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.js b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.js new file mode 100644 index 0000000000..54df69339b --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.js @@ -0,0 +1,14 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +frappe.ui.form.on('Asset Shift Allocation', { + onload: function(frm) { + frm.events.make_schedules_editable(frm); + }, + + make_schedules_editable: function(frm) { + frm.toggle_enable("depreciation_schedule", true); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("schedule_date", false); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("depreciation_amount", false); + frm.fields_dict["depreciation_schedule"].grid.toggle_enable("shift", true); + } +}); diff --git a/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.json b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.json new file mode 100644 index 0000000000..89fa298a74 --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.json @@ -0,0 +1,111 @@ +{ + "actions": [], + "autoname": "naming_series:", + "creation": "2023-11-24 15:07:44.652133", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "section_break_esaa", + "asset", + "naming_series", + "column_break_tdae", + "finance_book", + "amended_from", + "depreciation_schedule_section", + "depreciation_schedule" + ], + "fields": [ + { + "fieldname": "section_break_esaa", + "fieldtype": "Section Break" + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Asset Shift Allocation", + "print_hide": 1, + "read_only": 1, + "search_index": 1 + }, + { + "fieldname": "asset", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Asset", + "options": "Asset", + "reqd": 1 + }, + { + "fieldname": "column_break_tdae", + "fieldtype": "Column Break" + }, + { + "fieldname": "finance_book", + "fieldtype": "Link", + "label": "Finance Book", + "options": "Finance Book" + }, + { + "depends_on": "eval:!doc.__islocal", + "fieldname": "depreciation_schedule_section", + "fieldtype": "Section Break", + "label": "Depreciation Schedule" + }, + { + "fieldname": "depreciation_schedule", + "fieldtype": "Table", + "label": "Depreciation Schedule", + "options": "Depreciation Schedule" + }, + { + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Naming Series", + "options": "ACC-ASA-.YYYY.-", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "is_submittable": 1, + "links": [], + "modified": "2023-11-29 04:05:04.683518", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Shift Allocation", + "naming_rule": "By \"Naming Series\" field", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, + "submit": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py new file mode 100644 index 0000000000..d419ef4c84 --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py @@ -0,0 +1,262 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document +from frappe.utils import ( + add_months, + cint, + flt, + get_last_day, + get_link_to_form, + is_last_day_of_the_month, +) + +from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_asset_depr_schedule_doc, + get_asset_shift_factors_map, + get_temp_asset_depr_schedule_doc, +) + + +class AssetShiftAllocation(Document): + def after_insert(self): + self.fetch_and_set_depr_schedule() + + def validate(self): + self.asset_depr_schedule_doc = get_asset_depr_schedule_doc( + self.asset, "Active", self.finance_book + ) + + self.validate_invalid_shift_change() + self.update_depr_schedule() + + def on_submit(self): + self.create_new_asset_depr_schedule() + + def fetch_and_set_depr_schedule(self): + if self.asset_depr_schedule_doc: + if self.asset_depr_schedule_doc.shift_based: + for schedule in self.asset_depr_schedule_doc.get("depreciation_schedule"): + self.append( + "depreciation_schedule", + { + "schedule_date": schedule.schedule_date, + "depreciation_amount": schedule.depreciation_amount, + "accumulated_depreciation_amount": schedule.accumulated_depreciation_amount, + "journal_entry": schedule.journal_entry, + "shift": schedule.shift, + }, + ) + + self.flags.ignore_validate = True + self.save() + else: + frappe.throw( + _( + "Asset Depreciation Schedule for Asset {0} and Finance Book {1} is not using shift based depreciation" + ).format(self.asset, self.finance_book) + ) + else: + frappe.throw( + _("Asset Depreciation Schedule not found for Asset {0} and Finance Book {1}").format( + self.asset, self.finance_book + ) + ) + + def validate_invalid_shift_change(self): + if not self.get("depreciation_schedule") or self.docstatus == 1: + return + + for i, sch in enumerate(self.depreciation_schedule): + if ( + sch.journal_entry and self.asset_depr_schedule_doc.depreciation_schedule[i].shift != sch.shift + ): + frappe.throw( + _( + "Row {0}: Shift cannot be changed since the depreciation has already been processed" + ).format(i) + ) + + def update_depr_schedule(self): + if not self.get("depreciation_schedule") or self.docstatus == 1: + return + + self.allocate_shift_diff_in_depr_schedule() + + asset_doc = frappe.get_doc("Asset", self.asset) + fb_row = asset_doc.finance_books[self.asset_depr_schedule_doc.finance_book_id - 1] + + asset_doc.flags.shift_allocation = True + + temp_depr_schedule = get_temp_asset_depr_schedule_doc( + asset_doc, fb_row, new_depr_schedule=self.depreciation_schedule + ).get("depreciation_schedule") + + self.depreciation_schedule = [] + + for schedule in temp_depr_schedule: + self.append( + "depreciation_schedule", + { + "schedule_date": schedule.schedule_date, + "depreciation_amount": schedule.depreciation_amount, + "accumulated_depreciation_amount": schedule.accumulated_depreciation_amount, + "journal_entry": schedule.journal_entry, + "shift": schedule.shift, + }, + ) + + def allocate_shift_diff_in_depr_schedule(self): + asset_shift_factors_map = get_asset_shift_factors_map() + reverse_asset_shift_factors_map = { + asset_shift_factors_map[k]: k for k in asset_shift_factors_map + } + + original_shift_factors_sum = sum( + flt(asset_shift_factors_map.get(schedule.shift)) + for schedule in self.asset_depr_schedule_doc.depreciation_schedule + ) + + new_shift_factors_sum = sum( + flt(asset_shift_factors_map.get(schedule.shift)) for schedule in self.depreciation_schedule + ) + + diff = new_shift_factors_sum - original_shift_factors_sum + + if diff > 0: + for i, schedule in reversed(list(enumerate(self.depreciation_schedule))): + if diff <= 0: + break + + shift_factor = flt(asset_shift_factors_map.get(schedule.shift)) + + if shift_factor <= diff: + self.depreciation_schedule.pop() + diff -= shift_factor + else: + try: + self.depreciation_schedule[i].shift = reverse_asset_shift_factors_map.get( + shift_factor - diff + ) + diff = 0 + except Exception: + frappe.throw(_("Could not auto update shifts. Shift with shift factor {0} needed.")).format( + shift_factor - diff + ) + elif diff < 0: + shift_factors = list(asset_shift_factors_map.values()) + desc_shift_factors = sorted(shift_factors, reverse=True) + depr_schedule_len_diff = self.asset_depr_schedule_doc.total_number_of_depreciations - len( + self.depreciation_schedule + ) + subsets_result = [] + + if depr_schedule_len_diff > 0: + num_rows_to_add = depr_schedule_len_diff + + while not subsets_result and num_rows_to_add > 0: + find_subsets_with_sum(shift_factors, num_rows_to_add, abs(diff), [], subsets_result) + if subsets_result: + break + num_rows_to_add -= 1 + + if subsets_result: + for i in range(num_rows_to_add): + schedule_date = add_months( + self.depreciation_schedule[-1].schedule_date, + cint(self.asset_depr_schedule_doc.frequency_of_depreciation), + ) + + if is_last_day_of_the_month(self.depreciation_schedule[-1].schedule_date): + schedule_date = get_last_day(schedule_date) + + self.append( + "depreciation_schedule", + { + "schedule_date": schedule_date, + "shift": reverse_asset_shift_factors_map.get(subsets_result[0][i]), + }, + ) + + if depr_schedule_len_diff <= 0 or not subsets_result: + for i, schedule in reversed(list(enumerate(self.depreciation_schedule))): + diff = abs(diff) + + if diff <= 0: + break + + shift_factor = flt(asset_shift_factors_map.get(schedule.shift)) + + if shift_factor <= diff: + for sf in desc_shift_factors: + if sf - shift_factor <= diff: + self.depreciation_schedule[i].shift = reverse_asset_shift_factors_map.get(sf) + diff -= sf - shift_factor + break + else: + try: + self.depreciation_schedule[i].shift = reverse_asset_shift_factors_map.get( + shift_factor + diff + ) + diff = 0 + except Exception: + frappe.throw(_("Could not auto update shifts. Shift with shift factor {0} needed.")).format( + shift_factor + diff + ) + + def create_new_asset_depr_schedule(self): + new_asset_depr_schedule_doc = frappe.copy_doc(self.asset_depr_schedule_doc) + + new_asset_depr_schedule_doc.depreciation_schedule = [] + + for schedule in self.depreciation_schedule: + new_asset_depr_schedule_doc.append( + "depreciation_schedule", + { + "schedule_date": schedule.schedule_date, + "depreciation_amount": schedule.depreciation_amount, + "accumulated_depreciation_amount": schedule.accumulated_depreciation_amount, + "journal_entry": schedule.journal_entry, + "shift": schedule.shift, + }, + ) + + notes = _( + "This schedule was created when Asset {0}'s shifts were adjusted through Asset Shift Allocation {1}." + ).format( + get_link_to_form("Asset", self.asset), + get_link_to_form(self.doctype, self.name), + ) + + new_asset_depr_schedule_doc.notes = notes + + self.asset_depr_schedule_doc.flags.should_not_cancel_depreciation_entries = True + self.asset_depr_schedule_doc.cancel() + + new_asset_depr_schedule_doc.submit() + + add_asset_activity( + self.asset, + _("Asset's depreciation schedule updated after Asset Shift Allocation {0}").format( + get_link_to_form(self.doctype, self.name) + ), + ) + + +def find_subsets_with_sum(numbers, k, target_sum, current_subset, result): + if k == 0 and target_sum == 0: + result.append(current_subset.copy()) + return + if k <= 0 or target_sum <= 0 or not numbers: + return + + # Include the current number in the subset + find_subsets_with_sum( + numbers, k - 1, target_sum - numbers[0], current_subset + [numbers[0]], result + ) + + # Exclude the current number from the subset + find_subsets_with_sum(numbers[1:], k, target_sum, current_subset, result) diff --git a/erpnext/assets/doctype/asset_shift_allocation/test_asset_shift_allocation.py b/erpnext/assets/doctype/asset_shift_allocation/test_asset_shift_allocation.py new file mode 100644 index 0000000000..8d00a24f6b --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_allocation/test_asset_shift_allocation.py @@ -0,0 +1,113 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +import frappe +from frappe.tests.utils import FrappeTestCase +from frappe.utils import cstr + +from erpnext.assets.doctype.asset.test_asset import create_asset +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( + get_depr_schedule, +) + + +class TestAssetShiftAllocation(FrappeTestCase): + @classmethod + def setUpClass(cls): + create_asset_shift_factors() + + @classmethod + def tearDownClass(cls): + frappe.db.rollback() + + def test_asset_shift_allocation(self): + asset = create_asset( + calculate_depreciation=1, + available_for_use_date="2023-01-01", + purchase_date="2023-01-01", + gross_purchase_amount=120000, + depreciation_start_date="2023-01-31", + total_number_of_depreciations=12, + frequency_of_depreciation=1, + shift_based=1, + submit=1, + ) + + expected_schedules = [ + ["2023-01-31", 10000.0, 10000.0, "Single"], + ["2023-02-28", 10000.0, 20000.0, "Single"], + ["2023-03-31", 10000.0, 30000.0, "Single"], + ["2023-04-30", 10000.0, 40000.0, "Single"], + ["2023-05-31", 10000.0, 50000.0, "Single"], + ["2023-06-30", 10000.0, 60000.0, "Single"], + ["2023-07-31", 10000.0, 70000.0, "Single"], + ["2023-08-31", 10000.0, 80000.0, "Single"], + ["2023-09-30", 10000.0, 90000.0, "Single"], + ["2023-10-31", 10000.0, 100000.0, "Single"], + ["2023-11-30", 10000.0, 110000.0, "Single"], + ["2023-12-31", 10000.0, 120000.0, "Single"], + ] + + schedules = [ + [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount, d.shift] + for d in get_depr_schedule(asset.name, "Active") + ] + + self.assertEqual(schedules, expected_schedules) + + asset_shift_allocation = frappe.get_doc( + {"doctype": "Asset Shift Allocation", "asset": asset.name} + ).insert() + + schedules = [ + [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount, d.shift] + for d in asset_shift_allocation.get("depreciation_schedule") + ] + + self.assertEqual(schedules, expected_schedules) + + asset_shift_allocation = frappe.get_doc("Asset Shift Allocation", asset_shift_allocation.name) + asset_shift_allocation.depreciation_schedule[4].shift = "Triple" + asset_shift_allocation.save() + + schedules = [ + [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount, d.shift] + for d in asset_shift_allocation.get("depreciation_schedule") + ] + + expected_schedules = [ + ["2023-01-31", 10000.0, 10000.0, "Single"], + ["2023-02-28", 10000.0, 20000.0, "Single"], + ["2023-03-31", 10000.0, 30000.0, "Single"], + ["2023-04-30", 10000.0, 40000.0, "Single"], + ["2023-05-31", 20000.0, 60000.0, "Triple"], + ["2023-06-30", 10000.0, 70000.0, "Single"], + ["2023-07-31", 10000.0, 80000.0, "Single"], + ["2023-08-31", 10000.0, 90000.0, "Single"], + ["2023-09-30", 10000.0, 100000.0, "Single"], + ["2023-10-31", 10000.0, 110000.0, "Single"], + ["2023-11-30", 10000.0, 120000.0, "Single"], + ] + + self.assertEqual(schedules, expected_schedules) + + asset_shift_allocation.submit() + + schedules = [ + [cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount, d.shift] + for d in get_depr_schedule(asset.name, "Active") + ] + + self.assertEqual(schedules, expected_schedules) + + +def create_asset_shift_factors(): + shifts = [ + {"doctype": "Asset Shift Factor", "shift_name": "Half", "shift_factor": 0.5, "default": 0}, + {"doctype": "Asset Shift Factor", "shift_name": "Single", "shift_factor": 1, "default": 1}, + {"doctype": "Asset Shift Factor", "shift_name": "Double", "shift_factor": 1.5, "default": 0}, + {"doctype": "Asset Shift Factor", "shift_name": "Triple", "shift_factor": 2, "default": 0}, + ] + + for s in shifts: + frappe.get_doc(s).insert() diff --git a/erpnext/assets/doctype/asset_shift_factor/__init__.py b/erpnext/assets/doctype/asset_shift_factor/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.js b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.js new file mode 100644 index 0000000000..88887fea87 --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.js @@ -0,0 +1,8 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Asset Shift Factor", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.json b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.json new file mode 100644 index 0000000000..fd04ffc5d4 --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.json @@ -0,0 +1,74 @@ +{ + "actions": [], + "allow_rename": 1, + "autoname": "field:shift_name", + "creation": "2023-11-27 18:16:03.980086", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "shift_name", + "shift_factor", + "default" + ], + "fields": [ + { + "fieldname": "shift_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Shift Name", + "reqd": 1, + "unique": 1 + }, + { + "fieldname": "shift_factor", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Shift Factor", + "reqd": 1 + }, + { + "default": "0", + "fieldname": "default", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Default" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2023-11-29 04:04:24.272872", + "modified_by": "Administrator", + "module": "Assets", + "name": "Asset Shift Factor", + "naming_rule": "By fieldname", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py new file mode 100644 index 0000000000..4c275ce092 --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py @@ -0,0 +1,24 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ +from frappe.model.document import Document + + +class AssetShiftFactor(Document): + def validate(self): + self.validate_default() + + def validate_default(self): + if self.default: + existing_default_shift_factor = frappe.db.get_value( + "Asset Shift Factor", {"default": 1}, "name" + ) + + if existing_default_shift_factor: + frappe.throw( + _("Asset Shift Factor {0} is set as default currently. Please change it first.").format( + frappe.bold(existing_default_shift_factor) + ) + ) diff --git a/erpnext/assets/doctype/asset_shift_factor/test_asset_shift_factor.py b/erpnext/assets/doctype/asset_shift_factor/test_asset_shift_factor.py new file mode 100644 index 0000000000..75073673c0 --- /dev/null +++ b/erpnext/assets/doctype/asset_shift_factor/test_asset_shift_factor.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestAssetShiftFactor(FrappeTestCase): + pass diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json index 884e0c6cb2..ef706e8f25 100644 --- a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json @@ -12,6 +12,7 @@ "column_break_3", "accumulated_depreciation_amount", "journal_entry", + "shift", "make_depreciation_entry" ], "fields": [ @@ -57,11 +58,17 @@ "fieldname": "make_depreciation_entry", "fieldtype": "Button", "label": "Make Depreciation Entry" + }, + { + "fieldname": "shift", + "fieldtype": "Link", + "label": "Shift", + "options": "Asset Shift Factor" } ], "istable": 1, "links": [], - "modified": "2023-07-26 12:56:48.718736", + "modified": "2023-11-27 18:28:35.325376", "modified_by": "Administrator", "module": "Assets", "name": "Depreciation Schedule", diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py index 9a2a39fb78..793497b766 100644 --- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py +++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py @@ -86,6 +86,7 @@ def get_asset_finance_books_map(): afb.frequency_of_depreciation, afb.rate_of_depreciation, afb.expected_value_after_useful_life, + afb.shift_based, ) .where(asset.docstatus < 2) .orderby(afb.idx) From fddf341f444efa89f80ec0fcb4e35b9b840061f5 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 29 Nov 2023 12:21:11 +0530 Subject: [PATCH 155/202] fix: incorrect ordered qty for Subcontracting Order (#38415) --- .../tests/test_subcontracting_controller.py | 4 ++ .../subcontracting_order.py | 29 ++++++++- .../test_subcontracting_order.py | 62 +++++++++++++++++++ .../subcontracting_receipt.py | 6 +- 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py index 6b61ae949d..47762ac4cf 100644 --- a/erpnext/controllers/tests/test_subcontracting_controller.py +++ b/erpnext/controllers/tests/test_subcontracting_controller.py @@ -1001,6 +1001,7 @@ def make_subcontracted_items(): "Subcontracted Item SA5": {}, "Subcontracted Item SA6": {}, "Subcontracted Item SA7": {}, + "Subcontracted Item SA8": {}, } for item, properties in sub_contracted_items.items(): @@ -1020,6 +1021,7 @@ def make_raw_materials(): }, "Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"}, "Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"}, + "Subcontracted SRM Item 8": {}, } for item, properties in raw_materials.items(): @@ -1043,6 +1045,7 @@ def make_service_items(): "Subcontracted Service Item 5": {}, "Subcontracted Service Item 6": {}, "Subcontracted Service Item 7": {}, + "Subcontracted Service Item 8": {}, } for item, properties in service_items.items(): @@ -1066,6 +1069,7 @@ def make_bom_for_subcontracted_items(): "Subcontracted Item SA5": ["Subcontracted SRM Item 5"], "Subcontracted Item SA6": ["Subcontracted SRM Item 3"], "Subcontracted Item SA7": ["Subcontracted SRM Item 1"], + "Subcontracted Item SA8": ["Subcontracted SRM Item 8"], } for item_code, raw_materials in boms.items(): diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index faf0cadb75..70ca1c31f5 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -8,7 +8,7 @@ from frappe.utils import flt from erpnext.buying.doctype.purchase_order.purchase_order import is_subcontracting_order_created from erpnext.controllers.subcontracting_controller import SubcontractingController -from erpnext.stock.stock_balance import get_ordered_qty, update_bin_qty +from erpnext.stock.stock_balance import update_bin_qty from erpnext.stock.utils import get_bin @@ -114,7 +114,32 @@ class SubcontractingOrder(SubcontractingController): ): item_wh_list.append([item.item_code, item.warehouse]) for item_code, warehouse in item_wh_list: - update_bin_qty(item_code, warehouse, {"ordered_qty": get_ordered_qty(item_code, warehouse)}) + update_bin_qty( + item_code, warehouse, {"ordered_qty": self.get_ordered_qty(item_code, warehouse)} + ) + + @staticmethod + def get_ordered_qty(item_code, warehouse): + table = frappe.qb.DocType("Subcontracting Order") + child = frappe.qb.DocType("Subcontracting Order Item") + + query = ( + frappe.qb.from_(table) + .inner_join(child) + .on(table.name == child.parent) + .select((child.qty - child.received_qty) * child.conversion_factor) + .where( + (table.docstatus == 1) + & (child.item_code == item_code) + & (child.warehouse == warehouse) + & (child.qty > child.received_qty) + & (table.status != "Completed") + ) + ) + + query = query.run() + + return flt(query[0][0]) if query else 0 def update_reserved_qty_for_subcontracting(self): for item in self.supplied_items: diff --git a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py index 22fdc13cc1..3557858935 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py @@ -6,6 +6,7 @@ from collections import defaultdict import frappe from frappe.tests.utils import FrappeTestCase +from frappe.utils import flt from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_subcontracting_order from erpnext.controllers.subcontracting_controller import ( @@ -566,6 +567,67 @@ class TestSubcontractingOrder(FrappeTestCase): self.assertEqual(sco.status, "Closed") self.assertEqual(sco.supplied_items[0].returned_qty, 5) + def test_ordered_qty_for_subcontracting_order(self): + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 8", + "qty": 10, + "rate": 100, + "fg_item": "Subcontracted Item SA8", + "fg_item_qty": 10, + }, + ] + + ordered_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="ordered_qty", + ) + ordered_qty = flt(ordered_qty) + + sco = get_subcontracting_order(service_items=service_items) + sco.reload() + + new_ordered_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="ordered_qty", + ) + new_ordered_qty = flt(new_ordered_qty) + + self.assertEqual(ordered_qty + 10, new_ordered_qty) + + for row in sco.supplied_items: + make_stock_entry( + target="_Test Warehouse 1 - _TC", + item_code=row.rm_item_code, + qty=row.required_qty, + basic_rate=100, + ) + + scr = make_subcontracting_receipt(sco.name) + scr.submit() + + new_ordered_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="ordered_qty", + ) + + self.assertEqual(ordered_qty, new_ordered_qty) + + scr.reload() + scr.cancel() + + new_ordered_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="ordered_qty", + ) + + self.assertEqual(ordered_qty + 10, new_ordered_qty) + def create_subcontracting_order(**args): args = frappe._dict(args) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 8d705aa97d..ae64cc632a 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -95,12 +95,12 @@ class SubcontractingReceipt(SubcontractingController): ) self.update_status_updater_args() self.update_prevdoc_status() - self.update_stock_ledger() - self.make_gl_entries_on_cancel() - self.repost_future_sle_and_gle() self.delete_auto_created_batches() self.set_consumed_qty_in_subcontract_order() self.set_subcontracting_order_status() + self.update_stock_ledger() + self.make_gl_entries_on_cancel() + self.repost_future_sle_and_gle() self.update_status() def validate_items_qty(self): From 096a2c8cd0afafb28e916a5c9e92ef1eb041e0a3 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 12:46:31 +0530 Subject: [PATCH 156/202] chore: PR ref in SCR connections --- .../subcontracting_receipt/subcontracting_receipt.js | 4 ++++ .../subcontracting_receipt_dashboard.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 762cdc96af..86b4d9bf1c 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -11,6 +11,10 @@ frappe.ui.form.on('Subcontracting Receipt', { frm.get_field('supplied_items').grid.cannot_add_rows = true; frm.get_field('supplied_items').grid.only_sortable(); frm.trigger('set_queries'); + + frm.custom_make_buttons = { + 'Purchase Receipt': 'Purchase Receipt', + } }, on_submit(frm) { diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py index 4d15938e4b..6b67a1621a 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt_dashboard.py @@ -16,7 +16,13 @@ def get_data(): "transactions": [ { "label": _("Reference"), - "items": ["Subcontracting Order", "Purchase Order", "Quality Inspection", "Project"], + "items": [ + "Purchase Order", + "Purchase Receipt", + "Subcontracting Order", + "Quality Inspection", + "Project", + ], }, {"label": _("Returns"), "items": ["Subcontracting Receipt"]}, ], From 874766a82f1b31a55b8d5c9c998896748ad49cdf Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:07:39 +0530 Subject: [PATCH 157/202] fix: map warehouses in return SCR --- erpnext/controllers/sales_and_purchase_return.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index e91212b031..8e3a15a0ad 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -391,7 +391,10 @@ def make_return_doc( if doc.get("discount_amount"): doc.discount_amount = -1 * source.discount_amount - if doctype != "Subcontracting Receipt": + if doctype == "Subcontracting Receipt": + doc.set_warehouse = source.set_warehouse + doc.supplier_warehouse = source.supplier_warehouse + else: doc.run_method("calculate_taxes_and_totals") def update_item(source_doc, target_doc, source_parent): From 7145b040f12a62be9f0ac945c69ac221debd7c03 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:21:24 +0530 Subject: [PATCH 158/202] fix(ux): hide `Create Purchase Receipt` button for Subcontract Return --- .../subcontracting_receipt.js | 68 ++++++++++--------- .../subcontracting_receipt.py | 12 ++-- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 86b4d9bf1c..575c4eda73 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -52,49 +52,51 @@ frappe.ui.form.on('Subcontracting Receipt', { frappe.set_route('query-report', 'General Ledger'); }, __('View')); - frm.add_custom_button(__('Purchase Receipt'), () => { - frappe.model.open_mapped_doc({ - method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', - frm: frm, - freeze: true, - freeze_message: __('Creating Purchase Receipt ...') - }); - }, __('Create')); + if (frm.doc.is_return === 0) { + frm.add_custom_button(__('Purchase Receipt'), () => { + frappe.model.open_mapped_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_purchase_receipt', + frm: frm, + freeze: true, + freeze_message: __('Creating Purchase Receipt ...') + }); + }, __('Create')); + } } if (!frm.doc.is_return && frm.doc.docstatus === 1 && frm.doc.per_returned < 100) { frm.add_custom_button(__('Subcontract Return'), () => { - frappe.model.open_mapped_doc({ - method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_subcontract_return', - frm: frm - }); - }, __('Create')); + frappe.model.open_mapped_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_receipt.subcontracting_receipt.make_subcontract_return', + frm: frm + }); + }, __('Create')); frm.page.set_inner_btn_group_as_primary(__('Create')); } if (frm.doc.docstatus === 0) { frm.add_custom_button(__('Subcontracting Order'), () => { - if (!frm.doc.supplier) { - frappe.throw({ - title: __('Mandatory'), - message: __('Please Select a Supplier') - }); - } - - erpnext.utils.map_current_doc({ - method: 'erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.make_subcontracting_receipt', - source_doctype: 'Subcontracting Order', - target: frm, - setters: { - supplier: frm.doc.supplier, - }, - get_query_filters: { - docstatus: 1, - per_received: ['<', 100], - company: frm.doc.company - } + if (!frm.doc.supplier) { + frappe.throw({ + title: __('Mandatory'), + message: __('Please Select a Supplier') }); - }, __('Get Items From')); + } + + erpnext.utils.map_current_doc({ + method: 'erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.make_subcontracting_receipt', + source_doctype: 'Subcontracting Order', + target: frm, + setters: { + supplier: frm.doc.supplier, + }, + get_query_filters: { + docstatus: 1, + per_received: ['<', 100], + company: frm.doc.company + } + }); + }, __('Get Items From')); frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty', 'read_only', frm.doc.__onload && frm.doc.__onload.backflush_based_on === 'BOM'); } diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 000078f241..4f4a65044d 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -545,9 +545,11 @@ def make_subcontract_return(source_name, target_doc=None): @frappe.whitelist() def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False, notify=False): if isinstance(source_name, str): - source_name = frappe.get_doc("Subcontracting Receipt", source_name) + source_doc = frappe.get_doc("Subcontracting Receipt", source_name) + else: + source_doc = source_name - if not source_name.is_return: + if not source_doc.is_return: if not target_doc: target_doc = frappe.new_doc("Purchase Receipt") target_doc.is_subcontracted = 1 @@ -555,7 +557,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False target_doc = get_mapped_doc( "Subcontracting Receipt", - source_name.name, + source_doc.name, { "Subcontracting Receipt": { "doctype": "Purchase Receipt", @@ -573,7 +575,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False ) po_items_details = {} - for item in source_name.items: + for item in source_doc.items: if item.purchase_order and item.purchase_order_item: if item.purchase_order not in po_items_details: po_doc = frappe.get_doc("Purchase Order", item.purchase_order) @@ -599,7 +601,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False if not target_doc.items: frappe.throw( _("Purchase Order Item reference is missing in Subcontracting Receipt {0}").format( - source_name.name + source_doc.name ) ) From 857f2b5a014b4d14d21bca793ea569f8bdc1c398 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:39:02 +0530 Subject: [PATCH 159/202] chore: `linter` --- .../subcontracting_order/subcontracting_order.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index cc99085486..33a2061320 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -123,6 +123,8 @@ class SubcontractingOrder(SubcontractingController): stock_bin.update_reserved_qty_for_sub_contracting() def populate_items_table(self): + items = [] + for si in self.service_items: if si.fg_item: item = frappe.get_doc("Item", si.fg_item) @@ -132,8 +134,8 @@ class SubcontractingOrder(SubcontractingController): ) or item.default_bom ) - self.append( - "items", + + items.append( { "item_code": item.item_code, "item_name": item.item_name, @@ -143,7 +145,7 @@ class SubcontractingOrder(SubcontractingController): "stock_uom": item.stock_uom, "bom": bom, "purchase_order_item": si.purchase_order_item, - }, + } ) else: frappe.throw( @@ -152,6 +154,10 @@ class SubcontractingOrder(SubcontractingController): ) ) + if items: + for item in items: + self.append("items", item) + self.set_missing_values() def update_status(self, status=None, update_modified=True): From 68585f6f2b05e0b8dc3429741950ef31bbc42e17 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 13:58:21 +0530 Subject: [PATCH 160/202] test: auto create SCO on PO submit --- .../purchase_order/test_purchase_order.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 0f8574c84d..f80a00a95f 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -981,6 +981,38 @@ class TestPurchaseOrder(FrappeTestCase): self.assertEqual(po.items[0].qty, 30) self.assertEqual(po.items[0].fg_item_qty, 30) + @change_settings("Buying Settings", {"auto_create_subcontracting_order": 1}) + def test_auto_create_subcontracting_order(self): + from erpnext.controllers.tests.test_subcontracting_controller import ( + make_bom_for_subcontracted_items, + make_raw_materials, + make_service_items, + make_subcontracted_items, + ) + + make_subcontracted_items() + make_raw_materials() + make_service_items() + make_bom_for_subcontracted_items() + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 7", + "qty": 10, + "rate": 100, + "fg_item": "Subcontracted Item SA7", + "fg_item_qty": 10, + }, + ] + po = create_purchase_order( + rm_items=service_items, + is_subcontracted=1, + supplier_warehouse="_Test Warehouse 1 - _TC", + ) + + self.assertTrue(frappe.db.get_value("Subcontracting Order", {"purchase_order": po.name})) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier From 7b0cd03f88a7052460438ee70390799fae5c336c Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 14:10:48 +0530 Subject: [PATCH 161/202] test: auto create PR on SCR submit --- .../subcontracting_receipt.py | 4 +-- .../test_subcontracting_receipt.py | 29 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 4f4a65044d..4d7b15717e 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -586,8 +586,8 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False item_row = { "item_code": po_item.item_code, "item_name": po_item.item_name, - "qty": item.qty * conversion_factor, - "rejected_qty": item.rejected_qty * conversion_factor, + "qty": flt(item.qty) * conversion_factor, + "rejected_qty": flt(item.rejected_qty) * conversion_factor, "uom": po_item.uom, "rate": po_item.rate, "warehouse": item.warehouse, diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index f0e4e00074..1d007fe3c8 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -5,7 +5,7 @@ import copy import frappe -from frappe.tests.utils import FrappeTestCase +from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, cint, cstr, flt, nowtime, today import erpnext @@ -953,6 +953,33 @@ class TestSubcontractingReceipt(FrappeTestCase): scr.submit() + @change_settings("Buying Settings", {"auto_create_purchase_receipt": 1}) + def test_auto_create_purchase_receipt(self): + fg_item = "Subcontracted Item SA1" + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 1", + "qty": 5, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 5, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + rm_items = get_rm_items(sco.supplied_items) + itemwise_details = make_stock_in_entry(rm_items=rm_items) + make_stock_transfer_entry( + sco_no=sco.name, + rm_items=rm_items, + itemwise_details=copy.deepcopy(itemwise_details), + ) + scr = make_subcontracting_receipt(sco.name) + scr.save() + scr.submit() + + self.assertTrue(frappe.db.get_value("Purchase Receipt", {"subcontracting_receipt": scr.name})) + def make_return_subcontracting_receipt(**args): args = frappe._dict(args) From 97be527ee9693b41d42bf06da96526f508ccc59a Mon Sep 17 00:00:00 2001 From: Nandhinidevi123 Date: Wed, 29 Nov 2023 17:21:51 +0530 Subject: [PATCH 162/202] fix:change default qty --- .../doctype/serial_and_batch_bundle/serial_and_batch_bundle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index abdbeb496b..3c824fd590 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1018,7 +1018,7 @@ def update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=Non doc.append( "entries", { - "qty": d.get("qty") * (1 if doc.type_of_transaction == "Inward" else -1), + "qty": (d.get("qty") or 1.0) * (1 if doc.type_of_transaction == "Inward" else -1), "warehouse": warehouse or d.get("warehouse"), "batch_no": d.get("batch_no"), "serial_no": d.get("serial_no"), From 3da0aa6a0b21c775e5356ae7d359f7378f190d92 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 17:35:21 +0530 Subject: [PATCH 163/202] fix(test): `test_auto_create_purchase_receipt` --- .../doctype/subcontracting_receipt/subcontracting_receipt.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 4d7b15717e..33e5c3ad0f 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -574,6 +574,8 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False ignore_child_tables=True, ) + target_doc.currency = frappe.get_cached_value("Company", target_doc.company, "default_currency") + po_items_details = {} for item in source_doc.items: if item.purchase_order and item.purchase_order_item: @@ -586,6 +588,7 @@ def make_purchase_receipt(source_name, target_doc=None, save=False, submit=False item_row = { "item_code": po_item.item_code, "item_name": po_item.item_name, + "conversion_factor": conversion_factor, "qty": flt(item.qty) * conversion_factor, "rejected_qty": flt(item.rejected_qty) * conversion_factor, "uom": po_item.uom, From ef8e4191cda22e148e9319758ab6624d76a4ae2f Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 29 Nov 2023 18:25:52 +0530 Subject: [PATCH 164/202] fix: set cwip account before asset tests --- .../asset_value_adjustment/test_asset_value_adjustment.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py index 5d49759727..2c97baece5 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py @@ -18,6 +18,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu class TestAssetValueAdjustment(unittest.TestCase): def setUp(self): create_asset_data() + frappe.db.set_value( + "Company", "_Test Company", "capital_work_in_progress_account", "CWIP Account - _TC" + ) def test_current_asset_value(self): pr = make_purchase_receipt( From abc7d3002467946984be5b41d79024da92047dd3 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 29 Nov 2023 19:49:58 +0530 Subject: [PATCH 165/202] fix(ux): make `basic_rate` field read-only based on purpose --- erpnext/stock/doctype/stock_entry/stock_entry.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index d37e8ee599..7334b356ee 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -258,7 +258,7 @@ frappe.ui.form.on('Stock Entry', { } } - if (frm.doc.docstatus===0) { + if (frm.doc.docstatus === 0) { frm.add_custom_button(__('Purchase Invoice'), function() { erpnext.utils.map_current_doc({ method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_stock_entry", @@ -311,7 +311,8 @@ frappe.ui.form.on('Stock Entry', { }) }, __("Get Items From")); } - if (frm.doc.docstatus===0 && frm.doc.purpose == "Material Issue") { + + if (frm.doc.docstatus === 0 && frm.doc.purpose == "Material Issue") { frm.add_custom_button(__('Expired Batches'), function() { frappe.call({ method: "erpnext.stock.doctype.stock_entry.stock_entry.get_expired_batch_items", @@ -397,6 +398,10 @@ frappe.ui.form.on('Stock Entry', { frm.remove_custom_button('Bill of Materials', "Get Items From"); frm.events.show_bom_custom_button(frm); frm.trigger('add_to_transit'); + + frm.fields_dict.items.grid.update_docfield_property( + 'basic_rate', 'read_only', frm.doc.purpose == "Material Receipt" ? 0 : 1 + ); }, purpose: function(frm) { From ff27cccff42f9f4cd54aa6071a71687d5183091a Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Wed, 29 Nov 2023 20:59:23 +0000 Subject: [PATCH 166/202] refactor: get outstanding journal entry using query builder --- .../doctype/payment_entry/payment_entry.py | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 90109ea211..70d8d6d7bf 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -9,6 +9,8 @@ import frappe from frappe import ValidationError, _, qb, scrub, throw from frappe.utils import cint, comma_or, flt, getdate, nowdate from frappe.utils.data import comma_and, fmt_money +from pypika import Case +from pypika.functions import Coalesce, Sum import erpnext from erpnext.accounts.doctype.bank_account.bank_account import ( @@ -1986,19 +1988,24 @@ def get_company_defaults(company): def get_outstanding_on_journal_entry(name): - res = frappe.db.sql( - "SELECT " - 'CASE WHEN party_type IN ("Customer") ' - "THEN ifnull(sum(debit_in_account_currency - credit_in_account_currency), 0) " - "ELSE ifnull(sum(credit_in_account_currency - debit_in_account_currency), 0) " - "END as outstanding_amount " - "FROM `tabGL Entry` WHERE (voucher_no=%s OR against_voucher=%s) " - "AND party_type IS NOT NULL " - 'AND party_type != ""' - "AND is_cancelled = 0", - (name, name), - as_dict=1, - ) + gl = frappe.qb.DocType("GL Entry") + res = ( + frappe.qb.from_(gl) + .select( + Case() + .when( + gl.party_type == "Customer", + Coalesce(Sum(gl.debit_in_account_currency - gl.credit_in_account_currency), 0), + ) + .else_(Coalesce(Sum(gl.credit_in_account_currency - gl.debit_in_account_currency), 0)) + .as_("outstanding_amount") + ) + .where( + (Coalesce(gl.party_type, "") != "") + & (gl.is_cancelled == 0) + & ((gl.voucher_no == name) | (gl.against_voucher == name)) + ) + ).run(as_dict=True) outstanding_amount = res[0].get("outstanding_amount", 0) if res else 0 From 1423b38d50faa8b2f44cab9626a837037e1d0570 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 30 Nov 2023 11:43:28 +0530 Subject: [PATCH 167/202] fix: use `docstatus` instead of `status` --- erpnext/buying/doctype/purchase_order/purchase_order.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index f000185393..4b121a806d 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -770,8 +770,8 @@ def get_mapped_subcontracting_order(source_name, target_doc=None): @frappe.whitelist() def is_subcontracting_order_created(po_name) -> bool: - count = frappe.db.count( - "Subcontracting Order", {"purchase_order": po_name, "status": ["not in", ["Draft", "Cancelled"]]} + return ( + True + if frappe.db.exists("Subcontracting Order", {"purchase_order": po_name, "docstatus": ["=", 1]}) + else False ) - - return True if count else False From 96b13c59c13350acdf0bef8374a587cd572c00ae Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Thu, 30 Nov 2023 06:20:15 +0000 Subject: [PATCH 168/202] fix(pe): show split alert only on splitting --- .../accounts/doctype/payment_entry/payment_entry.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 0344e3de9f..fe432d0f9a 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1698,12 +1698,13 @@ def split_invoices_based_on_payment_terms(outstanding_invoices, company) -> list if not split_rows: continue - frappe.msgprint( - _("Splitting {0} {1} into {2} rows as per Payment Terms").format( - _(entry.voucher_type), frappe.bold(entry.voucher_no), len(split_rows) - ), - alert=True, - ) + if len(split_rows) > 1: + frappe.msgprint( + _("Splitting {0} {1} into {2} rows as per Payment Terms").format( + _(entry.voucher_type), frappe.bold(entry.voucher_no), len(split_rows) + ), + alert=True, + ) outstanding_invoices_after_split += split_rows continue From 62b4a263f86a15dc39cd62b4fa39df87f0ec0dfa Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 30 Nov 2023 12:07:52 +0530 Subject: [PATCH 169/202] fix: exploded items in Subcontracting Receipt --- .../subcontracting_receipt_item.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json index 35a79a9308..9bfc2fdb7a 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json @@ -42,6 +42,7 @@ "column_break_40", "rejected_warehouse", "bom", + "include_exploded_items", "quality_inspection", "schedule_date", "reference_name", @@ -538,12 +539,19 @@ "options": "Purchase Order", "read_only": 1, "search_index": 1 + }, + { + "default": "0", + "fieldname": "include_exploded_items", + "fieldtype": "Check", + "label": "Include Exploded Items", + "print_hide": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-23 17:38:55.134685", + "modified": "2023-11-30 12:05:51.920705", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Receipt Item", From cfd3230c75b5e549b98b2362947ee8744c98e920 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 30 Nov 2023 12:22:55 +0530 Subject: [PATCH 170/202] refactor: pass on filter to upfront outstanding query as well --- erpnext/accounts/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 9d32a03931..4f2a9460e7 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1846,6 +1846,8 @@ class QueryPaymentLedger(object): .where(ple.delinked == 0) .where(Criterion.all(filter_on_against_voucher_no)) .where(Criterion.all(self.common_filter)) + .where(Criterion.all(self.dimensions_filter)) + .where(Criterion.all(self.voucher_posting_date)) .groupby(ple.against_voucher_type, ple.against_voucher_no, ple.party_type, ple.party) .orderby(ple.posting_date, ple.voucher_no) .having(qb.Field("amount_in_account_currency") > 0) From 1da9087cc4e0a411a820b817d0a1c657981be84e Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 30 Nov 2023 13:28:55 +0530 Subject: [PATCH 171/202] refactor: Simpler log settings setup (#38449) Depends on https://github.com/frappe/frappe/pull/23507 --- erpnext/hooks.py | 5 +++++ erpnext/patches.txt | 1 - erpnext/patches/v14_0/setup_clear_repost_logs.py | 8 -------- erpnext/setup/install.py | 8 -------- 4 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 erpnext/patches/v14_0/setup_clear_repost_logs.py diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 857471f1fd..60ec49587c 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -638,3 +638,8 @@ additional_timeline_content = { extend_bootinfo = [ "erpnext.support.doctype.service_level_agreement.service_level_agreement.add_sla_doctypes", ] + + +default_log_clearing_doctypes = { + "Repost Item Valuation": 60, +} diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a73502de5b..0de100a883 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -304,7 +304,6 @@ erpnext.patches.v13_0.drop_unused_sle_index_parts erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization erpnext.patches.v14_0.update_partial_tds_fields erpnext.patches.v14_0.create_incoterms_and_migrate_shipment -erpnext.patches.v14_0.setup_clear_repost_logs erpnext.patches.v14_0.create_accounting_dimensions_for_payment_request erpnext.patches.v14_0.update_entry_type_for_journal_entry erpnext.patches.v14_0.change_autoname_for_tax_withheld_vouchers diff --git a/erpnext/patches/v14_0/setup_clear_repost_logs.py b/erpnext/patches/v14_0/setup_clear_repost_logs.py deleted file mode 100644 index be9ddcab7a..0000000000 --- a/erpnext/patches/v14_0/setup_clear_repost_logs.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors -# License: MIT. See LICENSE - -from erpnext.setup.install import setup_log_settings - - -def execute(): - setup_log_settings() diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index b106cfcc1a..5b993fa64b 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -31,7 +31,6 @@ def after_install(): add_company_to_session_defaults() add_standard_navbar_items() add_app_name() - setup_log_settings() hide_workspaces() update_roles() frappe.db.commit() @@ -221,13 +220,6 @@ def add_app_name(): frappe.db.set_single_value("System Settings", "app_name", "ERPNext") -def setup_log_settings(): - log_settings = frappe.get_single("Log Settings") - log_settings.append("logs_to_clear", {"ref_doctype": "Repost Item Valuation", "days": 60}) - - log_settings.save(ignore_permissions=True) - - def hide_workspaces(): for ws in ["Integration", "Settings"]: frappe.db.set_value("Workspace", ws, "public", 0) From 63313eef6f6618f52c7e6194f7abd345cf920b15 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 30 Nov 2023 13:53:48 +0530 Subject: [PATCH 172/202] feat: enable automatic type annotations (#38452) --- erpnext/accounts/doctype/account/account.py | 59 ++++++ .../account_closing_balance.py | 23 +++ .../accounting_dimension.py | 19 ++ .../accounting_dimension_detail.py | 20 ++ .../accounting_dimension_filter.py | 22 +++ .../accounting_period/accounting_period.py | 17 ++ .../accounts_settings/accounts_settings.py | 46 +++++ .../doctype/advance_tax/advance_tax.py | 18 ++ .../advance_taxes_and_charges.py | 29 +++ .../allowed_dimension/allowed_dimension.py | 15 ++ .../allowed_to_transact_with.py | 14 ++ .../applicable_on_account.py | 15 ++ erpnext/accounts/doctype/bank/bank.py | 19 ++ .../doctype/bank_account/bank_account.py | 27 +++ .../bank_account_subtype.py | 11 ++ .../bank_account_type/bank_account_type.py | 11 ++ .../doctype/bank_clearance/bank_clearance.py | 22 +++ .../bank_clearance_detail.py | 21 ++ .../doctype/bank_guarantee/bank_guarantee.py | 34 ++++ .../bank_reconciliation_tool.py | 20 ++ .../bank_statement_import.py | 24 +++ .../bank_transaction/bank_transaction.py | 35 ++++ .../bank_transaction_mapping.py | 15 ++ .../bank_transaction_payments.py | 17 ++ erpnext/accounts/doctype/budget/budget.py | 30 +++ .../doctype/budget_account/budget_account.py | 15 ++ .../doctype/campaign_item/campaign_item.py | 14 ++ .../cashier_closing/cashier_closing.py | 26 +++ .../cashier_closing_payments.py | 15 ++ .../chart_of_accounts_importer.py | 12 ++ .../cheque_print_template.py | 35 ++++ .../closed_document/closed_document.py | 15 ++ .../doctype/cost_center/cost_center.py | 19 ++ .../cost_center_allocation.py | 19 ++ .../cost_center_allocation_percentage.py | 15 ++ .../doctype/coupon_code/coupon_code.py | 21 ++ .../currency_exchange_settings.py | 24 +++ .../currency_exchange_settings_details.py | 15 ++ .../currency_exchange_settings_result.py | 14 ++ .../customer_group_item.py | 14 ++ .../doctype/customer_item/customer_item.py | 14 ++ .../discounted_invoice/discounted_invoice.py | 18 ++ erpnext/accounts/doctype/dunning/dunning.py | 46 +++++ .../dunning_letter_text.py | 17 ++ .../doctype/dunning_type/dunning_type.py | 20 ++ .../exchange_rate_revaluation.py | 22 +++ .../exchange_rate_revaluation_account.py | 25 +++ .../doctype/finance_book/finance_book.py | 11 ++ .../doctype/fiscal_year/fiscal_year.py | 19 ++ .../fiscal_year_company.py | 14 ++ erpnext/accounts/doctype/gl_entry/gl_entry.py | 41 ++++ .../invoice_discounting.py | 28 +++ .../item_tax_template/item_tax_template.py | 18 ++ .../item_tax_template_detail.py | 15 ++ .../doctype/journal_entry/journal_entry.py | 72 +++++++ .../journal_entry_account.py | 52 +++++ .../journal_entry_template.py | 35 ++++ .../journal_entry_template_account.py | 14 ++ .../doctype/ledger_merge/ledger_merge.py | 21 ++ .../ledger_merge_accounts.py | 16 ++ .../loyalty_point_entry.py | 21 ++ .../loyalty_point_entry_redemption.py | 16 ++ .../loyalty_program/loyalty_program.py | 27 +++ .../loyalty_program_collection.py | 16 ++ .../mode_of_payment/mode_of_payment.py | 18 ++ .../mode_of_payment_account.py | 15 ++ .../monthly_distribution.py | 17 ++ .../monthly_distribution_percentage.py | 15 ++ .../opening_invoice_creation_tool.py | 19 ++ .../opening_invoice_creation_tool_item.py | 23 +++ .../overdue_payment/overdue_payment.py | 27 +++ .../doctype/party_account/party_account.py | 16 ++ .../accounts/doctype/party_link/party_link.py | 14 ++ .../payment_entry_deduction.py | 17 ++ .../payment_entry_reference.py | 24 +++ .../payment_gateway_account.py | 16 ++ .../payment_ledger_entry.py | 29 +++ .../doctype/payment_order/payment_order.py | 24 +++ .../payment_order_reference.py | 22 +++ .../payment_reconciliation.py | 42 ++++ .../payment_reconciliation_allocation.py | 28 +++ .../payment_reconciliation_invoice.py | 20 ++ .../payment_reconciliation_payment.py | 24 +++ .../payment_request/payment_request.py | 59 ++++++ .../payment_schedule/payment_schedule.py | 26 +++ .../doctype/payment_term/payment_term.py | 29 +++ .../payment_terms_template.py | 17 ++ .../payment_terms_template_detail.py | 32 +++ .../period_closing_voucher.py | 20 ++ .../pos_closing_entry/pos_closing_entry.py | 37 ++++ .../pos_closing_entry_detail.py | 18 ++ .../pos_closing_entry_taxes.py | 16 ++ .../pos_customer_group/pos_customer_group.py | 14 ++ .../accounts/doctype/pos_field/pos_field.py | 20 ++ .../doctype/pos_invoice/pos_invoice.py | 163 ++++++++++++++++ .../pos_invoice_item/pos_invoice_item.py | 80 ++++++++ .../pos_invoice_merge_log.py | 24 +++ .../pos_invoice_reference.py | 19 ++ .../doctype/pos_item_group/pos_item_group.py | 14 ++ .../pos_opening_entry/pos_opening_entry.py | 25 +++ .../pos_opening_entry_detail.py | 15 ++ .../pos_payment_method/pos_payment_method.py | 16 ++ .../doctype/pos_profile/pos_profile.py | 51 +++++ .../pos_profile_user/pos_profile_user.py | 15 ++ .../pos_search_fields/pos_search_fields.py | 15 ++ .../doctype/pos_settings/pos_settings.py | 15 ++ .../doctype/pricing_rule/pricing_rule.py | 109 +++++++++++ .../pricing_rule_brand/pricing_rule_brand.py | 15 ++ .../pricing_rule_detail.py | 19 ++ .../pricing_rule_item_code.py | 15 ++ .../pricing_rule_item_group.py | 15 ++ .../process_deferred_accounting.py | 17 ++ .../process_payment_reconciliation.py | 25 +++ .../process_payment_reconciliation_log.py | 24 +++ ..._payment_reconciliation_log_allocations.py | 27 +++ .../process_statement_of_accounts.py | 54 ++++++ .../process_statement_of_accounts_customer.py | 17 ++ .../process_subscription.py | 13 ++ .../promotional_scheme/promotional_scheme.py | 67 +++++++ .../promotional_scheme_price_discount.py | 51 +++++ .../promotional_scheme_product_discount.py | 51 +++++ .../psoa_cost_center/psoa_cost_center.py | 14 ++ .../doctype/psoa_project/psoa_project.py | 14 ++ .../purchase_invoice/purchase_invoice.py | 168 ++++++++++++++++ .../purchase_invoice_advance.py | 21 ++ .../purchase_invoice_item.py | 89 +++++++++ .../purchase_taxes_and_charges.py | 38 ++++ .../purchase_taxes_and_charges_template.py | 20 ++ .../repost_accounting_ledger.py | 18 ++ .../repost_accounting_ledger_items.py | 15 ++ .../repost_accounting_ledger_settings.py | 13 ++ .../repost_allowed_types.py | 15 ++ .../repost_payment_ledger.py | 22 +++ .../repost_payment_ledger_items.py | 15 ++ .../doctype/sales_invoice/sales_invoice.py | 183 ++++++++++++++++++ .../sales_invoice_advance.py | 21 ++ .../sales_invoice_item/sales_invoice_item.py | 85 ++++++++ .../sales_invoice_payment.py | 20 ++ .../sales_invoice_timesheet.py | 22 +++ .../sales_partner_item/sales_partner_item.py | 14 ++ .../sales_taxes_and_charges.py | 37 ++++ .../sales_taxes_and_charges_template.py | 20 ++ .../doctype/share_balance/share_balance.py | 21 ++ .../doctype/share_transfer/share_transfer.py | 27 +++ .../accounts/doctype/share_type/share_type.py | 12 ++ .../doctype/shareholder/shareholder.py | 19 ++ .../doctype/shipping_rule/shipping_rule.py | 27 +++ .../shipping_rule_condition.py | 16 ++ .../shipping_rule_country.py | 14 ++ .../south_africa_vat_account.py | 14 ++ .../doctype/subscription/subscription.py | 45 +++++ .../subscription_invoice.py | 15 ++ .../subscription_plan/subscription_plan.py | 21 ++ .../subscription_plan_detail.py | 15 ++ .../subscription_settings.py | 13 ++ .../supplier_group_item.py | 14 ++ .../doctype/supplier_item/supplier_item.py | 14 ++ .../doctype/tax_category/tax_category.py | 12 ++ erpnext/accounts/doctype/tax_rule/tax_rule.py | 35 ++++ .../tax_withheld_vouchers.py | 16 ++ .../tax_withholding_account.py | 15 ++ .../tax_withholding_category.py | 21 ++ .../tax_withholding_rate.py | 18 ++ .../doctype/territory_item/territory_item.py | 14 ++ .../unreconcile_payment.py | 19 ++ .../unreconcile_payment_entries.py | 21 ++ erpnext/assets/doctype/asset/asset.py | 75 +++++++ .../doctype/asset_activity/asset_activity.py | 14 ++ .../asset_capitalization.py | 55 ++++++ .../asset_capitalization_asset_item.py | 22 +++ .../asset_capitalization_service_item.py | 21 ++ .../asset_capitalization_stock_item.py | 25 +++ .../doctype/asset_category/asset_category.py | 19 ++ .../asset_category_account.py | 18 ++ .../asset_depreciation_schedule.py | 34 ++++ .../asset_finance_book/asset_finance_book.py | 26 +++ .../asset_maintenance/asset_maintenance.py | 23 +++ .../asset_maintenance_log.py | 28 +++ .../asset_maintenance_task.py | 27 +++ .../asset_maintenance_team.py | 19 ++ .../doctype/asset_movement/asset_movement.py | 19 ++ .../asset_movement_item.py | 20 ++ .../doctype/asset_repair/asset_repair.py | 36 ++++ .../asset_repair_consumed_item.py | 19 ++ .../asset_shift_allocation.py | 19 ++ .../asset_shift_factor/asset_shift_factor.py | 13 ++ .../asset_value_adjustment.py | 21 ++ .../depreciation_schedule.py | 18 ++ .../linked_location/linked_location.py | 14 ++ erpnext/assets/doctype/location/location.py | 21 ++ .../maintenance_team_member.py | 16 ++ .../bulk_transaction_log.py | 14 ++ .../bulk_transaction_log_detail.py | 18 ++ .../buying_settings/buying_settings.py | 32 +++ .../doctype/purchase_order/purchase_order.py | 131 +++++++++++++ .../purchase_order_item.py | 87 +++++++++ .../purchase_order_item_supplied.py | 27 +++ .../purchase_receipt_item_supplied.py | 29 +++ .../request_for_quotation.py | 39 ++++ .../request_for_quotation_item.py | 31 +++ .../request_for_quotation_supplier.py | 20 ++ erpnext/buying/doctype/supplier/supplier.py | 54 ++++++ .../supplier_quotation/supplier_quotation.py | 89 +++++++++ .../supplier_quotation_item.py | 58 ++++++ .../supplier_scorecard/supplier_scorecard.py | 32 +++ .../supplier_scorecard_criteria.py | 14 ++ .../supplier_scorecard_period.py | 26 +++ .../supplier_scorecard_scoring_criteria.py | 18 ++ .../supplier_scorecard_scoring_standing.py | 24 +++ .../supplier_scorecard_scoring_variable.py | 18 ++ .../supplier_scorecard_standing.py | 21 ++ .../supplier_scorecard_variable.py | 15 ++ .../communication_medium.py | 20 ++ .../communication_medium_timeslot.py | 19 ++ .../crm/doctype/appointment/appointment.py | 20 ++ .../appointment_booking_settings.py | 26 +++ .../appointment_booking_slots.py | 18 ++ .../availability_of_slots.py | 18 ++ erpnext/crm/doctype/campaign/campaign.py | 18 ++ .../campaign_email_schedule.py | 15 ++ erpnext/crm/doctype/competitor/competitor.py | 12 ++ .../competitor_detail/competitor_detail.py | 14 ++ erpnext/crm/doctype/contract/contract.py | 36 ++++ .../contract_fulfilment_checklist.py | 17 ++ .../contract_template/contract_template.py | 18 ++ .../contract_template_fulfilment_terms.py | 14 ++ erpnext/crm/doctype/crm_note/crm_note.py | 17 ++ .../crm/doctype/crm_settings/crm_settings.py | 16 ++ .../doctype/email_campaign/email_campaign.py | 17 ++ erpnext/crm/doctype/lead/lead.py | 66 +++++++ .../crm/doctype/lead_source/lead_source.py | 12 ++ .../lost_reason_detail/lost_reason_detail.py | 14 ++ .../doctype/market_segment/market_segment.py | 11 ++ .../crm/doctype/opportunity/opportunity.py | 66 +++++++ .../opportunity_item/opportunity_item.py | 25 +++ .../opportunity_lost_reason.py | 11 ++ .../opportunity_lost_reason_detail.py | 14 ++ .../opportunity_type/opportunity_type.py | 11 ++ erpnext/crm/doctype/prospect/prospect.py | 28 +++ .../doctype/prospect_lead/prospect_lead.py | 19 ++ .../prospect_opportunity.py | 22 +++ .../crm/doctype/sales_stage/sales_stage.py | 11 ++ .../doctype/plaid_settings/plaid_settings.py | 16 ++ .../quickbooks_migrator.py | 30 +++ .../tally_migration/tally_migration.py | 33 ++++ erpnext/hooks.py | 2 + .../maintenance_schedule.py | 34 ++++ .../maintenance_schedule_detail.py | 21 ++ .../maintenance_schedule_item.py | 24 +++ .../maintenance_visit/maintenance_visit.py | 36 ++++ .../maintenance_visit_purpose.py | 21 ++ .../doctype/blanket_order/blanket_order.py | 25 +++ .../blanket_order_item/blanket_order_item.py | 19 ++ erpnext/manufacturing/doctype/bom/bom.py | 65 +++++++ .../doctype/bom_creator/bom_creator.py | 33 ++++ .../bom_creator_item/bom_creator_item.py | 35 ++++ .../bom_explosion_item/bom_explosion_item.py | 26 +++ .../doctype/bom_item/bom_item.py | 36 ++++ .../doctype/bom_operation/bom_operation.py | 29 +++ .../doctype/bom_scrap_item/bom_scrap_item.py | 21 ++ .../bom_update_batch/bom_update_batch.py | 17 ++ .../doctype/bom_update_log/bom_update_log.py | 21 ++ .../bom_update_tool/bom_update_tool.py | 12 ++ .../bom_website_item/bom_website_item.py | 18 ++ .../bom_website_operation.py | 18 ++ .../doctype/downtime_entry/downtime_entry.py | 27 +++ .../doctype/job_card/job_card.py | 76 ++++++++ .../doctype/job_card_item/job_card_item.py | 23 +++ .../job_card_operation/job_card_operation.py | 17 ++ .../job_card_scheduled_time.py | 16 ++ .../job_card_scrap_item.py | 18 ++ .../job_card_time_log/job_card_time_log.py | 19 ++ .../manufacturing_settings.py | 26 +++ .../material_request_plan_item.py | 34 ++++ .../doctype/operation/operation.py | 20 ++ .../production_plan/production_plan.py | 75 +++++++ .../production_plan_item.py | 31 +++ .../production_plan_item_reference.py | 17 ++ .../production_plan_material_request.py | 15 ++ ...duction_plan_material_request_warehouse.py | 14 ++ .../production_plan_sales_order.py | 17 ++ .../production_plan_sub_assembly_item.py | 33 ++++ .../manufacturing/doctype/routing/routing.py | 15 ++ .../doctype/sub_operation/sub_operation.py | 16 ++ .../doctype/work_order/work_order.py | 74 +++++++ .../work_order_item/work_order_item.py | 28 +++ .../work_order_operation.py | 32 +++ .../doctype/workstation/workstation.py | 25 +++ .../workstation_type/workstation_type.py | 17 ++ .../workstation_working_hour.py | 16 ++ erpnext/portal/doctype/homepage/homepage.py | 18 ++ .../homepage_section/homepage_section.py | 19 ++ .../homepage_section_card.py | 18 ++ .../website_attribute/website_attribute.py | 14 ++ .../website_filter_field.py | 14 ++ .../doctype/activity_cost/activity_cost.py | 17 ++ .../doctype/activity_type/activity_type.py | 14 ++ .../doctype/dependent_task/dependent_task.py | 14 ++ .../project_template/project_template.py | 16 ++ .../project_template_task.py | 15 ++ .../doctype/project_type/project_type.py | 12 ++ .../doctype/project_update/project_update.py | 19 ++ .../doctype/project_user/project_user.py | 20 ++ .../projects_settings/projects_settings.py | 13 ++ erpnext/projects/doctype/task/task.py | 50 +++++ .../task_depends_on/task_depends_on.py | 16 ++ .../projects/doctype/task_type/task_type.py | 12 ++ .../timesheet_detail/timesheet_detail.py | 34 ++++ .../non_conformance/non_conformance.py | 18 ++ .../doctype/quality_action/quality_action.py | 22 +++ .../quality_action_resolution.py | 18 ++ .../quality_feedback/quality_feedback.py | 18 ++ .../quality_feedback_parameter.py | 16 ++ .../quality_feedback_template.py | 16 ++ .../quality_feedback_template_parameter.py | 14 ++ .../doctype/quality_goal/quality_goal.py | 51 +++++ .../quality_goal_objective.py | 16 ++ .../quality_meeting/quality_meeting.py | 20 ++ .../quality_meeting_agenda.py | 14 ++ .../quality_meeting_minutes.py | 16 ++ .../quality_procedure/quality_procedure.py | 23 +++ .../quality_procedure_process.py | 15 ++ .../doctype/quality_review/quality_review.py | 20 ++ .../quality_review_objective.py | 18 ++ .../import_supplier_invoice.py | 18 ++ .../lower_deduction_certificate.py | 20 ++ .../south_africa_vat_settings.py | 16 ++ .../uae_vat_account/uae_vat_account.py | 14 ++ .../uae_vat_settings/uae_vat_settings.py | 14 ++ erpnext/selling/doctype/customer/customer.py | 64 ++++++ .../customer_credit_limit.py | 16 ++ .../doctype/industry_type/industry_type.py | 11 ++ .../installation_note/installation_note.py | 32 +++ .../installation_note_item.py | 21 ++ .../party_specific_item.py | 14 ++ .../doctype/product_bundle/product_bundle.py | 16 ++ .../product_bundle_item.py | 18 ++ .../selling/doctype/quotation/quotation.py | 103 ++++++++++ .../doctype/quotation_item/quotation_item.py | 63 ++++++ .../doctype/sales_order/sales_order.py | 133 +++++++++++++ .../sales_order_item/sales_order_item.py | 84 ++++++++ .../sales_partner_type/sales_partner_type.py | 11 ++ .../selling/doctype/sales_team/sales_team.py | 19 ++ .../selling_settings/selling_settings.py | 31 +++ .../selling/doctype/sms_center/sms_center.py | 29 +++ .../authorization_control.py | 10 + .../authorization_rule/authorization_rule.py | 39 ++++ erpnext/setup/doctype/branch/branch.py | 11 ++ erpnext/setup/doctype/brand/brand.py | 16 ++ erpnext/setup/doctype/company/company.py | 84 ++++++++ .../currency_exchange/currency_exchange.py | 16 ++ .../doctype/customer_group/customer_group.py | 25 +++ .../setup/doctype/department/department.py | 18 ++ .../setup/doctype/designation/designation.py | 12 ++ erpnext/setup/doctype/driver/driver.py | 25 +++ .../driving_license_category.py | 16 ++ .../doctype/email_digest/email_digest.py | 44 +++++ .../email_digest_recipient.py | 14 ++ .../employee_education/employee_education.py | 19 ++ .../employee_external_work_history.py | 19 ++ .../doctype/employee_group/employee_group.py | 14 ++ .../employee_group_table.py | 16 ++ .../employee_internal_work_history.py | 18 ++ .../global_defaults/global_defaults.py | 18 ++ erpnext/setup/doctype/holiday/holiday.py | 16 ++ .../doctype/holiday_list/holiday_list.py | 23 +++ erpnext/setup/doctype/incoterm/incoterm.py | 13 ++ .../setup/doctype/item_group/item_group.py | 22 +++ .../setup/doctype/party_type/party_type.py | 12 ++ .../doctype/print_heading/print_heading.py | 12 ++ .../quotation_lost_reason.py | 11 ++ .../quotation_lost_reason_detail.py | 14 ++ .../doctype/sales_partner/sales_partner.py | 24 +++ .../doctype/sales_person/sales_person.py | 23 +++ .../doctype/supplier_group/supplier_group.py | 20 ++ .../doctype/target_detail/target_detail.py | 18 ++ .../terms_and_conditions.py | 15 ++ erpnext/setup/doctype/territory/territory.py | 20 ++ .../transaction_deletion_record.py | 19 ++ .../transaction_deletion_record_item.py | 15 ++ erpnext/setup/doctype/uom/uom.py | 13 ++ .../uom_conversion_factor.py | 14 ++ erpnext/setup/doctype/vehicle/vehicle.py | 30 +++ .../website_item_group/website_item_group.py | 14 ++ erpnext/stock/doctype/batch/batch.py | 27 +++ erpnext/stock/doctype/bin/bin.py | 25 +++ .../closing_stock_balance.py | 21 ++ .../customs_tariff_number.py | 12 ++ .../doctype/delivery_note/delivery_note.py | 122 ++++++++++++ .../delivery_note_item/delivery_note_item.py | 81 ++++++++ .../delivery_settings/delivery_settings.py | 14 ++ .../doctype/delivery_stop/delivery_stop.py | 29 +++ .../doctype/delivery_trip/delivery_trip.py | 27 +++ .../inventory_dimension.py | 24 +++ erpnext/stock/doctype/item/item.py | 100 ++++++++++ .../item_alternative/item_alternative.py | 15 ++ .../doctype/item_attribute/item_attribute.py | 18 ++ .../item_attribute_value.py | 15 ++ .../doctype/item_barcode/item_barcode.py | 32 +++ .../item_customer_detail.py | 16 ++ .../doctype/item_default/item_default.py | 25 +++ .../item_manufacturer/item_manufacturer.py | 16 ++ .../stock/doctype/item_price/item_price.py | 29 +++ .../item_quality_inspection_parameter.py | 21 ++ .../doctype/item_reorder/item_reorder.py | 18 ++ .../doctype/item_supplier/item_supplier.py | 15 ++ erpnext/stock/doctype/item_tax/item_tax.py | 18 ++ .../doctype/item_variant/item_variant.py | 15 ++ .../item_variant_attribute.py | 20 ++ .../item_variant_settings.py | 15 ++ .../item_website_specification.py | 15 ++ .../landed_cost_item/landed_cost_item.py | 24 +++ .../landed_cost_purchase_receipt.py | 18 ++ .../landed_cost_taxes_and_charges.py | 19 ++ .../landed_cost_voucher.py | 27 +++ .../doctype/manufacturer/manufacturer.py | 16 ++ .../material_request/material_request.py | 49 +++++ .../material_request_item.py | 48 +++++ .../stock/doctype/packed_item/packed_item.py | 36 ++++ .../doctype/packing_slip/packing_slip.py | 23 +++ .../packing_slip_item/packing_slip_item.py | 24 +++ erpnext/stock/doctype/pick_list/pick_list.py | 28 +++ .../doctype/pick_list_item/pick_list_item.py | 33 ++++ .../stock/doctype/price_list/price_list.py | 19 ++ .../price_list_country/price_list_country.py | 14 ++ .../purchase_receipt/purchase_receipt.py | 112 +++++++++++ .../purchase_receipt_item.py | 100 ++++++++++ .../doctype/putaway_rule/putaway_rule.py | 21 ++ .../quality_inspection/quality_inspection.py | 43 ++++ .../quality_inspection_parameter.py | 13 ++ .../quality_inspection_parameter_group.py | 11 ++ .../quality_inspection_reading.py | 34 ++++ .../quality_inspection_template.py | 16 ++ .../quick_stock_balance.py | 18 ++ .../repost_item_valuation.py | 31 +++ .../serial_and_batch_bundle.py | 36 ++++ .../serial_and_batch_entry.py | 23 +++ erpnext/stock/doctype/serial_no/serial_no.py | 33 ++++ erpnext/stock/doctype/shipment/shipment.py | 59 ++++++ .../shipment_delivery_note.py | 15 ++ .../shipment_parcel/shipment_parcel.py | 18 ++ .../shipment_parcel_template.py | 15 ++ .../stock/doctype/stock_entry/stock_entry.py | 76 ++++++++ .../stock_entry_detail/stock_entry_detail.py | 61 ++++++ .../stock_entry_type/stock_entry_type.py | 22 +++ .../stock_ledger_entry/stock_ledger_entry.py | 40 ++++ .../stock_reconciliation.py | 28 +++ .../stock_reconciliation_item.py | 32 +++ .../stock_reposting_settings.py | 18 ++ .../stock_reservation_entry.py | 37 ++++ .../doctype/stock_settings/stock_settings.py | 45 +++++ .../doctype/uom_category/uom_category.py | 11 ++ .../uom_conversion_detail.py | 15 ++ .../doctype/variant_field/variant_field.py | 14 ++ erpnext/stock/doctype/warehouse/warehouse.py | 29 +++ .../doctype/warehouse_type/warehouse_type.py | 11 ++ .../subcontracting_bom/subcontracting_bom.py | 19 ++ .../subcontracting_order.py | 67 +++++++ .../subcontracting_order_item.py | 39 ++++ .../subcontracting_order_service_item.py | 21 ++ .../subcontracting_order_supplied_item.py | 27 +++ .../subcontracting_receipt.py | 70 +++++++ .../subcontracting_receipt_item.py | 55 ++++++ .../subcontracting_receipt_supplied_item.py | 31 +++ erpnext/support/doctype/issue/issue.py | 44 +++++ .../doctype/issue_priority/issue_priority.py | 11 ++ .../support/doctype/issue_type/issue_type.py | 11 ++ .../pause_sla_on_status.py | 14 ++ .../doctype/service_day/service_day.py | 16 ++ .../service_level_agreement.py | 35 ++++ .../service_level_priority.py | 17 ++ .../sla_fulfilled_on_status.py | 14 ++ .../support_search_source.py | 27 +++ .../support_settings/support_settings.py | 29 +++ .../doctype/warranty_claim/warranty_claim.py | 41 ++++ .../telephony/doctype/call_log/call_log.py | 28 +++ .../incoming_call_handling_schedule.py | 19 ++ .../incoming_call_settings.py | 19 ++ .../telephony_call_type.py | 12 ++ .../voice_call_settings.py | 15 ++ .../doctype/portal_user/portal_user.py | 14 ++ .../doctype/rename_tool/rename_tool.py | 12 ++ erpnext/utilities/doctype/sms_log/sms_log.py | 17 ++ erpnext/utilities/doctype/video/video.py | 22 +++ .../doctype/video_settings/video_settings.py | 13 ++ 485 files changed, 12920 insertions(+) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 02e6c20572..82af85d702 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -23,6 +23,65 @@ class InvalidAccountMergeError(frappe.ValidationError): class Account(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_currency: DF.Link | None + account_name: DF.Data + account_number: DF.Data | None + account_type: DF.Literal[ + "", + "Accumulated Depreciation", + "Asset Received But Not Billed", + "Bank", + "Cash", + "Chargeable", + "Capital Work in Progress", + "Cost of Goods Sold", + "Current Asset", + "Current Liability", + "Depreciation", + "Direct Expense", + "Direct Income", + "Equity", + "Expense Account", + "Expenses Included In Asset Valuation", + "Expenses Included In Valuation", + "Fixed Asset", + "Income Account", + "Indirect Expense", + "Indirect Income", + "Liability", + "Payable", + "Receivable", + "Round Off", + "Stock", + "Stock Adjustment", + "Stock Received But Not Billed", + "Service Received But Not Billed", + "Tax", + "Temporary", + ] + balance_must_be: DF.Literal["", "Debit", "Credit"] + company: DF.Link + disabled: DF.Check + freeze_account: DF.Literal["No", "Yes"] + include_in_gross: DF.Check + is_group: DF.Check + lft: DF.Int + old_parent: DF.Data | None + parent_account: DF.Link + report_type: DF.Literal["", "Balance Sheet", "Profit and Loss"] + rgt: DF.Int + root_type: DF.Literal["", "Asset", "Liability", "Income", "Expense", "Equity"] + tax_rate: DF.Float + # end: auto-generated types + nsm_parent_field = "parent_account" def on_update(self): diff --git a/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py b/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py index d06bd833c8..65933ab717 100644 --- a/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py +++ b/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py @@ -11,6 +11,29 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( class AccountClosingBalance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + account_currency: DF.Link | None + closing_date: DF.Date | None + company: DF.Link | None + cost_center: DF.Link | None + credit: DF.Currency + credit_in_account_currency: DF.Currency + debit: DF.Currency + debit_in_account_currency: DF.Currency + finance_book: DF.Link | None + is_period_closing_voucher_entry: DF.Check + period_closing_voucher: DF.Link | None + project: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 8f76492d4e..295cd983b3 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -13,6 +13,25 @@ from frappe.utils import cstr class AccountingDimension(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.accounting_dimension_detail.accounting_dimension_detail import ( + AccountingDimensionDetail, + ) + + dimension_defaults: DF.Table[AccountingDimensionDetail] + disabled: DF.Check + document_type: DF.Link + fieldname: DF.Data | None + label: DF.Data | None + # end: auto-generated types + def before_insert(self): self.set_fieldname_and_label() diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py index 4b0cbb35a0..e797ac615d 100644 --- a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py +++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py @@ -7,4 +7,24 @@ from frappe.model.document import Document class AccountingDimensionDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + automatically_post_balancing_accounting_entry: DF.Check + company: DF.Link | None + default_dimension: DF.DynamicLink | None + mandatory_for_bs: DF.Check + mandatory_for_pl: DF.Check + offsetting_account: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + reference_document: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py index de1b82c1d5..01f6e60bf3 100644 --- a/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py +++ b/erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py @@ -8,6 +8,28 @@ from frappe.model.document import Document class AccountingDimensionFilter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.allowed_dimension.allowed_dimension import AllowedDimension + from erpnext.accounts.doctype.applicable_on_account.applicable_on_account import ( + ApplicableOnAccount, + ) + + accounting_dimension: DF.Literal + accounts: DF.Table[ApplicableOnAccount] + allow_or_restrict: DF.Literal["Allow", "Restrict"] + apply_restriction_on_values: DF.Check + company: DF.Link + dimensions: DF.Table[AllowedDimension] + disabled: DF.Check + # end: auto-generated types + def before_save(self): # If restriction is not applied on values, then remove all the dimensions and set allow_or_restrict to Restrict if not self.apply_restriction_on_values: diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index d5f37a6806..b32a231c32 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -16,6 +16,23 @@ class ClosedAccountingPeriod(frappe.ValidationError): class AccountingPeriod(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.closed_document.closed_document import ClosedDocument + + closed_documents: DF.Table[ClosedDocument] + company: DF.Link + end_date: DF.Date + period_name: DF.Data + start_date: DF.Date + # end: auto-generated types + def validate(self): self.validate_overlap() diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index ac3d44bb5e..07d1a65265 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -14,6 +14,52 @@ from erpnext.stock.utils import check_pending_reposting class AccountsSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + acc_frozen_upto: DF.Date | None + add_taxes_from_item_tax_template: DF.Check + allow_multi_currency_invoices_against_single_party_account: DF.Check + allow_stale: DF.Check + auto_reconcile_payments: DF.Check + automatically_fetch_payment_terms: DF.Check + automatically_process_deferred_accounting_entry: DF.Check + book_asset_depreciation_entry_automatically: DF.Check + book_deferred_entries_based_on: DF.Literal["Days", "Months"] + book_deferred_entries_via_journal_entry: DF.Check + book_tax_discount_loss: DF.Check + check_supplier_invoice_uniqueness: DF.Check + credit_controller: DF.Link | None + delete_linked_ledger_entries: DF.Check + determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"] + enable_common_party_accounting: DF.Check + enable_fuzzy_matching: DF.Check + enable_party_matching: DF.Check + frozen_accounts_modifier: DF.Link | None + general_ledger_remarks_length: DF.Int + ignore_account_closing_balance: DF.Check + make_payment_via_journal_entry: DF.Check + merge_similar_account_heads: DF.Check + over_billing_allowance: DF.Currency + post_change_gl_entries: DF.Check + receivable_payable_remarks_length: DF.Int + role_allowed_to_over_bill: DF.Link | None + round_row_wise_tax: DF.Check + show_balance_in_coa: DF.Check + show_inclusive_tax_in_print: DF.Check + show_payment_schedule_in_print: DF.Check + show_taxes_as_table_in_print: DF.Check + stale_days: DF.Int + submit_journal_entries: DF.Check + unlink_advance_payment_on_cancelation_of_order: DF.Check + unlink_payment_on_cancellation_of_invoice: DF.Check + # end: auto-generated types + def validate(self): old_doc = self.get_doc_before_save() clear_cache = False diff --git a/erpnext/accounts/doctype/advance_tax/advance_tax.py b/erpnext/accounts/doctype/advance_tax/advance_tax.py index 2e784efd8f..59bdac7bc5 100644 --- a/erpnext/accounts/doctype/advance_tax/advance_tax.py +++ b/erpnext/accounts/doctype/advance_tax/advance_tax.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class AdvanceTax(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_head: DF.Link | None + allocated_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + reference_detail: DF.Data | None + reference_name: DF.DynamicLink | None + reference_type: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py index 55c84fb9e5..47e97ba015 100644 --- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py +++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py @@ -7,4 +7,33 @@ from frappe.model.document import Document class AdvanceTaxesandCharges(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_head: DF.Link + add_deduct_tax: DF.Literal["Add", "Deduct"] + allocated_amount: DF.Currency + base_tax_amount: DF.Currency + base_total: DF.Currency + charge_type: DF.Literal[ + "", "Actual", "On Paid Amount", "On Previous Row Amount", "On Previous Row Total" + ] + cost_center: DF.Link | None + currency: DF.Link | None + description: DF.SmallText + included_in_paid_amount: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Float + row_id: DF.Data | None + tax_amount: DF.Currency + total: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py b/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py index a3173a84f6..ddc3a161ff 100644 --- a/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py +++ b/erpnext/accounts/doctype/allowed_dimension/allowed_dimension.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class AllowedDimension(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + accounting_dimension: DF.Link | None + dimension_value: DF.DynamicLink | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py index a532070d1e..16654198f9 100644 --- a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py +++ b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class AllowedToTransactWith(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py b/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py index aae216627c..c32f7df4d3 100644 --- a/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py +++ b/erpnext/accounts/doctype/applicable_on_account/applicable_on_account.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class ApplicableOnAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + applicable_on_account: DF.Link + is_mandatory: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/bank/bank.py b/erpnext/accounts/doctype/bank/bank.py index d44be9af23..23bd30c587 100644 --- a/erpnext/accounts/doctype/bank/bank.py +++ b/erpnext/accounts/doctype/bank/bank.py @@ -10,6 +10,25 @@ from frappe.model.document import Document class Bank(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.bank_transaction_mapping.bank_transaction_mapping import ( + BankTransactionMapping, + ) + + bank_name: DF.Data + bank_transaction_mapping: DF.Table[BankTransactionMapping] + plaid_access_token: DF.Data | None + swift_number: DF.Data | None + website: DF.Data | None + # end: auto-generated types + def onload(self): """Load address and contacts in `__onload`""" load_address_and_contact(self) diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index 363a2776aa..4b99b198de 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -12,6 +12,33 @@ from frappe.model.document import Document class BankAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + account_name: DF.Data + account_subtype: DF.Link | None + account_type: DF.Link | None + bank: DF.Link + bank_account_no: DF.Data | None + branch_code: DF.Data | None + company: DF.Link | None + disabled: DF.Check + iban: DF.Data | None + integration_id: DF.Data | None + is_company_account: DF.Check + is_default: DF.Check + last_integration_date: DF.Date | None + mask: DF.Data | None + party: DF.DynamicLink | None + party_type: DF.Link | None + # end: auto-generated types + def onload(self): """Load address and contacts in `__onload`""" load_address_and_contact(self) diff --git a/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py index 6355478fbd..dbd71cc8d2 100644 --- a/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py +++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class BankAccountSubtype(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_subtype: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/bank_account_type/bank_account_type.py b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py index 177b711166..79b755115a 100644 --- a/erpnext/accounts/doctype/bank_account_type/bank_account_type.py +++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py @@ -7,4 +7,15 @@ from frappe.model.document import Document class BankAccountType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_type: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index 8edd376f22..4b97619f29 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -13,6 +13,28 @@ form_grid_templates = {"journal_entries": "templates/form_grid/bank_reconciliati class BankClearance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.bank_clearance_detail.bank_clearance_detail import ( + BankClearanceDetail, + ) + + account: DF.Link + account_currency: DF.Link | None + bank_account: DF.Link | None + from_date: DF.Date + include_pos_transactions: DF.Check + include_reconciled_entries: DF.Check + payment_entries: DF.Table[BankClearanceDetail] + to_date: DF.Date + # end: auto-generated types + @frappe.whitelist() def get_payment_entries(self): if not (self.from_date and self.to_date): diff --git a/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py index 3d29fd7a48..5c1f5bf183 100644 --- a/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py +++ b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class BankClearanceDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + against_account: DF.Data | None + amount: DF.Data | None + cheque_date: DF.Date | None + cheque_number: DF.Data | None + clearance_date: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_document: DF.Link | None + payment_entry: DF.DynamicLink | None + posting_date: DF.Date | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py index 02eb599acc..0af2caf111 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py @@ -8,6 +8,40 @@ from frappe.model.document import Document class BankGuarantee(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + amended_from: DF.Link | None + amount: DF.Currency + bank: DF.Link | None + bank_account: DF.Link | None + bank_account_no: DF.Data | None + bank_guarantee_number: DF.Data | None + bg_type: DF.Literal["", "Receiving", "Providing"] + branch_code: DF.Data | None + charges: DF.Currency + customer: DF.Link | None + end_date: DF.Date | None + fixed_deposit_number: DF.Data | None + iban: DF.Data | None + margin_money: DF.Currency + more_information: DF.TextEditor | None + name_of_beneficiary: DF.Data | None + project: DF.Link | None + reference_docname: DF.DynamicLink | None + reference_doctype: DF.Link | None + start_date: DF.Date + supplier: DF.Link | None + swift_number: DF.Data | None + validity: DF.Int + # end: auto-generated types + def validate(self): if not (self.customer or self.supplier): frappe.throw(_("Select the customer or supplier.")) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index c2ddb39964..0779a09e2f 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -22,6 +22,26 @@ from erpnext.setup.utils import get_exchange_rate class BankReconciliationTool(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_currency: DF.Link | None + account_opening_balance: DF.Currency + bank_account: DF.Link | None + bank_statement_closing_balance: DF.Currency + bank_statement_from_date: DF.Date | None + bank_statement_to_date: DF.Date | None + company: DF.Link | None + filter_by_reference_date: DF.Check + from_reference_date: DF.Date | None + to_reference_date: DF.Date | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py index 003a43c5c2..1a4747c55b 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py @@ -20,6 +20,30 @@ INVALID_VALUES = ("", None) class BankStatementImport(DataImport): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + bank: DF.Link | None + bank_account: DF.Link + company: DF.Link + google_sheets_url: DF.Data | None + import_file: DF.Attach | None + import_type: DF.Literal["", "Insert New Records", "Update Existing Records"] + mute_emails: DF.Check + reference_doctype: DF.Link + show_failed_logs: DF.Check + statement_import_log: DF.Code | None + status: DF.Literal["Pending", "Success", "Partial Success", "Error"] + submit_after_import: DF.Check + template_options: DF.Code | None + template_warnings: DF.Code | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(BankStatementImport, self).__init__(*args, **kwargs) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 51c823a459..629ed1cf75 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -9,6 +9,41 @@ from erpnext.controllers.status_updater import StatusUpdater class BankTransaction(StatusUpdater): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.bank_transaction_payments.bank_transaction_payments import ( + BankTransactionPayments, + ) + + allocated_amount: DF.Currency + amended_from: DF.Link | None + bank_account: DF.Link | None + bank_party_account_number: DF.Data | None + bank_party_iban: DF.Data | None + bank_party_name: DF.Data | None + company: DF.Link | None + currency: DF.Link | None + date: DF.Date | None + deposit: DF.Currency + description: DF.SmallText | None + naming_series: DF.Literal["ACC-BTN-.YYYY.-"] + party: DF.DynamicLink | None + party_type: DF.Link | None + payment_entries: DF.Table[BankTransactionPayments] + reference_number: DF.Data | None + status: DF.Literal["", "Pending", "Settled", "Unreconciled", "Reconciled", "Cancelled"] + transaction_id: DF.Data | None + transaction_type: DF.Data | None + unallocated_amount: DF.Currency + withdrawal: DF.Currency + # end: auto-generated types + def before_validate(self): self.update_allocated_amount() diff --git a/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py b/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py index e19712ccff..44aaf38584 100644 --- a/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py +++ b/erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class BankTransactionMapping(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + bank_transaction_field: DF.Literal + file_field: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py b/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py index 0536aa24b3..e0c84a3ddf 100644 --- a/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py +++ b/erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class BankTransactionPayments(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allocated_amount: DF.Currency + clearance_date: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_document: DF.Link + payment_entry: DF.DynamicLink + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index 63e7bc67c9..2cf9d97e59 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -22,6 +22,36 @@ class DuplicateBudgetError(frappe.ValidationError): class Budget(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.budget_account.budget_account import BudgetAccount + + accounts: DF.Table[BudgetAccount] + action_if_accumulated_monthly_budget_exceeded: DF.Literal["", "Stop", "Warn", "Ignore"] + action_if_accumulated_monthly_budget_exceeded_on_mr: DF.Literal["", "Stop", "Warn", "Ignore"] + action_if_accumulated_monthly_budget_exceeded_on_po: DF.Literal["", "Stop", "Warn", "Ignore"] + action_if_annual_budget_exceeded: DF.Literal["", "Stop", "Warn", "Ignore"] + action_if_annual_budget_exceeded_on_mr: DF.Literal["", "Stop", "Warn", "Ignore"] + action_if_annual_budget_exceeded_on_po: DF.Literal["", "Stop", "Warn", "Ignore"] + amended_from: DF.Link | None + applicable_on_booking_actual_expenses: DF.Check + applicable_on_material_request: DF.Check + applicable_on_purchase_order: DF.Check + budget_against: DF.Literal["", "Cost Center", "Project"] + company: DF.Link + cost_center: DF.Link | None + fiscal_year: DF.Link + monthly_distribution: DF.Link | None + naming_series: DF.Data | None + project: DF.Link | None + # end: auto-generated types + def validate(self): if not self.get(frappe.scrub(self.budget_against)): frappe.throw(_("{0} is mandatory").format(self.budget_against)) diff --git a/erpnext/accounts/doctype/budget_account/budget_account.py b/erpnext/accounts/doctype/budget_account/budget_account.py index 65bc95157b..db2b9a34d8 100644 --- a/erpnext/accounts/doctype/budget_account/budget_account.py +++ b/erpnext/accounts/doctype/budget_account/budget_account.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class BudgetAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + budget_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/campaign_item/campaign_item.py b/erpnext/accounts/doctype/campaign_item/campaign_item.py index d78fdf5285..929ac33435 100644 --- a/erpnext/accounts/doctype/campaign_item/campaign_item.py +++ b/erpnext/accounts/doctype/campaign_item/campaign_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class CampaignItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + campaign: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py index 6013807728..6ab94c5c51 100644 --- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py +++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py @@ -9,6 +9,32 @@ from frappe.utils import flt class CashierClosing(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.cashier_closing_payments.cashier_closing_payments import ( + CashierClosingPayments, + ) + + amended_from: DF.Link | None + custody: DF.Float + date: DF.Date | None + expense: DF.Float + from_time: DF.Time + naming_series: DF.Literal["POS-CLO-"] + net_amount: DF.Float + outstanding_amount: DF.Float + payments: DF.Table[CashierClosingPayments] + returns: DF.Float + time: DF.Time + user: DF.Link + # end: auto-generated types + def validate(self): self.validate_time() diff --git a/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py b/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py index 7617f9bdba..84ce232858 100644 --- a/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py +++ b/erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class CashierClosingPayments(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Float + mode_of_payment: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py index 1e64eeeae6..1c805ccfa9 100644 --- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py +++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py @@ -24,6 +24,18 @@ from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import class ChartofAccountsImporter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link | None + import_file: DF.Attach | None + # end: auto-generated types + def validate(self): if self.import_file: get_coa( diff --git a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py index f8ac66444b..205bb290dc 100644 --- a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py +++ b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py @@ -8,6 +8,41 @@ from frappe.model.document import Document class ChequePrintTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + acc_no_dist_from_left_edge: DF.Float + acc_no_dist_from_top_edge: DF.Float + acc_pay_dist_from_left_edge: DF.Float + acc_pay_dist_from_top_edge: DF.Float + amt_in_figures_from_left_edge: DF.Float + amt_in_figures_from_top_edge: DF.Float + amt_in_word_width: DF.Float + amt_in_words_from_left_edge: DF.Float + amt_in_words_from_top_edge: DF.Float + amt_in_words_line_spacing: DF.Float + bank_name: DF.Data + cheque_height: DF.Float + cheque_size: DF.Literal["", "Regular", "A4"] + cheque_width: DF.Float + date_dist_from_left_edge: DF.Float + date_dist_from_top_edge: DF.Float + has_print_format: DF.Check + is_account_payable: DF.Check + message_to_show: DF.Data | None + payer_name_from_left_edge: DF.Float + payer_name_from_top_edge: DF.Float + scanned_cheque: DF.Attach | None + signatory_from_left_edge: DF.Float + signatory_from_top_edge: DF.Float + starting_position_from_top_edge: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/closed_document/closed_document.py b/erpnext/accounts/doctype/closed_document/closed_document.py index 89d3d2e29c..2f8cd52910 100644 --- a/erpnext/accounts/doctype/closed_document/closed_document.py +++ b/erpnext/accounts/doctype/closed_document/closed_document.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ClosedDocument(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + closed: DF.Check + document_type: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/cost_center/cost_center.py b/erpnext/accounts/doctype/cost_center/cost_center.py index e8b34bbf03..f662eb1fed 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center.py +++ b/erpnext/accounts/doctype/cost_center/cost_center.py @@ -10,6 +10,25 @@ from erpnext.accounts.utils import validate_field_number class CostCenter(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link + cost_center_name: DF.Data + cost_center_number: DF.Data | None + disabled: DF.Check + is_group: DF.Check + lft: DF.Int + old_parent: DF.Link | None + parent_cost_center: DF.Link + rgt: DF.Int + # end: auto-generated types + nsm_parent_field = "parent_cost_center" def autoname(self): diff --git a/erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.py b/erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.py index 54ffe21a15..9ed5ddf078 100644 --- a/erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.py +++ b/erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.py @@ -28,6 +28,25 @@ class InvalidDateError(frappe.ValidationError): class CostCenterAllocation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.cost_center_allocation_percentage.cost_center_allocation_percentage import ( + CostCenterAllocationPercentage, + ) + + allocation_percentages: DF.Table[CostCenterAllocationPercentage] + amended_from: DF.Link | None + company: DF.Link + main_cost_center: DF.Link + valid_from: DF.Date + # end: auto-generated types + def __init__(self, *args, **kwargs): super(CostCenterAllocation, self).__init__(*args, **kwargs) self._skip_from_date_validation = False diff --git a/erpnext/accounts/doctype/cost_center_allocation_percentage/cost_center_allocation_percentage.py b/erpnext/accounts/doctype/cost_center_allocation_percentage/cost_center_allocation_percentage.py index 7d20efb6d5..7257907680 100644 --- a/erpnext/accounts/doctype/cost_center_allocation_percentage/cost_center_allocation_percentage.py +++ b/erpnext/accounts/doctype/cost_center_allocation_percentage/cost_center_allocation_percentage.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class CostCenterAllocationPercentage(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + cost_center: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + percentage: DF.Percent + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/coupon_code/coupon_code.py b/erpnext/accounts/doctype/coupon_code/coupon_code.py index 6a0cdf91c0..540011dd0a 100644 --- a/erpnext/accounts/doctype/coupon_code/coupon_code.py +++ b/erpnext/accounts/doctype/coupon_code/coupon_code.py @@ -9,6 +9,27 @@ from frappe.utils import strip class CouponCode(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + coupon_code: DF.Data | None + coupon_name: DF.Data + coupon_type: DF.Literal["Promotional", "Gift Card"] + customer: DF.Link | None + description: DF.TextEditor | None + maximum_use: DF.Int + pricing_rule: DF.Link + used: DF.Int + valid_from: DF.Date | None + valid_upto: DF.Date | None + # end: auto-generated types + def autoname(self): self.coupon_name = strip(self.coupon_name) self.name = self.coupon_name diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py index 117d5ff21e..3393d4170b 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py +++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py @@ -9,6 +9,30 @@ from frappe.utils import nowdate class CurrencyExchangeSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.currency_exchange_settings_details.currency_exchange_settings_details import ( + CurrencyExchangeSettingsDetails, + ) + from erpnext.accounts.doctype.currency_exchange_settings_result.currency_exchange_settings_result import ( + CurrencyExchangeSettingsResult, + ) + + access_key: DF.Data | None + api_endpoint: DF.Data + disabled: DF.Check + req_params: DF.Table[CurrencyExchangeSettingsDetails] + result_key: DF.Table[CurrencyExchangeSettingsResult] + service_provider: DF.Literal["frankfurter.app", "exchangerate.host", "Custom"] + url: DF.Data | None + # end: auto-generated types + def validate(self): self.set_parameters_and_result() if frappe.flags.in_test or frappe.flags.in_install or frappe.flags.in_setup_wizard: diff --git a/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py index a6ad7634a5..bba0d5d6be 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py +++ b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class CurrencyExchangeSettingsDetails(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + key: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + value: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py index 177412860a..75fb1dfee8 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py +++ b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class CurrencyExchangeSettingsResult(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + key: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/customer_group_item/customer_group_item.py b/erpnext/accounts/doctype/customer_group_item/customer_group_item.py index 100bfd5e66..db76f5be4a 100644 --- a/erpnext/accounts/doctype/customer_group_item/customer_group_item.py +++ b/erpnext/accounts/doctype/customer_group_item/customer_group_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class CustomerGroupItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer_group: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/customer_item/customer_item.py b/erpnext/accounts/doctype/customer_item/customer_item.py index da3533fcc6..67473d403c 100644 --- a/erpnext/accounts/doctype/customer_item/customer_item.py +++ b/erpnext/accounts/doctype/customer_item/customer_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class CustomerItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py index 9b8932c19e..25bef70fbf 100644 --- a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py +++ b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class DiscountedInvoice(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer: DF.Link | None + debit_to: DF.Link | None + outstanding_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + posting_date: DF.Date | None + sales_invoice: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py index 9d0d36b970..c61c3329c6 100644 --- a/erpnext/accounts/doctype/dunning/dunning.py +++ b/erpnext/accounts/doctype/dunning/dunning.py @@ -22,6 +22,52 @@ from erpnext.controllers.accounts_controller import AccountsController class Dunning(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.overdue_payment.overdue_payment import OverduePayment + + address_display: DF.SmallText | None + amended_from: DF.Link | None + base_dunning_amount: DF.Currency + body_text: DF.TextEditor | None + closing_text: DF.TextEditor | None + company: DF.Link + company_address: DF.Link | None + company_address_display: DF.SmallText | None + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + currency: DF.Link | None + customer: DF.Link + customer_address: DF.Link | None + customer_name: DF.Data | None + dunning_amount: DF.Currency + dunning_fee: DF.Currency + dunning_type: DF.Link | None + grand_total: DF.Currency + income_account: DF.Link | None + language: DF.Link | None + letter_head: DF.Link | None + naming_series: DF.Literal["DUNN-.MM.-.YY.-"] + overdue_payments: DF.Table[OverduePayment] + posting_date: DF.Date + posting_time: DF.Time | None + rate_of_interest: DF.Float + spacer: DF.Data | None + status: DF.Literal["Draft", "Resolved", "Unresolved", "Cancelled"] + total_interest: DF.Currency + total_outstanding: DF.Currency + # end: auto-generated types + def validate(self): self.validate_same_currency() self.validate_overdue_payments() diff --git a/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py index 9f3cf7f3f6..a126ff70d6 100644 --- a/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py +++ b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py @@ -7,4 +7,21 @@ from frappe.model.document import Document class DunningLetterText(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + body_text: DF.TextEditor | None + closing_text: DF.TextEditor | None + is_default_language: DF.Check + language: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.py b/erpnext/accounts/doctype/dunning_type/dunning_type.py index 226e159a3b..77f2e004e3 100644 --- a/erpnext/accounts/doctype/dunning_type/dunning_type.py +++ b/erpnext/accounts/doctype/dunning_type/dunning_type.py @@ -7,6 +7,26 @@ from frappe.model.document import Document class DunningType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.dunning_letter_text.dunning_letter_text import DunningLetterText + + company: DF.Link + cost_center: DF.Link | None + dunning_fee: DF.Currency + dunning_letter_text: DF.Table[DunningLetterText] + dunning_type: DF.Data + income_account: DF.Link | None + is_default: DF.Check + rate_of_interest: DF.Float + # end: auto-generated types + def autoname(self): company_abbr = frappe.get_value("Company", self.company, "abbr") self.name = f"{self.dunning_type} - {company_abbr}" diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index 3b5698b118..4f7eeba2d1 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -17,6 +17,28 @@ from erpnext.setup.utils import get_exchange_rate class ExchangeRateRevaluation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.exchange_rate_revaluation_account.exchange_rate_revaluation_account import ( + ExchangeRateRevaluationAccount, + ) + + accounts: DF.Table[ExchangeRateRevaluationAccount] + amended_from: DF.Link | None + company: DF.Link + gain_loss_booked: DF.Currency + gain_loss_unbooked: DF.Currency + posting_date: DF.Date + rounding_loss_allowance: DF.Float + total_gain_loss: DF.Currency + # end: auto-generated types + def validate(self): self.validate_rounding_loss_allowance() self.set_total_gain_loss() diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py b/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py index 96a92bb31f..4efdfddf18 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class ExchangeRateRevaluationAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + account_currency: DF.Link | None + balance_in_account_currency: DF.Currency + balance_in_base_currency: DF.Currency + current_exchange_rate: DF.Float + gain_loss: DF.Currency + new_balance_in_account_currency: DF.Currency + new_balance_in_base_currency: DF.Currency + new_exchange_rate: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + party: DF.DynamicLink | None + party_type: DF.Link | None + zero_balance: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/finance_book/finance_book.py b/erpnext/accounts/doctype/finance_book/finance_book.py index 78b321b2da..a8f7a407f1 100644 --- a/erpnext/accounts/doctype/finance_book/finance_book.py +++ b/erpnext/accounts/doctype/finance_book/finance_book.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class FinanceBook(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + finance_book_name: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index 0dfe569ec9..85f3ffd903 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -10,6 +10,25 @@ from frappe.utils import add_days, add_years, cstr, getdate class FiscalYear(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.fiscal_year_company.fiscal_year_company import FiscalYearCompany + + auto_created: DF.Check + companies: DF.Table[FiscalYearCompany] + disabled: DF.Check + is_short_year: DF.Check + year: DF.Data + year_end_date: DF.Date + year_start_date: DF.Date + # end: auto-generated types + def validate(self): self.validate_dates() self.validate_overlap() diff --git a/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py b/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py index d5db78dfb9..9447120d32 100644 --- a/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py +++ b/erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class FiscalYearCompany(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 7af40c46cb..f7dd29ab1c 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -28,6 +28,47 @@ exclude_from_linked_with = True class GLEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + account_currency: DF.Link | None + against: DF.Text | None + against_voucher: DF.DynamicLink | None + against_voucher_type: DF.Link | None + company: DF.Link | None + cost_center: DF.Link | None + credit: DF.Currency + credit_in_account_currency: DF.Currency + credit_in_transaction_currency: DF.Currency + debit: DF.Currency + debit_in_account_currency: DF.Currency + debit_in_transaction_currency: DF.Currency + due_date: DF.Date | None + finance_book: DF.Link | None + fiscal_year: DF.Link | None + is_advance: DF.Literal["No", "Yes"] + is_cancelled: DF.Check + is_opening: DF.Literal["No", "Yes"] + party: DF.DynamicLink | None + party_type: DF.Link | None + posting_date: DF.Date | None + project: DF.Link | None + remarks: DF.Text | None + to_rename: DF.Check + transaction_currency: DF.Link | None + transaction_date: DF.Date | None + transaction_exchange_rate: DF.Float + voucher_detail_no: DF.Data | None + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + # end: auto-generated types + def autoname(self): """ Temporarily name doc for fast insertion diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index 5bd4585a9a..76f4dadf87 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -17,6 +17,34 @@ from erpnext.controllers.accounts_controller import AccountsController class InvoiceDiscounting(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.discounted_invoice.discounted_invoice import DiscountedInvoice + + accounts_receivable_credit: DF.Link + accounts_receivable_discounted: DF.Link + accounts_receivable_unpaid: DF.Link + amended_from: DF.Link | None + bank_account: DF.Link + bank_charges: DF.Currency + bank_charges_account: DF.Link + company: DF.Link + invoices: DF.Table[DiscountedInvoice] + loan_end_date: DF.Date | None + loan_period: DF.Int + loan_start_date: DF.Date | None + posting_date: DF.Date + short_term_loan: DF.Link + status: DF.Literal["Draft", "Sanctioned", "Disbursed", "Settled", "Cancelled"] + total_amount: DF.Currency + # end: auto-generated types + def validate(self): self.validate_mandatory() self.validate_invoices() diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py index 7e2fca8d24..8d3cdc8637 100644 --- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py +++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py @@ -8,6 +8,24 @@ from frappe.model.document import Document class ItemTaxTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.item_tax_template_detail.item_tax_template_detail import ( + ItemTaxTemplateDetail, + ) + + company: DF.Link + disabled: DF.Check + taxes: DF.Table[ItemTaxTemplateDetail] + title: DF.Data + # end: auto-generated types + def validate(self): self.validate_tax_accounts() diff --git a/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py index 221081e84d..810235e369 100644 --- a/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py +++ b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ItemTaxTemplateDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + tax_rate: DF.Float + tax_type: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 0ad20c31c1..e4f1645fd0 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -35,6 +35,78 @@ class StockAccountInvalidTransaction(frappe.ValidationError): class JournalEntry(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.journal_entry_account.journal_entry_account import ( + JournalEntryAccount, + ) + + accounts: DF.Table[JournalEntryAccount] + amended_from: DF.Link | None + apply_tds: DF.Check + auto_repeat: DF.Link | None + bill_date: DF.Date | None + bill_no: DF.Data | None + cheque_date: DF.Date | None + cheque_no: DF.Data | None + clearance_date: DF.Date | None + company: DF.Link + difference: DF.Currency + due_date: DF.Date | None + finance_book: DF.Link | None + from_template: DF.Link | None + inter_company_journal_entry_reference: DF.Link | None + is_opening: DF.Literal["No", "Yes"] + is_system_generated: DF.Check + letter_head: DF.Link | None + mode_of_payment: DF.Link | None + multi_currency: DF.Check + naming_series: DF.Literal["ACC-JV-.YYYY.-"] + paid_loan: DF.Data | None + pay_to_recd_from: DF.Data | None + payment_order: DF.Link | None + posting_date: DF.Date + process_deferred_accounting: DF.Link | None + remark: DF.SmallText | None + reversal_of: DF.Link | None + select_print_heading: DF.Link | None + stock_entry: DF.Link | None + tax_withholding_category: DF.Link | None + title: DF.Data | None + total_amount: DF.Currency + total_amount_currency: DF.Link | None + total_amount_in_words: DF.Data | None + total_credit: DF.Currency + total_debit: DF.Currency + user_remark: DF.SmallText | None + voucher_type: DF.Literal[ + "Journal Entry", + "Inter Company Journal Entry", + "Bank Entry", + "Cash Entry", + "Credit Card Entry", + "Debit Note", + "Credit Note", + "Contra Entry", + "Excise Entry", + "Write Off Entry", + "Opening Entry", + "Depreciation Entry", + "Exchange Rate Revaluation", + "Exchange Gain Or Loss", + "Deferred Revenue", + "Deferred Expense", + ] + write_off_amount: DF.Currency + write_off_based_on: DF.Literal["Accounts Receivable", "Accounts Payable"] + # end: auto-generated types + def __init__(self, *args, **kwargs): super(JournalEntry, self).__init__(*args, **kwargs) diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py index 534b589273..00c9dcb374 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.py @@ -6,4 +6,56 @@ from frappe.model.document import Document class JournalEntryAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + account_currency: DF.Link | None + account_type: DF.Data | None + against_account: DF.Text | None + balance: DF.Currency + bank_account: DF.Link | None + cost_center: DF.Link | None + credit: DF.Currency + credit_in_account_currency: DF.Currency + debit: DF.Currency + debit_in_account_currency: DF.Currency + exchange_rate: DF.Float + is_advance: DF.Literal["No", "Yes"] + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + party: DF.DynamicLink | None + party_balance: DF.Currency + party_type: DF.Link | None + project: DF.Link | None + reference_detail_no: DF.Data | None + reference_due_date: DF.Date | None + reference_name: DF.DynamicLink | None + reference_type: DF.Literal[ + "", + "Sales Invoice", + "Purchase Invoice", + "Journal Entry", + "Sales Order", + "Purchase Order", + "Expense Claim", + "Asset", + "Loan", + "Payroll Entry", + "Employee Advance", + "Exchange Rate Revaluation", + "Invoice Discounting", + "Fees", + "Full and Final Statement", + "Payment Entry", + ] + user_remark: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py index b8ef3545d3..f87efc54e1 100644 --- a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py +++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py @@ -7,6 +7,41 @@ from frappe.model.document import Document class JournalEntryTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.journal_entry_template_account.journal_entry_template_account import ( + JournalEntryTemplateAccount, + ) + + accounts: DF.Table[JournalEntryTemplateAccount] + company: DF.Link + is_opening: DF.Literal["No", "Yes"] + multi_currency: DF.Check + naming_series: DF.Literal + template_title: DF.Data + voucher_type: DF.Literal[ + "Journal Entry", + "Inter Company Journal Entry", + "Bank Entry", + "Cash Entry", + "Credit Card Entry", + "Debit Note", + "Credit Note", + "Contra Entry", + "Excise Entry", + "Write Off Entry", + "Opening Entry", + "Depreciation Entry", + "Exchange Rate Revaluation", + ] + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py index f84fddd54c..2426f577a1 100644 --- a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py +++ b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class JournalEntryTemplateAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/ledger_merge/ledger_merge.py b/erpnext/accounts/doctype/ledger_merge/ledger_merge.py index 362d27342a..49993393fe 100644 --- a/erpnext/accounts/doctype/ledger_merge/ledger_merge.py +++ b/erpnext/accounts/doctype/ledger_merge/ledger_merge.py @@ -10,6 +10,27 @@ from erpnext.accounts.doctype.account.account import merge_account class LedgerMerge(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.ledger_merge_accounts.ledger_merge_accounts import ( + LedgerMergeAccounts, + ) + + account: DF.Link + account_name: DF.Data + company: DF.Link + is_group: DF.Check + merge_accounts: DF.Table[LedgerMergeAccounts] + root_type: DF.Literal["", "Asset", "Liability", "Income", "Expense", "Equity"] + status: DF.Literal["Pending", "Success", "Partial Success", "Error"] + # end: auto-generated types + def start_merge(self): from frappe.utils.background_jobs import enqueue from frappe.utils.scheduler import is_scheduler_inactive diff --git a/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py b/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py index 30dfd65782..e40e7d6ada 100644 --- a/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py +++ b/erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class LedgerMergeAccounts(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + account_name: DF.Data + merged: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py index dcb43fb2cb..eb8a06606d 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py +++ b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py @@ -10,6 +10,27 @@ exclude_from_linked_with = True class LoyaltyPointEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link | None + customer: DF.Link | None + expiry_date: DF.Date | None + invoice: DF.DynamicLink | None + invoice_type: DF.Link | None + loyalty_points: DF.Int + loyalty_program: DF.Link | None + loyalty_program_tier: DF.Data | None + posting_date: DF.Date | None + purchase_amount: DF.Currency + redeem_against: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py b/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py index bc8f5c70a7..1463b10571 100644 --- a/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py +++ b/erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class LoyaltyPointEntryRedemption(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + redeemed_points: DF.Int + redemption_date: DF.Date | None + sales_invoice: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py index 4f58579a52..463b3cdc3a 100644 --- a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py +++ b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py @@ -9,6 +9,33 @@ from frappe.utils import flt, today class LoyaltyProgram(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.loyalty_program_collection.loyalty_program_collection import ( + LoyaltyProgramCollection, + ) + + auto_opt_in: DF.Check + collection_rules: DF.Table[LoyaltyProgramCollection] + company: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + customer_group: DF.Link | None + customer_territory: DF.Link | None + expense_account: DF.Link | None + expiry_duration: DF.Int + from_date: DF.Date + loyalty_program_name: DF.Data + loyalty_program_type: DF.Literal["Single Tier Program", "Multiple Tier Program"] + to_date: DF.Date | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py b/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py index c462d5f065..b6cecb8c37 100644 --- a/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py +++ b/erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class LoyaltyProgramCollection(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + collection_factor: DF.Currency + min_spent: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + tier_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py index 7d6ef3c3bf..6fc9eba4c3 100644 --- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py +++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py @@ -8,6 +8,24 @@ from frappe.model.document import Document class ModeofPayment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.mode_of_payment_account.mode_of_payment_account import ( + ModeofPaymentAccount, + ) + + accounts: DF.Table[ModeofPaymentAccount] + enabled: DF.Check + mode_of_payment: DF.Data + type: DF.Literal["Cash", "Bank", "General", "Phone"] + # end: auto-generated types + def validate(self): self.validate_accounts() self.validate_repeating_companies() diff --git a/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py b/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py index 3d3bba6b23..e20d6fb2e0 100644 --- a/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py +++ b/erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ModeofPaymentAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link | None + default_account: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py index 1d19708edd..72705765f8 100644 --- a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py +++ b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py @@ -9,6 +9,23 @@ from frappe.utils import add_months, flt class MonthlyDistribution(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.monthly_distribution_percentage.monthly_distribution_percentage import ( + MonthlyDistributionPercentage, + ) + + distribution_id: DF.Data + fiscal_year: DF.Link | None + percentages: DF.Table[MonthlyDistributionPercentage] + # end: auto-generated types + @frappe.whitelist() def get_months(self): month_list = [ diff --git a/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py b/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py index 274e2b643f..d12f79fd89 100644 --- a/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py +++ b/erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class MonthlyDistributionPercentage(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + month: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + percentage_allocation: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py index 680afb1143..f5f8f8ab10 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py @@ -14,6 +14,25 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( class OpeningInvoiceCreationTool(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.opening_invoice_creation_tool_item.opening_invoice_creation_tool_item import ( + OpeningInvoiceCreationToolItem, + ) + + company: DF.Link + cost_center: DF.Link | None + create_missing_party: DF.Check + invoice_type: DF.Literal["Sales", "Purchase"] + invoices: DF.Table[OpeningInvoiceCreationToolItem] + # end: auto-generated types + def onload(self): """Load the Opening Invoice summary""" summary, max_count = self.get_opening_invoice_summary() diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py index 6c0ca4a19f..bc48300286 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.py @@ -6,4 +6,27 @@ from frappe.model.document import Document class OpeningInvoiceCreationToolItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + cost_center: DF.Link | None + due_date: DF.Date | None + invoice_number: DF.Data | None + item_name: DF.Data | None + outstanding_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + party: DF.DynamicLink + party_type: DF.Link | None + posting_date: DF.Date | None + qty: DF.Data | None + temporary_opening_account: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/overdue_payment/overdue_payment.py b/erpnext/accounts/doctype/overdue_payment/overdue_payment.py index 6a543ad467..95e4255cb2 100644 --- a/erpnext/accounts/doctype/overdue_payment/overdue_payment.py +++ b/erpnext/accounts/doctype/overdue_payment/overdue_payment.py @@ -6,4 +6,31 @@ from frappe.model.document import Document class OverduePayment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + discounted_amount: DF.Currency + due_date: DF.Date | None + dunning_level: DF.Int + interest: DF.Currency + invoice_portion: DF.Percent + mode_of_payment: DF.Link | None + outstanding: DF.Currency + overdue_days: DF.Data | None + paid_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_amount: DF.Currency + payment_schedule: DF.Data | None + payment_term: DF.Link | None + sales_invoice: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/party_account/party_account.py b/erpnext/accounts/doctype/party_account/party_account.py index cd270b1184..4b795958a2 100644 --- a/erpnext/accounts/doctype/party_account/party_account.py +++ b/erpnext/accounts/doctype/party_account/party_account.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class PartyAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + advance_account: DF.Link | None + company: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py index 312cfd2c0a..d60acce241 100644 --- a/erpnext/accounts/doctype/party_link/party_link.py +++ b/erpnext/accounts/doctype/party_link/party_link.py @@ -7,6 +7,20 @@ from frappe.model.document import Document class PartyLink(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + primary_party: DF.DynamicLink | None + primary_role: DF.Link + secondary_party: DF.DynamicLink | None + secondary_role: DF.Link | None + # end: auto-generated types + def validate(self): if self.primary_role not in ["Customer", "Supplier"]: frappe.throw( diff --git a/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py b/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py index b71dbb97d7..fc67c526b2 100644 --- a/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py +++ b/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class PaymentEntryDeduction(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + amount: DF.Currency + cost_center: DF.Link + description: DF.SmallText | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py index fc1cad9ad6..13707e53ef 100644 --- a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py +++ b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.py @@ -6,4 +6,28 @@ from frappe.model.document import Document class PaymentEntryReference(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + allocated_amount: DF.Float + bill_no: DF.Data | None + due_date: DF.Date | None + exchange_gain_loss: DF.Currency + exchange_rate: DF.Float + outstanding_amount: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_term: DF.Link | None + reference_doctype: DF.Link + reference_name: DF.DynamicLink + total_amount: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py index 791de2570a..f1bf363eca 100644 --- a/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py +++ b/erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.py @@ -7,6 +7,22 @@ from frappe.model.document import Document class PaymentGatewayAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + currency: DF.ReadOnly | None + is_default: DF.Check + message: DF.SmallText | None + payment_account: DF.Link + payment_channel: DF.Literal["", "Email", "Phone"] + payment_gateway: DF.Link + # end: auto-generated types + def autoname(self): self.name = self.payment_gateway + " - " + self.currency diff --git a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py index 58691ab8d4..e8dfda2023 100644 --- a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py +++ b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py @@ -21,6 +21,35 @@ from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDim class PaymentLedgerEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + account_currency: DF.Link | None + account_type: DF.Literal["Receivable", "Payable"] + against_voucher_no: DF.DynamicLink | None + against_voucher_type: DF.Link | None + amount: DF.Currency + amount_in_account_currency: DF.Currency + company: DF.Link | None + cost_center: DF.Link | None + delinked: DF.Check + due_date: DF.Date | None + finance_book: DF.Link | None + party: DF.DynamicLink | None + party_type: DF.Link | None + posting_date: DF.Date | None + remarks: DF.Text | None + voucher_detail_no: DF.Data | None + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + # end: auto-generated types + def validate_account(self): valid_account = frappe.db.get_list( "Account", diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py index ff9615d14f..0ed26e4578 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.py +++ b/erpnext/accounts/doctype/payment_order/payment_order.py @@ -11,6 +11,30 @@ from erpnext.accounts.party import get_party_account class PaymentOrder(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_order_reference.payment_order_reference import ( + PaymentOrderReference, + ) + + account: DF.Data | None + amended_from: DF.Link | None + company: DF.Link + company_bank: DF.Link | None + company_bank_account: DF.Link + naming_series: DF.Literal["PMO-"] + party: DF.Link | None + payment_order_type: DF.Literal["", "Payment Request", "Payment Entry"] + posting_date: DF.Date | None + references: DF.Table[PaymentOrderReference] + # end: auto-generated types + def on_submit(self): self.update_payment_status() diff --git a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py index 94704fcd16..26c2ce2852 100644 --- a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py +++ b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.py @@ -6,4 +6,26 @@ from frappe.model.document import Document class PaymentOrderReference(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + amount: DF.Currency + bank_account: DF.Link + mode_of_payment: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_reference: DF.Data | None + payment_request: DF.Link | None + reference_doctype: DF.Link + reference_name: DF.DynamicLink + supplier: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 6673e8de28..fbc4d245cb 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -23,6 +23,48 @@ from erpnext.controllers.accounts_controller import get_advance_payment_entries_ class PaymentReconciliation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_reconciliation_allocation.payment_reconciliation_allocation import ( + PaymentReconciliationAllocation, + ) + from erpnext.accounts.doctype.payment_reconciliation_invoice.payment_reconciliation_invoice import ( + PaymentReconciliationInvoice, + ) + from erpnext.accounts.doctype.payment_reconciliation_payment.payment_reconciliation_payment import ( + PaymentReconciliationPayment, + ) + + allocation: DF.Table[PaymentReconciliationAllocation] + bank_cash_account: DF.Link | None + company: DF.Link + cost_center: DF.Link | None + default_advance_account: DF.Link | None + from_invoice_date: DF.Date | None + from_payment_date: DF.Date | None + invoice_limit: DF.Int + invoice_name: DF.Data | None + invoices: DF.Table[PaymentReconciliationInvoice] + maximum_invoice_amount: DF.Currency + maximum_payment_amount: DF.Currency + minimum_invoice_amount: DF.Currency + minimum_payment_amount: DF.Currency + party: DF.DynamicLink + party_type: DF.Link + payment_limit: DF.Int + payment_name: DF.Data | None + payments: DF.Table[PaymentReconciliationPayment] + receivable_payable_account: DF.Link + to_invoice_date: DF.Date | None + to_payment_date: DF.Date | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(PaymentReconciliation, self).__init__(*args, **kwargs) self.common_filter_conditions = [] diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py index 9db8e62af0..a4141afb37 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.py @@ -6,4 +6,32 @@ from frappe.model.document import Document class PaymentReconciliationAllocation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allocated_amount: DF.Currency + amount: DF.Currency + cost_center: DF.Link | None + currency: DF.Link | None + difference_account: DF.Link | None + difference_amount: DF.Currency + exchange_rate: DF.Float + gain_loss_posting_date: DF.Date | None + invoice_number: DF.DynamicLink + invoice_type: DF.Link + is_advance: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + reference_name: DF.DynamicLink + reference_row: DF.Data | None + reference_type: DF.Link + unreconciled_amount: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py index 7665b75ff0..1e9f6cec82 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py +++ b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.py @@ -6,4 +6,24 @@ from frappe.model.document import Document class PaymentReconciliationInvoice(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + currency: DF.Link | None + exchange_rate: DF.Float + invoice_date: DF.Date | None + invoice_number: DF.DynamicLink | None + invoice_type: DF.Literal["Sales Invoice", "Purchase Invoice", "Journal Entry"] + outstanding_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py index c0e3fd641a..aa956fe59b 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py +++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.py @@ -6,4 +6,28 @@ from frappe.model.document import Document class PaymentReconciliationPayment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + cost_center: DF.Link | None + currency: DF.Link | None + difference_amount: DF.Currency + exchange_rate: DF.Float + is_advance: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + posting_date: DF.Date | None + reference_name: DF.DynamicLink | None + reference_row: DF.Data | None + reference_type: DF.Link | None + remark: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index c2e01c4ba3..20019cb683 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -27,6 +27,65 @@ def _get_payment_gateway_controller(*args, **kwargs): class PaymentRequest(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.subscription_plan_detail.subscription_plan_detail import ( + SubscriptionPlanDetail, + ) + + account: DF.ReadOnly | None + amended_from: DF.Link | None + bank: DF.Link | None + bank_account: DF.Link | None + bank_account_no: DF.ReadOnly | None + branch_code: DF.ReadOnly | None + cost_center: DF.Link | None + currency: DF.Link | None + email_to: DF.Data | None + grand_total: DF.Currency + iban: DF.ReadOnly | None + is_a_subscription: DF.Check + make_sales_invoice: DF.Check + message: DF.Text | None + mode_of_payment: DF.Link | None + mute_email: DF.Check + naming_series: DF.Literal["ACC-PRQ-.YYYY.-"] + party: DF.DynamicLink | None + party_type: DF.Link | None + payment_account: DF.ReadOnly | None + payment_channel: DF.Literal["", "Email", "Phone"] + payment_gateway: DF.ReadOnly | None + payment_gateway_account: DF.Link | None + payment_order: DF.Link | None + payment_request_type: DF.Literal["Outward", "Inward"] + payment_url: DF.Data | None + print_format: DF.Literal + project: DF.Link | None + reference_doctype: DF.Link | None + reference_name: DF.DynamicLink | None + status: DF.Literal[ + "", + "Draft", + "Requested", + "Initiated", + "Partially Paid", + "Payment Ordered", + "Paid", + "Failed", + "Cancelled", + ] + subject: DF.Data | None + subscription_plans: DF.Table[SubscriptionPlanDetail] + swift_number: DF.ReadOnly | None + transaction_date: DF.Date | None + # end: auto-generated types + def validate(self): if self.get("__islocal"): self.status = "Draft" diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py index 33e261f0ef..8a292fd3ab 100644 --- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.py +++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.py @@ -6,4 +6,30 @@ from frappe.model.document import Document class PaymentSchedule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + base_payment_amount: DF.Currency + description: DF.SmallText | None + discount: DF.Float + discount_date: DF.Date | None + discount_type: DF.Literal["Percentage", "Amount"] + discounted_amount: DF.Currency + due_date: DF.Date + invoice_portion: DF.Percent + mode_of_payment: DF.Link | None + outstanding: DF.Currency + paid_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_amount: DF.Currency + payment_term: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_term/payment_term.py b/erpnext/accounts/doctype/payment_term/payment_term.py index 956c2b13fd..5f9171ec22 100644 --- a/erpnext/accounts/doctype/payment_term/payment_term.py +++ b/erpnext/accounts/doctype/payment_term/payment_term.py @@ -6,4 +6,33 @@ from frappe.model.document import Document class PaymentTerm(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + credit_days: DF.Int + credit_months: DF.Int + description: DF.SmallText | None + discount: DF.Float + discount_type: DF.Literal["Percentage", "Amount"] + discount_validity: DF.Int + discount_validity_based_on: DF.Literal[ + "Day(s) after invoice date", + "Day(s) after the end of the invoice month", + "Month(s) after the end of the invoice month", + ] + due_date_based_on: DF.Literal[ + "Day(s) after invoice date", + "Day(s) after the end of the invoice month", + "Month(s) after the end of the invoice month", + ] + invoice_portion: DF.Float + mode_of_payment: DF.Link | None + payment_term_name: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py index 7b04a68e89..8f028f9160 100644 --- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py +++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py @@ -9,6 +9,23 @@ from frappe.utils import flt class PaymentTermsTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_terms_template_detail.payment_terms_template_detail import ( + PaymentTermsTemplateDetail, + ) + + allocate_payment_based_on_payment_terms: DF.Check + template_name: DF.Data | None + terms: DF.Table[PaymentTermsTemplateDetail] + # end: auto-generated types + def validate(self): self.validate_invoice_portion() self.validate_terms() diff --git a/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py index 710988bdf0..0edcd42f38 100644 --- a/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py +++ b/erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.py @@ -6,4 +6,36 @@ from frappe.model.document import Document class PaymentTermsTemplateDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + credit_days: DF.Int + credit_months: DF.Int + description: DF.SmallText | None + discount: DF.Float + discount_type: DF.Literal["Percentage", "Amount"] + discount_validity: DF.Int + discount_validity_based_on: DF.Literal[ + "Day(s) after invoice date", + "Day(s) after the end of the invoice month", + "Month(s) after the end of the invoice month", + ] + due_date_based_on: DF.Literal[ + "Day(s) after invoice date", + "Day(s) after the end of the invoice month", + "Month(s) after the end of the invoice month", + ] + invoice_portion: DF.Float + mode_of_payment: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + payment_term: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py index 674db6c2e4..2a84d971f4 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -15,6 +15,26 @@ from erpnext.controllers.accounts_controller import AccountsController class PeriodClosingVoucher(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + closing_account_head: DF.Link + company: DF.Link + error_message: DF.Text | None + fiscal_year: DF.Link + gle_processing_status: DF.Literal["In Progress", "Completed", "Failed"] + posting_date: DF.Date + remarks: DF.SmallText + transaction_date: DF.Date | None + year_start_date: DF.Date | None + # end: auto-generated types + def validate(self): self.validate_account_head() self.validate_posting_date() diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py index 115b415eed..0f3a5bb916 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py @@ -14,6 +14,43 @@ from erpnext.controllers.status_updater import StatusUpdater class POSClosingEntry(StatusUpdater): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pos_closing_entry_detail.pos_closing_entry_detail import ( + POSClosingEntryDetail, + ) + from erpnext.accounts.doctype.pos_closing_entry_taxes.pos_closing_entry_taxes import ( + POSClosingEntryTaxes, + ) + from erpnext.accounts.doctype.pos_invoice_reference.pos_invoice_reference import ( + POSInvoiceReference, + ) + + amended_from: DF.Link | None + company: DF.Link + error_message: DF.SmallText | None + grand_total: DF.Currency + net_total: DF.Currency + payment_reconciliation: DF.Table[POSClosingEntryDetail] + period_end_date: DF.Datetime + period_start_date: DF.Datetime + pos_opening_entry: DF.Link + pos_profile: DF.Link + pos_transactions: DF.Table[POSInvoiceReference] + posting_date: DF.Date + posting_time: DF.Time + status: DF.Literal["Draft", "Submitted", "Queued", "Failed", "Cancelled"] + taxes: DF.Table[POSClosingEntryTaxes] + total_quantity: DF.Float + user: DF.Link + # end: auto-generated types + def validate(self): self.posting_date = self.posting_date or frappe.utils.nowdate() self.posting_time = self.posting_time or frappe.utils.nowtime() diff --git a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py index 2e34e44c92..97e5670b05 100644 --- a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py +++ b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class POSClosingEntryDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + closing_amount: DF.Currency + difference: DF.Currency + expected_amount: DF.Currency + mode_of_payment: DF.Link + opening_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py index cfedeb3a9a..ce354a7552 100644 --- a/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py +++ b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class POSClosingEntryTaxes(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_head: DF.Link | None + amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Percent + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py index 5e532ae560..a1a184ee9e 100644 --- a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py +++ b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class POSCustomerGroup(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer_group: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_field/pos_field.py b/erpnext/accounts/doctype/pos_field/pos_field.py index 4ef8827421..68441c623a 100644 --- a/erpnext/accounts/doctype/pos_field/pos_field.py +++ b/erpnext/accounts/doctype/pos_field/pos_field.py @@ -7,4 +7,24 @@ from frappe.model.document import Document class POSField(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + default_value: DF.Data | None + fieldname: DF.Literal + fieldtype: DF.Data | None + label: DF.Data | None + options: DF.Text | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + read_only: DF.Check + reqd: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 9091a77f99..bfb51da58b 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -20,6 +20,169 @@ from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos class POSInvoice(SalesInvoice): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule + from erpnext.accounts.doctype.pos_invoice_item.pos_invoice_item import POSInvoiceItem + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.sales_invoice_advance.sales_invoice_advance import ( + SalesInvoiceAdvance, + ) + from erpnext.accounts.doctype.sales_invoice_payment.sales_invoice_payment import ( + SalesInvoicePayment, + ) + from erpnext.accounts.doctype.sales_invoice_timesheet.sales_invoice_timesheet import ( + SalesInvoiceTimesheet, + ) + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, + ) + from erpnext.selling.doctype.sales_team.sales_team import SalesTeam + from erpnext.stock.doctype.packed_item.packed_item import PackedItem + + account_for_change_amount: DF.Link | None + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + advances: DF.Table[SalesInvoiceAdvance] + against_income_account: DF.SmallText | None + allocate_advances_automatically: DF.Check + amended_from: DF.Link | None + amount_eligible_for_commission: DF.Currency + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + auto_repeat: DF.Link | None + base_change_amount: DF.Currency + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_paid_amount: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + base_write_off_amount: DF.Currency + campaign: DF.Link | None + cash_bank_account: DF.Link | None + change_amount: DF.Currency + commission_rate: DF.Float + company: DF.Link + company_address: DF.Link | None + company_address_display: DF.SmallText | None + consolidated_invoice: DF.Link | None + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.Data | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + coupon_code: DF.Link | None + currency: DF.Link + customer: DF.Link | None + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + debit_to: DF.Link + discount_amount: DF.Currency + due_date: DF.Date | None + from_date: DF.Date | None + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + inter_company_invoice_reference: DF.Link | None + is_discounted: DF.Check + is_opening: DF.Literal["No", "Yes"] + is_pos: DF.Check + is_return: DF.Check + items: DF.Table[POSInvoiceItem] + language: DF.Data | None + letter_head: DF.Link | None + loyalty_amount: DF.Currency + loyalty_points: DF.Int + loyalty_program: DF.Link | None + loyalty_redemption_account: DF.Link | None + loyalty_redemption_cost_center: DF.Link | None + naming_series: DF.Literal["ACC-PSINV-.YYYY.-"] + net_total: DF.Currency + other_charges_calculation: DF.LongText | None + outstanding_amount: DF.Currency + packed_items: DF.Table[PackedItem] + paid_amount: DF.Currency + party_account_currency: DF.Link | None + payment_schedule: DF.Table[PaymentSchedule] + payment_terms_template: DF.Link | None + payments: DF.Table[SalesInvoicePayment] + plc_conversion_rate: DF.Float + po_date: DF.Date | None + po_no: DF.Data | None + pos_profile: DF.Link | None + posting_date: DF.Date + posting_time: DF.Time | None + price_list_currency: DF.Link + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + redeem_loyalty_points: DF.Check + remarks: DF.SmallText | None + return_against: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + sales_partner: DF.Link | None + sales_team: DF.Table[SalesTeam] + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + selling_price_list: DF.Link + set_posting_time: DF.Check + set_warehouse: DF.Link | None + shipping_address: DF.SmallText | None + shipping_address_name: DF.Link | None + shipping_rule: DF.Link | None + source: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "Return", + "Credit Note Issued", + "Consolidated", + "Submitted", + "Paid", + "Unpaid", + "Unpaid and Discounted", + "Overdue and Discounted", + "Overdue", + "Cancelled", + ] + tax_category: DF.Link | None + tax_id: DF.Data | None + taxes: DF.Table[SalesTaxesandCharges] + taxes_and_charges: DF.Link | None + tc_name: DF.Link | None + terms: DF.TextEditor | None + territory: DF.Link | None + timesheets: DF.Table[SalesInvoiceTimesheet] + title: DF.Data | None + to_date: DF.Date | None + total: DF.Currency + total_advance: DF.Currency + total_billing_amount: DF.Currency + total_commission: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + update_billed_amount_in_delivery_note: DF.Check + update_billed_amount_in_sales_order: DF.Check + update_stock: DF.Check + write_off_account: DF.Link | None + write_off_amount: DF.Currency + write_off_cost_center: DF.Link | None + write_off_outstanding_amount_automatically: DF.Check + # end: auto-generated types + def __init__(self, *args, **kwargs): super(POSInvoice, self).__init__(*args, **kwargs) diff --git a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py index 7e3ae82a8b..e2a62f1336 100644 --- a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py +++ b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py @@ -7,4 +7,84 @@ from frappe.model.document import Document class POSInvoiceItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_batch_qty: DF.Float + actual_qty: DF.Float + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + asset: DF.Link | None + barcode: DF.Data | None + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + batch_no: DF.Link | None + brand: DF.Data | None + conversion_factor: DF.Float + cost_center: DF.Link + customer_item_code: DF.Data | None + deferred_revenue_account: DF.Link | None + delivered_by_supplier: DF.Check + delivered_qty: DF.Float + delivery_note: DF.Link | None + description: DF.TextEditor + discount_amount: DF.Currency + discount_percentage: DF.Percent + dn_detail: DF.Data | None + enable_deferred_revenue: DF.Check + expense_account: DF.Link | None + finance_book: DF.Link | None + grant_commission: DF.Check + has_item_scanned: DF.Check + image: DF.Attach | None + income_account: DF.Link + is_fixed_asset: DF.Check + is_free_item: DF.Check + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data + item_tax_rate: DF.SmallText | None + item_tax_template: DF.Link | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + pos_invoice_item: DF.Data | None + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + project: DF.Link | None + qty: DF.Float + quality_inspection: DF.Link | None + rate: DF.Currency + rate_with_margin: DF.Currency + sales_order: DF.Link | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + service_end_date: DF.Date | None + service_start_date: DF.Date | None + service_stop_date: DF.Date | None + so_detail: DF.Data | None + stock_qty: DF.Float + stock_uom: DF.Link | None + target_warehouse: DF.Link | None + total_weight: DF.Float + uom: DF.Link + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index c161dac33f..cd858cab18 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -16,6 +16,30 @@ from erpnext.accounts.doctype.pos_profile.pos_profile import required_accounting class POSInvoiceMergeLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pos_invoice_reference.pos_invoice_reference import ( + POSInvoiceReference, + ) + + amended_from: DF.Link | None + consolidated_credit_note: DF.Link | None + consolidated_invoice: DF.Link | None + customer: DF.Link + customer_group: DF.Link | None + merge_invoices_based_on: DF.Literal["Customer", "Customer Group"] + pos_closing_entry: DF.Link | None + pos_invoices: DF.Table[POSInvoiceReference] + posting_date: DF.Date + posting_time: DF.Time + # end: auto-generated types + def validate(self): self.validate_customer() self.validate_pos_invoice_status() diff --git a/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py index c1c36f8da8..6e7710a3af 100644 --- a/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py +++ b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py @@ -7,4 +7,23 @@ from frappe.model.document import Document class POSInvoiceReference(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer: DF.Link + grand_total: DF.Currency + is_return: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + pos_invoice: DF.Link + posting_date: DF.Date + return_against: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_item_group/pos_item_group.py b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py index 75fa08048d..650b0be425 100644 --- a/erpnext/accounts/doctype/pos_item_group/pos_item_group.py +++ b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class POSItemGroup(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_group: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py index 3cd14264bb..10b07c2c80 100644 --- a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py +++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py @@ -10,6 +10,31 @@ from erpnext.controllers.status_updater import StatusUpdater class POSOpeningEntry(StatusUpdater): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pos_opening_entry_detail.pos_opening_entry_detail import ( + POSOpeningEntryDetail, + ) + + amended_from: DF.Link | None + balance_details: DF.Table[POSOpeningEntryDetail] + company: DF.Link + period_end_date: DF.Date | None + period_start_date: DF.Datetime + pos_closing_entry: DF.Data | None + pos_profile: DF.Link + posting_date: DF.Date + set_posting_date: DF.Check + status: DF.Literal["Draft", "Open", "Closed", "Cancelled"] + user: DF.Link + # end: auto-generated types + def validate(self): self.validate_pos_profile_and_cashier() self.validate_payment_method_account() diff --git a/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py index 9108b9080b..e66769c4aa 100644 --- a/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py +++ b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class POSOpeningEntryDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + mode_of_payment: DF.Link + opening_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py index 589047d1d5..42d0409189 100644 --- a/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py +++ b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class POSPaymentMethod(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_in_returns: DF.Check + default: DF.Check + mode_of_payment: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index 58be2d3e5c..30f3e0cc9e 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -9,6 +9,57 @@ from frappe.utils import get_link_to_form, now class POSProfile(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pos_customer_group.pos_customer_group import POSCustomerGroup + from erpnext.accounts.doctype.pos_item_group.pos_item_group import POSItemGroup + from erpnext.accounts.doctype.pos_payment_method.pos_payment_method import POSPaymentMethod + from erpnext.accounts.doctype.pos_profile_user.pos_profile_user import POSProfileUser + + account_for_change_amount: DF.Link | None + allow_discount_change: DF.Check + allow_rate_change: DF.Check + applicable_for_users: DF.Table[POSProfileUser] + apply_discount_on: DF.Literal["Grand Total", "Net Total"] + auto_add_item_to_cart: DF.Check + campaign: DF.Link | None + company: DF.Link + company_address: DF.Link | None + cost_center: DF.Link | None + country: DF.ReadOnly | None + currency: DF.Link + customer: DF.Link | None + customer_groups: DF.Table[POSCustomerGroup] + disable_rounded_total: DF.Check + disabled: DF.Check + expense_account: DF.Link | None + hide_images: DF.Check + hide_unavailable_items: DF.Check + ignore_pricing_rule: DF.Check + income_account: DF.Link | None + item_groups: DF.Table[POSItemGroup] + letter_head: DF.Link | None + payments: DF.Table[POSPaymentMethod] + print_format: DF.Link | None + select_print_heading: DF.Link | None + selling_price_list: DF.Link | None + tax_category: DF.Link | None + taxes_and_charges: DF.Link | None + tc_name: DF.Link | None + update_stock: DF.Check + validate_stock_on_save: DF.Check + warehouse: DF.Link + write_off_account: DF.Link + write_off_cost_center: DF.Link + write_off_limit: DF.Currency + # end: auto-generated types + def validate(self): self.validate_default_profile() self.validate_all_link_fields() diff --git a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py index c92d563225..d4de2632c3 100644 --- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py +++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class POSProfileUser(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + default: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + user: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py b/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py index fd55dc85a7..181f9ef54f 100644 --- a/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py +++ b/erpnext/accounts/doctype/pos_search_fields/pos_search_fields.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class POSSearchFields(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + field: DF.Literal + fieldname: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.py b/erpnext/accounts/doctype/pos_settings/pos_settings.py index 2adecc0859..1e298a68f4 100644 --- a/erpnext/accounts/doctype/pos_settings/pos_settings.py +++ b/erpnext/accounts/doctype/pos_settings/pos_settings.py @@ -6,5 +6,20 @@ from frappe.model.document import Document class POSSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pos_field.pos_field import POSField + from erpnext.accounts.doctype.pos_search_fields.pos_search_fields import POSSearchFields + + invoice_fields: DF.Table[POSField] + pos_search_fields: DF.Table[POSSearchFields] + # end: auto-generated types + def validate(self): pass diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 0b7ea2470c..b41cf53665 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -18,6 +18,115 @@ other_fields = ["other_item_code", "other_item_group", "other_brand"] class PricingRule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pricing_rule_brand.pricing_rule_brand import PricingRuleBrand + from erpnext.accounts.doctype.pricing_rule_item_code.pricing_rule_item_code import ( + PricingRuleItemCode, + ) + from erpnext.accounts.doctype.pricing_rule_item_group.pricing_rule_item_group import ( + PricingRuleItemGroup, + ) + + applicable_for: DF.Literal[ + "", + "Customer", + "Customer Group", + "Territory", + "Sales Partner", + "Campaign", + "Supplier", + "Supplier Group", + ] + apply_discount_on: DF.Literal["Grand Total", "Net Total"] + apply_discount_on_rate: DF.Check + apply_multiple_pricing_rules: DF.Check + apply_on: DF.Literal["", "Item Code", "Item Group", "Brand", "Transaction"] + apply_recursion_over: DF.Float + apply_rule_on_other: DF.Literal["", "Item Code", "Item Group", "Brand"] + brands: DF.Table[PricingRuleBrand] + buying: DF.Check + campaign: DF.Link | None + company: DF.Link | None + condition: DF.Code | None + coupon_code_based: DF.Check + currency: DF.Link + customer: DF.Link | None + customer_group: DF.Link | None + disable: DF.Check + discount_amount: DF.Currency + discount_percentage: DF.Float + for_price_list: DF.Link | None + free_item: DF.Link | None + free_item_rate: DF.Currency + free_item_uom: DF.Link | None + free_qty: DF.Float + is_cumulative: DF.Check + is_recursive: DF.Check + item_groups: DF.Table[PricingRuleItemGroup] + items: DF.Table[PricingRuleItemCode] + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + max_amt: DF.Currency + max_qty: DF.Float + min_amt: DF.Currency + min_qty: DF.Float + mixed_conditions: DF.Check + naming_series: DF.Literal["PRLE-.####"] + other_brand: DF.Link | None + other_item_code: DF.Link | None + other_item_group: DF.Link | None + price_or_product_discount: DF.Literal["Price", "Product"] + priority: DF.Literal[ + "", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + ] + promotional_scheme: DF.Link | None + promotional_scheme_id: DF.Data | None + rate: DF.Currency + rate_or_discount: DF.Literal["", "Rate", "Discount Percentage", "Discount Amount"] + recurse_for: DF.Float + round_free_qty: DF.Check + rule_description: DF.SmallText | None + sales_partner: DF.Link | None + same_item: DF.Check + selling: DF.Check + supplier: DF.Link | None + supplier_group: DF.Link | None + territory: DF.Link | None + threshold_percentage: DF.Percent + title: DF.Data + valid_from: DF.Date | None + valid_upto: DF.Date | None + validate_applied_rule: DF.Check + warehouse: DF.Link | None + # end: auto-generated types + def validate(self): self.validate_mandatory() self.validate_duplicate_apply_on() diff --git a/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py b/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py index fdd5be0f6c..ffd74c2319 100644 --- a/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py +++ b/erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class PricingRuleBrand(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + brand: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py b/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py index f48b569508..18be93d570 100644 --- a/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py +++ b/erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class PricingRuleDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + child_docname: DF.Data | None + item_code: DF.Data | None + margin_type: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + pricing_rule: DF.Link | None + rate_or_discount: DF.Data | None + rule_applied: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py b/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py index f8a2c0e648..ae9570aea4 100644 --- a/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py +++ b/erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class PricingRuleItemCode(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_code: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py b/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py index 940350af90..fed0c293dd 100644 --- a/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py +++ b/erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class PricingRuleItemGroup(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_group: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py index 1f88849b26..6a13c1f734 100644 --- a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py +++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py @@ -15,6 +15,23 @@ from erpnext.accounts.general_ledger import make_gl_entries class ProcessDeferredAccounting(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + amended_from: DF.Link | None + company: DF.Link + end_date: DF.Date + posting_date: DF.Date + start_date: DF.Date + type: DF.Literal["", "Income", "Expense"] + # end: auto-generated types + def validate(self): if self.end_date < self.start_date: frappe.throw(_("End date cannot be before start date")) diff --git a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py index eb8c16ee11..67a7f90042 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py @@ -9,6 +9,31 @@ from frappe.utils.scheduler import is_scheduler_inactive class ProcessPaymentReconciliation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + bank_cash_account: DF.Link | None + company: DF.Link + cost_center: DF.Link | None + error_log: DF.LongText | None + from_invoice_date: DF.Date | None + from_payment_date: DF.Date | None + party: DF.DynamicLink + party_type: DF.Link + receivable_payable_account: DF.Link + status: DF.Literal[ + "", "Queued", "Running", "Paused", "Completed", "Partially Reconciled", "Failed", "Cancelled" + ] + to_invoice_date: DF.Date | None + to_payment_date: DF.Date | None + # end: auto-generated types + def validate(self): self.validate_receivable_payable_account() self.validate_bank_cash_account() diff --git a/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.py b/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.py index 85d70a4832..153fffcf77 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.py @@ -6,4 +6,28 @@ from frappe.model.document import Document class ProcessPaymentReconciliationLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.process_payment_reconciliation_log_allocations.process_payment_reconciliation_log_allocations import ( + ProcessPaymentReconciliationLogAllocations, + ) + + allocated: DF.Check + allocations: DF.Table[ProcessPaymentReconciliationLogAllocations] + error_log: DF.LongText | None + process_pr: DF.Link + reconciled: DF.Check + reconciled_entries: DF.Int + status: DF.Literal[ + "Running", "Paused", "Reconciled", "Partially Reconciled", "Failed", "Cancelled" + ] + total_allocations: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.py b/erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.py index c3e43297d0..da02e1a41e 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.py @@ -6,4 +6,31 @@ from frappe.model.document import Document class ProcessPaymentReconciliationLogAllocations(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allocated_amount: DF.Currency + amount: DF.Currency + currency: DF.Link | None + difference_account: DF.Link | None + difference_amount: DF.Currency + exchange_rate: DF.Float + invoice_number: DF.DynamicLink + invoice_type: DF.Link + is_advance: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + reconciled: DF.Check + reference_name: DF.DynamicLink + reference_row: DF.Data | None + reference_type: DF.Link + unreconciled_amount: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index 6c959ba2f0..9ad25483e3 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -23,6 +23,60 @@ from erpnext.accounts.report.general_ledger.general_ledger import execute as get class ProcessStatementOfAccounts(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.process_statement_of_accounts_customer.process_statement_of_accounts_customer import ( + ProcessStatementOfAccountsCustomer, + ) + from erpnext.accounts.doctype.psoa_cost_center.psoa_cost_center import PSOACostCenter + from erpnext.accounts.doctype.psoa_project.psoa_project import PSOAProject + + account: DF.Link | None + ageing_based_on: DF.Literal["Due Date", "Posting Date"] + based_on_payment_terms: DF.Check + body: DF.TextEditor | None + cc_to: DF.Link | None + collection_name: DF.DynamicLink | None + company: DF.Link + cost_center: DF.TableMultiSelect[PSOACostCenter] + currency: DF.Link | None + customer_collection: DF.Literal[ + "", "Customer Group", "Territory", "Sales Partner", "Sales Person" + ] + customers: DF.Table[ProcessStatementOfAccountsCustomer] + enable_auto_email: DF.Check + filter_duration: DF.Int + finance_book: DF.Link | None + frequency: DF.Literal["Weekly", "Monthly", "Quarterly"] + from_date: DF.Date | None + group_by: DF.Literal["", "Group by Voucher", "Group by Voucher (Consolidated)"] + include_ageing: DF.Check + include_break: DF.Check + letter_head: DF.Link | None + orientation: DF.Literal["Landscape", "Portrait"] + payment_terms_template: DF.Link | None + pdf_name: DF.Data | None + posting_date: DF.Date | None + primary_mandatory: DF.Check + project: DF.TableMultiSelect[PSOAProject] + report: DF.Literal["General Ledger", "Accounts Receivable"] + sales_partner: DF.Link | None + sales_person: DF.Link | None + sender: DF.Link | None + show_net_values_in_party_account: DF.Check + start_date: DF.Date | None + subject: DF.Data | None + terms_and_conditions: DF.Link | None + territory: DF.Link | None + to_date: DF.Date | None + # end: auto-generated types + def validate(self): if not self.subject: self.subject = "Statement Of Accounts for {{ customer.customer_name }}" diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py index 94fcb78e31..cac2877704 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py @@ -7,4 +7,21 @@ from frappe.model.document import Document class ProcessStatementOfAccountsCustomer(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + billing_email: DF.Data | None + customer: DF.Link + customer_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + primary_email: DF.ReadOnly | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/process_subscription/process_subscription.py b/erpnext/accounts/doctype/process_subscription/process_subscription.py index 0aa9970cb8..b271e7c622 100644 --- a/erpnext/accounts/doctype/process_subscription/process_subscription.py +++ b/erpnext/accounts/doctype/process_subscription/process_subscription.py @@ -12,6 +12,19 @@ from erpnext.accounts.doctype.subscription.subscription import process_all class ProcessSubscription(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + posting_date: DF.Date + subscription: DF.Link | None + # end: auto-generated types + def on_submit(self): process_all(subscription=self.subscription, posting_date=self.posting_date) diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py index 4d28d10660..0bb8d3a457 100644 --- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py +++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py @@ -69,6 +69,73 @@ class TransactionExists(frappe.ValidationError): class PromotionalScheme(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.campaign_item.campaign_item import CampaignItem + from erpnext.accounts.doctype.customer_group_item.customer_group_item import CustomerGroupItem + from erpnext.accounts.doctype.customer_item.customer_item import CustomerItem + from erpnext.accounts.doctype.pricing_rule_brand.pricing_rule_brand import PricingRuleBrand + from erpnext.accounts.doctype.pricing_rule_item_code.pricing_rule_item_code import ( + PricingRuleItemCode, + ) + from erpnext.accounts.doctype.pricing_rule_item_group.pricing_rule_item_group import ( + PricingRuleItemGroup, + ) + from erpnext.accounts.doctype.promotional_scheme_price_discount.promotional_scheme_price_discount import ( + PromotionalSchemePriceDiscount, + ) + from erpnext.accounts.doctype.promotional_scheme_product_discount.promotional_scheme_product_discount import ( + PromotionalSchemeProductDiscount, + ) + from erpnext.accounts.doctype.sales_partner_item.sales_partner_item import SalesPartnerItem + from erpnext.accounts.doctype.supplier_group_item.supplier_group_item import SupplierGroupItem + from erpnext.accounts.doctype.supplier_item.supplier_item import SupplierItem + from erpnext.accounts.doctype.territory_item.territory_item import TerritoryItem + + applicable_for: DF.Literal[ + "", + "Customer", + "Customer Group", + "Territory", + "Sales Partner", + "Campaign", + "Supplier", + "Supplier Group", + ] + apply_on: DF.Literal["", "Item Code", "Item Group", "Brand", "Transaction"] + apply_rule_on_other: DF.Literal["", "Item Code", "Item Group", "Brand"] + brands: DF.Table[PricingRuleBrand] + buying: DF.Check + campaign: DF.TableMultiSelect[CampaignItem] + company: DF.Link + currency: DF.Link | None + customer: DF.TableMultiSelect[CustomerItem] + customer_group: DF.TableMultiSelect[CustomerGroupItem] + disable: DF.Check + is_cumulative: DF.Check + item_groups: DF.Table[PricingRuleItemGroup] + items: DF.Table[PricingRuleItemCode] + mixed_conditions: DF.Check + other_brand: DF.Link | None + other_item_code: DF.Link | None + other_item_group: DF.Link | None + price_discount_slabs: DF.Table[PromotionalSchemePriceDiscount] + product_discount_slabs: DF.Table[PromotionalSchemeProductDiscount] + sales_partner: DF.TableMultiSelect[SalesPartnerItem] + selling: DF.Check + supplier: DF.TableMultiSelect[SupplierItem] + supplier_group: DF.TableMultiSelect[SupplierGroupItem] + territory: DF.TableMultiSelect[TerritoryItem] + valid_from: DF.Date | None + valid_upto: DF.Date | None + # end: auto-generated types + def validate(self): if not self.selling and not self.buying: frappe.throw(_("Either 'Selling' or 'Buying' must be selected"), title=_("Mandatory")) diff --git a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py index a0e220004e..545c17dda8 100644 --- a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py +++ b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.py @@ -6,4 +6,55 @@ from frappe.model.document import Document class PromotionalSchemePriceDiscount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + apply_discount_on_rate: DF.Check + apply_multiple_pricing_rules: DF.Check + disable: DF.Check + discount_amount: DF.Currency + discount_percentage: DF.Float + max_amount: DF.Currency + max_qty: DF.Float + min_amount: DF.Currency + min_qty: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + priority: DF.Literal[ + "", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + ] + rate: DF.Currency + rate_or_discount: DF.Literal["", "Rate", "Discount Percentage", "Discount Amount"] + rule_description: DF.SmallText + threshold_percentage: DF.Percent + validate_applied_rule: DF.Check + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py index c9f6f86346..7dd5fea373 100644 --- a/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py +++ b/erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.py @@ -6,4 +6,55 @@ from frappe.model.document import Document class PromotionalSchemeProductDiscount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + apply_multiple_pricing_rules: DF.Check + disable: DF.Check + free_item: DF.Link | None + free_item_rate: DF.Currency + free_item_uom: DF.Link | None + free_qty: DF.Float + is_recursive: DF.Check + max_amount: DF.Currency + max_qty: DF.Float + min_amount: DF.Currency + min_qty: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + priority: DF.Literal[ + "", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + ] + rule_description: DF.SmallText + same_item: DF.Check + threshold_percentage: DF.Percent + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py index 877998a187..683cd78df0 100644 --- a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py +++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class PSOACostCenter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + cost_center_name: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.py b/erpnext/accounts/doctype/psoa_project/psoa_project.py index de22bb7304..c2d80767bc 100644 --- a/erpnext/accounts/doctype/psoa_project/psoa_project.py +++ b/erpnext/accounts/doctype/psoa_project/psoa_project.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class PSOAProject(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project_name: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index c6ae9377a0..f9c9fb5ac5 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -54,6 +54,174 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class PurchaseInvoice(BuyingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.advance_tax.advance_tax import AdvanceTax + from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.purchase_invoice_advance.purchase_invoice_advance import ( + PurchaseInvoiceAdvance, + ) + from erpnext.accounts.doctype.purchase_invoice_item.purchase_invoice_item import ( + PurchaseInvoiceItem, + ) + from erpnext.accounts.doctype.purchase_taxes_and_charges.purchase_taxes_and_charges import ( + PurchaseTaxesandCharges, + ) + from erpnext.accounts.doctype.tax_withheld_vouchers.tax_withheld_vouchers import ( + TaxWithheldVouchers, + ) + from erpnext.buying.doctype.purchase_receipt_item_supplied.purchase_receipt_item_supplied import ( + PurchaseReceiptItemSupplied, + ) + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + advance_tax: DF.Table[AdvanceTax] + advances: DF.Table[PurchaseInvoiceAdvance] + against_expense_account: DF.SmallText | None + allocate_advances_automatically: DF.Check + amended_from: DF.Link | None + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + apply_tds: DF.Check + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_paid_amount: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_tax_withholding_net_total: DF.Currency + base_taxes_and_charges_added: DF.Currency + base_taxes_and_charges_deducted: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + base_write_off_amount: DF.Currency + bill_date: DF.Date | None + bill_no: DF.Data | None + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + buying_price_list: DF.Link | None + cash_bank_account: DF.Link | None + clearance_date: DF.Date | None + company: DF.Link | None + contact_display: DF.SmallText | None + contact_email: DF.SmallText | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + credit_to: DF.Link + currency: DF.Link | None + disable_rounded_total: DF.Check + discount_amount: DF.Currency + due_date: DF.Date | None + from_date: DF.Date | None + grand_total: DF.Currency + group_same_items: DF.Check + hold_comment: DF.SmallText | None + ignore_default_payment_terms_template: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + inter_company_invoice_reference: DF.Link | None + is_internal_supplier: DF.Check + is_old_subcontracting_flow: DF.Check + is_opening: DF.Literal["No", "Yes"] + is_paid: DF.Check + is_return: DF.Check + is_subcontracted: DF.Check + items: DF.Table[PurchaseInvoiceItem] + language: DF.Data | None + letter_head: DF.Link | None + mode_of_payment: DF.Link | None + named_place: DF.Data | None + naming_series: DF.Literal["ACC-PINV-.YYYY.-", "ACC-PINV-RET-.YYYY.-"] + net_total: DF.Currency + on_hold: DF.Check + only_include_allocated_payments: DF.Check + other_charges_calculation: DF.LongText | None + outstanding_amount: DF.Currency + paid_amount: DF.Currency + party_account_currency: DF.Link | None + payment_schedule: DF.Table[PaymentSchedule] + payment_terms_template: DF.Link | None + per_received: DF.Percent + plc_conversion_rate: DF.Float + posting_date: DF.Date + posting_time: DF.Time | None + price_list_currency: DF.Link | None + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + rejected_warehouse: DF.Link | None + release_date: DF.Date | None + remarks: DF.SmallText | None + repost_required: DF.Check + represents_company: DF.Link | None + return_against: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + set_from_warehouse: DF.Link | None + set_posting_time: DF.Check + set_warehouse: DF.Link | None + shipping_address: DF.Link | None + shipping_address_display: DF.SmallText | None + shipping_rule: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "Return", + "Debit Note Issued", + "Submitted", + "Paid", + "Partly Paid", + "Unpaid", + "Overdue", + "Cancelled", + "Internal Transfer", + ] + subscription: DF.Link | None + supplied_items: DF.Table[PurchaseReceiptItemSupplied] + supplier: DF.Link + supplier_address: DF.Link | None + supplier_name: DF.Data | None + supplier_warehouse: DF.Link | None + tax_category: DF.Link | None + tax_id: DF.ReadOnly | None + tax_withheld_vouchers: DF.Table[TaxWithheldVouchers] + tax_withholding_category: DF.Link | None + tax_withholding_net_total: DF.Currency + taxes: DF.Table[PurchaseTaxesandCharges] + taxes_and_charges: DF.Link | None + taxes_and_charges_added: DF.Currency + taxes_and_charges_deducted: DF.Currency + tc_name: DF.Link | None + terms: DF.TextEditor | None + title: DF.Data | None + to_date: DF.Date | None + total: DF.Currency + total_advance: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + unrealized_profit_loss_account: DF.Link | None + update_stock: DF.Check + use_company_roundoff_cost_center: DF.Check + use_transaction_date_exchange_rate: DF.Check + write_off_account: DF.Link | None + write_off_amount: DF.Currency + write_off_cost_center: DF.Link | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(PurchaseInvoice, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py index 44e1f6d568..bbd3009224 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class PurchaseInvoiceAdvance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + advance_amount: DF.Currency + allocated_amount: DF.Currency + exchange_gain_loss: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + ref_exchange_rate: DF.Float + reference_name: DF.DynamicLink | None + reference_row: DF.Data | None + reference_type: DF.Link | None + remarks: DF.Text | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py index 0e3c723178..e48d22379a 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py @@ -6,4 +6,93 @@ from frappe.model.document import Document class PurchaseInvoiceItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + apply_tds: DF.Check + asset_category: DF.Link | None + asset_location: DF.Link | None + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + batch_no: DF.Link | None + bom: DF.Link | None + brand: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + deferred_expense_account: DF.Link | None + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + enable_deferred_expense: DF.Check + expense_account: DF.Link | None + from_warehouse: DF.Link | None + image: DF.Attach | None + include_exploded_items: DF.Check + is_fixed_asset: DF.Check + is_free_item: DF.Check + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data + item_tax_amount: DF.Currency + item_tax_rate: DF.Code | None + item_tax_template: DF.Link | None + landed_cost_voucher_amount: DF.Currency + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + po_detail: DF.Data | None + pr_detail: DF.Data | None + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + product_bundle: DF.Link | None + project: DF.Link | None + purchase_invoice_item: DF.Data | None + purchase_order: DF.Link | None + purchase_receipt: DF.Link | None + qty: DF.Float + quality_inspection: DF.Link | None + rate: DF.Currency + rate_with_margin: DF.Currency + received_qty: DF.Float + rejected_qty: DF.Float + rejected_serial_and_batch_bundle: DF.Link | None + rejected_serial_no: DF.Text | None + rejected_warehouse: DF.Link | None + rm_supp_cost: DF.Currency + sales_invoice_item: DF.Data | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.Text | None + service_end_date: DF.Date | None + service_start_date: DF.Date | None + service_stop_date: DF.Date | None + stock_qty: DF.Float + stock_uom: DF.Link | None + stock_uom_rate: DF.Currency + total_weight: DF.Float + uom: DF.Link + valuation_rate: DF.Currency + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + wip_composite_asset: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py index 262e7ebb5b..d6c0292244 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py @@ -6,4 +6,42 @@ from frappe.model.document import Document class PurchaseTaxesandCharges(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_currency: DF.Link | None + account_head: DF.Link + add_deduct_tax: DF.Literal["Add", "Deduct"] + base_tax_amount: DF.Currency + base_tax_amount_after_discount_amount: DF.Currency + base_total: DF.Currency + category: DF.Literal["Valuation and Total", "Valuation", "Total"] + charge_type: DF.Literal[ + "", + "Actual", + "On Net Total", + "On Previous Row Amount", + "On Previous Row Total", + "On Item Quantity", + ] + cost_center: DF.Link | None + description: DF.SmallText + included_in_paid_amount: DF.Check + included_in_print_rate: DF.Check + item_wise_tax_detail: DF.Code | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Float + row_id: DF.Data | None + tax_amount: DF.Currency + tax_amount_after_discount_amount: DF.Currency + total: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py index 70d29bfda2..16c30c52bd 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.py @@ -11,6 +11,26 @@ from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_c class PurchaseTaxesandChargesTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.purchase_taxes_and_charges.purchase_taxes_and_charges import ( + PurchaseTaxesandCharges, + ) + + company: DF.Link + disabled: DF.Check + is_default: DF.Check + tax_category: DF.Link | None + taxes: DF.Table[PurchaseTaxesandCharges] + title: DF.Data + # end: auto-generated types + def validate(self): valdiate_taxes_and_charges_template(self) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py index 1d72a46c12..8c23c67c20 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -8,6 +8,24 @@ from frappe.utils.data import comma_and class RepostAccountingLedger(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.repost_accounting_ledger_items.repost_accounting_ledger_items import ( + RepostAccountingLedgerItems, + ) + + amended_from: DF.Link | None + company: DF.Link | None + delete_cancelled_entries: DF.Check + vouchers: DF.Table[RepostAccountingLedgerItems] + # end: auto-generated types + def __init__(self, *args, **kwargs): super(RepostAccountingLedger, self).__init__(*args, **kwargs) self._allowed_types = get_allowed_types_from_settings() diff --git a/erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.py b/erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.py index 9221f44735..6e02e3a6b9 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class RepostAccountingLedgerItems(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/repost_accounting_ledger_settings/repost_accounting_ledger_settings.py b/erpnext/accounts/doctype/repost_accounting_ledger_settings/repost_accounting_ledger_settings.py index 2b8230df86..14a070dc46 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger_settings/repost_accounting_ledger_settings.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger_settings/repost_accounting_ledger_settings.py @@ -6,4 +6,17 @@ from frappe.model.document import Document class RepostAccountingLedgerSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.repost_allowed_types.repost_allowed_types import RepostAllowedTypes + + allowed_types: DF.Table[RepostAllowedTypes] + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/repost_allowed_types/repost_allowed_types.py b/erpnext/accounts/doctype/repost_allowed_types/repost_allowed_types.py index 0e4883b0c9..8226a91017 100644 --- a/erpnext/accounts/doctype/repost_allowed_types/repost_allowed_types.py +++ b/erpnext/accounts/doctype/repost_allowed_types/repost_allowed_types.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class RepostAllowedTypes(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allowed: DF.Check + document_type: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py index 209cad4f90..38bc1a6fb8 100644 --- a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py +++ b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py @@ -52,6 +52,28 @@ def start_payment_ledger_repost(docname=None): class RepostPaymentLedger(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.repost_payment_ledger_items.repost_payment_ledger_items import ( + RepostPaymentLedgerItems, + ) + + add_manually: DF.Check + amended_from: DF.Link | None + company: DF.Link + posting_date: DF.Date + repost_error_log: DF.LongText | None + repost_status: DF.Literal["", "Queued", "Failed", "Completed"] + repost_vouchers: DF.Table[RepostPaymentLedgerItems] + voucher_type: DF.Link | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(RepostPaymentLedger, self).__init__(*args, **kwargs) self.vouchers = [] diff --git a/erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.py b/erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.py index fb19e84f26..5f935183e7 100644 --- a/erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.py +++ b/erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class RepostPaymentLedgerItems(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 85cb3679c7..0ebf33564f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -45,6 +45,189 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class SalesInvoice(SellingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.sales_invoice_advance.sales_invoice_advance import ( + SalesInvoiceAdvance, + ) + from erpnext.accounts.doctype.sales_invoice_item.sales_invoice_item import SalesInvoiceItem + from erpnext.accounts.doctype.sales_invoice_payment.sales_invoice_payment import ( + SalesInvoicePayment, + ) + from erpnext.accounts.doctype.sales_invoice_timesheet.sales_invoice_timesheet import ( + SalesInvoiceTimesheet, + ) + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, + ) + from erpnext.selling.doctype.sales_team.sales_team import SalesTeam + from erpnext.stock.doctype.packed_item.packed_item import PackedItem + + account_for_change_amount: DF.Link | None + additional_discount_account: DF.Link | None + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + advances: DF.Table[SalesInvoiceAdvance] + against_income_account: DF.SmallText | None + allocate_advances_automatically: DF.Check + amended_from: DF.Link | None + amount_eligible_for_commission: DF.Currency + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + auto_repeat: DF.Link | None + base_change_amount: DF.Currency + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.SmallText | None + base_net_total: DF.Currency + base_paid_amount: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + base_write_off_amount: DF.Currency + campaign: DF.Link | None + cash_bank_account: DF.Link | None + change_amount: DF.Currency + commission_rate: DF.Float + company: DF.Link + company_address: DF.Link | None + company_address_display: DF.SmallText | None + company_tax_id: DF.Data | None + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + currency: DF.Link + customer: DF.Link | None + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.SmallText | None + debit_to: DF.Link + disable_rounded_total: DF.Check + discount_amount: DF.Currency + dispatch_address: DF.SmallText | None + dispatch_address_name: DF.Link | None + due_date: DF.Date | None + from_date: DF.Date | None + grand_total: DF.Currency + group_same_items: DF.Check + ignore_default_payment_terms_template: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.SmallText | None + incoterm: DF.Link | None + inter_company_invoice_reference: DF.Link | None + is_cash_or_non_trade_discount: DF.Check + is_consolidated: DF.Check + is_debit_note: DF.Check + is_discounted: DF.Check + is_internal_customer: DF.Check + is_opening: DF.Literal["No", "Yes"] + is_pos: DF.Check + is_return: DF.Check + items: DF.Table[SalesInvoiceItem] + language: DF.Data | None + letter_head: DF.Link | None + loyalty_amount: DF.Currency + loyalty_points: DF.Int + loyalty_program: DF.Link | None + loyalty_redemption_account: DF.Link | None + loyalty_redemption_cost_center: DF.Link | None + named_place: DF.Data | None + naming_series: DF.Literal["ACC-SINV-.YYYY.-", "ACC-SINV-RET-.YYYY.-"] + net_total: DF.Currency + only_include_allocated_payments: DF.Check + other_charges_calculation: DF.LongText | None + outstanding_amount: DF.Currency + packed_items: DF.Table[PackedItem] + paid_amount: DF.Currency + party_account_currency: DF.Link | None + payment_schedule: DF.Table[PaymentSchedule] + payment_terms_template: DF.Link | None + payments: DF.Table[SalesInvoicePayment] + plc_conversion_rate: DF.Float + po_date: DF.Date | None + po_no: DF.Data | None + pos_profile: DF.Link | None + posting_date: DF.Date + posting_time: DF.Time | None + price_list_currency: DF.Link + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + redeem_loyalty_points: DF.Check + remarks: DF.SmallText | None + repost_required: DF.Check + represents_company: DF.Link | None + return_against: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + sales_partner: DF.Link | None + sales_team: DF.Table[SalesTeam] + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + selling_price_list: DF.Link + set_posting_time: DF.Check + set_target_warehouse: DF.Link | None + set_warehouse: DF.Link | None + shipping_address: DF.SmallText | None + shipping_address_name: DF.Link | None + shipping_rule: DF.Link | None + source: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "Return", + "Credit Note Issued", + "Submitted", + "Paid", + "Partly Paid", + "Unpaid", + "Unpaid and Discounted", + "Partly Paid and Discounted", + "Overdue and Discounted", + "Overdue", + "Cancelled", + "Internal Transfer", + ] + subscription: DF.Link | None + tax_category: DF.Link | None + tax_id: DF.Data | None + taxes: DF.Table[SalesTaxesandCharges] + taxes_and_charges: DF.Link | None + tc_name: DF.Link | None + terms: DF.TextEditor | None + territory: DF.Link | None + timesheets: DF.Table[SalesInvoiceTimesheet] + title: DF.Data | None + to_date: DF.Date | None + total: DF.Currency + total_advance: DF.Currency + total_billing_amount: DF.Currency + total_billing_hours: DF.Float + total_commission: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + unrealized_profit_loss_account: DF.Link | None + update_billed_amount_in_delivery_note: DF.Check + update_billed_amount_in_sales_order: DF.Check + update_stock: DF.Check + use_company_roundoff_cost_center: DF.Check + write_off_account: DF.Link | None + write_off_amount: DF.Currency + write_off_cost_center: DF.Link | None + write_off_outstanding_amount_automatically: DF.Check + # end: auto-generated types + def __init__(self, *args, **kwargs): super(SalesInvoice, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py index 6d4bd4633c..5eeedb25f2 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class SalesInvoiceAdvance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + advance_amount: DF.Currency + allocated_amount: DF.Currency + exchange_gain_loss: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + ref_exchange_rate: DF.Float + reference_name: DF.DynamicLink | None + reference_row: DF.Data | None + reference_type: DF.Link | None + remarks: DF.Text | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py index ebeaf8b5ef..80f67748f4 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py @@ -6,4 +6,89 @@ from frappe.model.document import Document class SalesInvoiceItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_batch_qty: DF.Float + actual_qty: DF.Float + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + asset: DF.Link | None + barcode: DF.Data | None + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + batch_no: DF.Link | None + brand: DF.Data | None + conversion_factor: DF.Float + cost_center: DF.Link + customer_item_code: DF.Data | None + deferred_revenue_account: DF.Link | None + delivered_by_supplier: DF.Check + delivered_qty: DF.Float + delivery_note: DF.Link | None + description: DF.TextEditor | None + discount_account: DF.Link | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + dn_detail: DF.Data | None + enable_deferred_revenue: DF.Check + expense_account: DF.Link | None + finance_book: DF.Link | None + grant_commission: DF.Check + has_item_scanned: DF.Check + image: DF.Attach | None + income_account: DF.Link + incoming_rate: DF.Currency + is_fixed_asset: DF.Check + is_free_item: DF.Check + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data + item_tax_rate: DF.SmallText | None + item_tax_template: DF.Link | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + project: DF.Link | None + purchase_order: DF.Link | None + purchase_order_item: DF.Data | None + qty: DF.Float + quality_inspection: DF.Link | None + rate: DF.Currency + rate_with_margin: DF.Currency + sales_invoice_item: DF.Data | None + sales_order: DF.Link | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + service_end_date: DF.Date | None + service_start_date: DF.Date | None + service_stop_date: DF.Date | None + so_detail: DF.Data | None + stock_qty: DF.Float + stock_uom: DF.Link | None + stock_uom_rate: DF.Currency + target_warehouse: DF.Link | None + total_weight: DF.Float + uom: DF.Link + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py index d9b1dbe346..57d0142406 100644 --- a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py +++ b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.py @@ -6,4 +6,24 @@ from frappe.model.document import Document class SalesInvoicePayment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + amount: DF.Currency + base_amount: DF.Currency + clearance_date: DF.Date | None + default: DF.Check + mode_of_payment: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + type: DF.ReadOnly | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py index e50b1c2861..108241df31 100644 --- a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py +++ b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.py @@ -6,4 +6,26 @@ from frappe.model.document import Document class SalesInvoiceTimesheet(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + activity_type: DF.Link | None + billing_amount: DF.Currency + billing_hours: DF.Float + description: DF.SmallText | None + from_time: DF.Datetime | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project_name: DF.Data | None + time_sheet: DF.Link | None + timesheet_detail: DF.Data | None + to_time: DF.Datetime | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py b/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py index 97489d155f..c6715dca34 100644 --- a/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py +++ b/erpnext/accounts/doctype/sales_partner_item/sales_partner_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class SalesPartnerItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + sales_partner: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py index d412c1b730..7936178fda 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py @@ -6,4 +6,41 @@ from frappe.model.document import Document class SalesTaxesandCharges(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_currency: DF.Link | None + account_head: DF.Link + base_tax_amount: DF.Currency + base_tax_amount_after_discount_amount: DF.Currency + base_total: DF.Currency + charge_type: DF.Literal[ + "", + "Actual", + "On Net Total", + "On Previous Row Amount", + "On Previous Row Total", + "On Item Quantity", + ] + cost_center: DF.Link | None + description: DF.SmallText + dont_recompute_tax: DF.Check + included_in_paid_amount: DF.Check + included_in_print_rate: DF.Check + item_wise_tax_detail: DF.Code | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Float + row_id: DF.Data | None + tax_amount: DF.Currency + tax_amount_after_discount_amount: DF.Currency + total: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py index a3a5d627b7..ce3eda9bcf 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py @@ -16,6 +16,26 @@ from erpnext.controllers.accounts_controller import ( class SalesTaxesandChargesTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, + ) + + company: DF.Link + disabled: DF.Check + is_default: DF.Check + tax_category: DF.Link | None + taxes: DF.Table[SalesTaxesandCharges] + title: DF.Data + # end: auto-generated types + def validate(self): valdiate_taxes_and_charges_template(self) diff --git a/erpnext/accounts/doctype/share_balance/share_balance.py b/erpnext/accounts/doctype/share_balance/share_balance.py index 4c9ec439ee..7a77ce9b87 100644 --- a/erpnext/accounts/doctype/share_balance/share_balance.py +++ b/erpnext/accounts/doctype/share_balance/share_balance.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class ShareBalance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Int + current_state: DF.Literal["", "Issued", "Purchased"] + from_no: DF.Int + is_company: DF.Check + no_of_shares: DF.Int + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Int + share_type: DF.Link + to_no: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.py b/erpnext/accounts/doctype/share_transfer/share_transfer.py index 4f49843c1e..6a3ff7c394 100644 --- a/erpnext/accounts/doctype/share_transfer/share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/share_transfer.py @@ -15,6 +15,33 @@ class ShareDontExists(ValidationError): class ShareTransfer(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + amount: DF.Currency + asset_account: DF.Link | None + company: DF.Link + date: DF.Date + equity_or_liability_account: DF.Link + from_folio_no: DF.Data | None + from_no: DF.Int + from_shareholder: DF.Link | None + no_of_shares: DF.Int + rate: DF.Currency + remarks: DF.LongText | None + share_type: DF.Link + to_folio_no: DF.Data | None + to_no: DF.Int + to_shareholder: DF.Link | None + transfer_type: DF.Literal["", "Issue", "Purchase", "Transfer"] + # end: auto-generated types + def on_submit(self): if self.transfer_type == "Issue": shareholder = self.get_company_shareholder() diff --git a/erpnext/accounts/doctype/share_type/share_type.py b/erpnext/accounts/doctype/share_type/share_type.py index 80365aa2f2..df8cbaf76b 100644 --- a/erpnext/accounts/doctype/share_type/share_type.py +++ b/erpnext/accounts/doctype/share_type/share_type.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class ShareType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.LongText | None + title: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/shareholder/shareholder.py b/erpnext/accounts/doctype/shareholder/shareholder.py index b0e2493f7a..6542f93b60 100644 --- a/erpnext/accounts/doctype/shareholder/shareholder.py +++ b/erpnext/accounts/doctype/shareholder/shareholder.py @@ -10,6 +10,25 @@ from frappe.model.document import Document class Shareholder(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.share_balance.share_balance import ShareBalance + + company: DF.Link + contact_list: DF.Code | None + folio_no: DF.Data | None + is_company: DF.Check + naming_series: DF.Literal["ACC-SH-.YYYY.-"] + share_balance: DF.Table[ShareBalance] + title: DF.Data + # end: auto-generated types + def onload(self): """Load address and contacts in `__onload`""" load_address_and_contact(self) diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py index 1d79503a05..52a60ac7aa 100644 --- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py @@ -25,6 +25,33 @@ class ManyBlankToValuesError(frappe.ValidationError): class ShippingRule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.shipping_rule_condition.shipping_rule_condition import ( + ShippingRuleCondition, + ) + from erpnext.accounts.doctype.shipping_rule_country.shipping_rule_country import ( + ShippingRuleCountry, + ) + + account: DF.Link + calculate_based_on: DF.Literal["Fixed", "Net Total", "Net Weight"] + company: DF.Link + conditions: DF.Table[ShippingRuleCondition] + cost_center: DF.Link + countries: DF.Table[ShippingRuleCountry] + disabled: DF.Check + label: DF.Data + shipping_amount: DF.Currency + shipping_rule_type: DF.Literal["Selling", "Buying"] + # end: auto-generated types + def validate(self): self.validate_from_to_values() self.sort_shipping_rule_conditions() diff --git a/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py b/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py index 07f98deb23..4370477cc1 100644 --- a/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py +++ b/erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py @@ -8,4 +8,20 @@ from frappe.model.document import Document class ShippingRuleCondition(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from_value: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + shipping_amount: DF.Currency + to_value: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py b/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py index 90123c1616..ff06e8f795 100644 --- a/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py +++ b/erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class ShippingRuleCountry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + country: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py b/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py index d9a3bcc0df..516038a7f7 100644 --- a/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py +++ b/erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class SouthAfricaVATAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index a3d8c23418..6cc2d1e9ee 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -40,6 +40,51 @@ DateTimeLikeObject = Union[str, datetime.date] class Subscription(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.subscription_plan_detail.subscription_plan_detail import ( + SubscriptionPlanDetail, + ) + + additional_discount_amount: DF.Currency + additional_discount_percentage: DF.Percent + apply_additional_discount: DF.Literal["", "Grand Total", "Net Total"] + cancel_at_period_end: DF.Check + cancelation_date: DF.Date | None + company: DF.Link | None + cost_center: DF.Link | None + current_invoice_end: DF.Date | None + current_invoice_start: DF.Date | None + days_until_due: DF.Int + end_date: DF.Date | None + follow_calendar_months: DF.Check + generate_invoice_at: DF.Literal[ + "End of the current subscription period", + "Beginning of the current subscription period", + "Days before the current subscription period", + ] + generate_new_invoices_past_due_date: DF.Check + number_of_days: DF.Int + party: DF.DynamicLink + party_type: DF.Link + plans: DF.Table[SubscriptionPlanDetail] + purchase_tax_template: DF.Link | None + sales_tax_template: DF.Link | None + start_date: DF.Date | None + status: DF.Literal[ + "", "Trialling", "Active", "Past Due Date", "Cancelled", "Unpaid", "Completed" + ] + submit_invoice: DF.Check + trial_period_end: DF.Date | None + trial_period_start: DF.Date | None + # end: auto-generated types + def before_insert(self): # update start just before the subscription doc is created self.update_subscription_period(self.start_date) diff --git a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py index 41f7f9f6f3..ecef5e78ce 100644 --- a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py +++ b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class SubscriptionInvoice(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + document_type: DF.Link | None + invoice: DF.DynamicLink | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index f6e5c56cce..118d254780 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -12,6 +12,27 @@ from erpnext.utilities.product import get_price class SubscriptionPlan(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + billing_interval: DF.Literal["Day", "Week", "Month", "Year"] + billing_interval_count: DF.Int + cost: DF.Currency + cost_center: DF.Link | None + currency: DF.Link | None + item: DF.Link + payment_gateway: DF.Link | None + plan_name: DF.Data + price_determination: DF.Literal["", "Fixed Rate", "Based On Price List", "Monthly Rate"] + price_list: DF.Link | None + product_price_id: DF.Data | None + # end: auto-generated types + def validate(self): self.validate_interval_count() diff --git a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py index d22a73f25d..91f3319d38 100644 --- a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py +++ b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class SubscriptionPlanDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + plan: DF.Link + qty: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/subscription_settings/subscription_settings.py b/erpnext/accounts/doctype/subscription_settings/subscription_settings.py index 12580db1ed..abc698e17d 100644 --- a/erpnext/accounts/doctype/subscription_settings/subscription_settings.py +++ b/erpnext/accounts/doctype/subscription_settings/subscription_settings.py @@ -6,4 +6,17 @@ from frappe.model.document import Document class SubscriptionSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + cancel_after_grace: DF.Check + grace_period: DF.Int + prorate: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py b/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py index 61c16fe0ff..bcad816fb5 100644 --- a/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py +++ b/erpnext/accounts/doctype/supplier_group_item/supplier_group_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class SupplierGroupItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + supplier_group: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/supplier_item/supplier_item.py b/erpnext/accounts/doctype/supplier_item/supplier_item.py index 2105b1d332..c90a53aefe 100644 --- a/erpnext/accounts/doctype/supplier_item/supplier_item.py +++ b/erpnext/accounts/doctype/supplier_item/supplier_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class SupplierItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + supplier: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/tax_category/tax_category.py b/erpnext/accounts/doctype/tax_category/tax_category.py index 18cf72ad59..bfb1f16723 100644 --- a/erpnext/accounts/doctype/tax_category/tax_category.py +++ b/erpnext/accounts/doctype/tax_category/tax_category.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class TaxCategory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + disabled: DF.Check + title: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index ac0dd5123a..9ff530bfaf 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -27,6 +27,41 @@ class ConflictingTaxRule(frappe.ValidationError): class TaxRule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + billing_city: DF.Data | None + billing_country: DF.Link | None + billing_county: DF.Data | None + billing_state: DF.Data | None + billing_zipcode: DF.Data | None + company: DF.Link | None + customer: DF.Link | None + customer_group: DF.Link | None + from_date: DF.Date | None + item: DF.Link | None + item_group: DF.Link | None + priority: DF.Int + purchase_tax_template: DF.Link | None + sales_tax_template: DF.Link | None + shipping_city: DF.Data | None + shipping_country: DF.Link | None + shipping_county: DF.Data | None + shipping_state: DF.Data | None + shipping_zipcode: DF.Data | None + supplier: DF.Link | None + supplier_group: DF.Link | None + tax_category: DF.Link | None + tax_type: DF.Literal["Sales", "Purchase"] + to_date: DF.Date | None + use_for_shopping_cart: DF.Check + # end: auto-generated types + def __setup__(self): self.flags.ignore_these_exceptions_in_test = [ConflictingTaxRule] diff --git a/erpnext/accounts/doctype/tax_withheld_vouchers/tax_withheld_vouchers.py b/erpnext/accounts/doctype/tax_withheld_vouchers/tax_withheld_vouchers.py index ea54c5403a..bc2003e2be 100644 --- a/erpnext/accounts/doctype/tax_withheld_vouchers/tax_withheld_vouchers.py +++ b/erpnext/accounts/doctype/tax_withheld_vouchers/tax_withheld_vouchers.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class TaxWithheldVouchers(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + taxable_amount: DF.Currency + voucher_name: DF.DynamicLink | None + voucher_type: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py b/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py index c8d9d45ec7..f22ecba7e6 100644 --- a/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py +++ b/erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class TaxWithholdingAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link + company: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index de2f9e7e0d..c39a9db980 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -11,6 +11,27 @@ from frappe.utils import cint, flt, getdate class TaxWithholdingCategory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.tax_withholding_account.tax_withholding_account import ( + TaxWithholdingAccount, + ) + from erpnext.accounts.doctype.tax_withholding_rate.tax_withholding_rate import TaxWithholdingRate + + accounts: DF.Table[TaxWithholdingAccount] + category_name: DF.Data | None + consider_party_ledger_amount: DF.Check + rates: DF.Table[TaxWithholdingRate] + round_off_tax_amount: DF.Check + tax_on_excess_amount: DF.Check + # end: auto-generated types + def validate(self): self.validate_dates() self.validate_accounts() diff --git a/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py b/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py index 16cbccc8be..35d4e63ecc 100644 --- a/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py +++ b/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class TaxWithholdingRate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + cumulative_threshold: DF.Float + from_date: DF.Date + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + single_threshold: DF.Float + tax_withholding_rate: DF.Float + to_date: DF.Date + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/territory_item/territory_item.py b/erpnext/accounts/doctype/territory_item/territory_item.py index bcc02be2dd..cadcbcf16e 100644 --- a/erpnext/accounts/doctype/territory_item/territory_item.py +++ b/erpnext/accounts/doctype/territory_item/territory_item.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class TerritoryItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + territory: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py index 77906a7833..e258a73d4d 100644 --- a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py @@ -16,6 +16,25 @@ from erpnext.accounts.utils import ( class UnreconcilePayment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.unreconcile_payment_entries.unreconcile_payment_entries import ( + UnreconcilePaymentEntries, + ) + + allocations: DF.Table[UnreconcilePaymentEntries] + amended_from: DF.Link | None + company: DF.Link | None + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + # end: auto-generated types + def validate(self): self.supported_types = ["Payment Entry", "Journal Entry"] if not self.voucher_type in self.supported_types: diff --git a/erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.py b/erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.py index c41545c268..7c097b5eb0 100644 --- a/erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.py +++ b/erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class UnreconcilePaymentEntries(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Data | None + account_currency: DF.Link | None + allocated_amount: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + party: DF.Data | None + party_type: DF.Data | None + reference_doctype: DF.Link | None + reference_name: DF.DynamicLink | None + unlinked: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index d1f03f2046..5fb2d36178 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -40,6 +40,81 @@ from erpnext.controllers.accounts_controller import AccountsController class Asset(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.asset_finance_book.asset_finance_book import AssetFinanceBook + + amended_from: DF.Link | None + asset_category: DF.Link | None + asset_name: DF.Data + asset_owner: DF.Literal["", "Company", "Supplier", "Customer"] + asset_owner_company: DF.Link | None + asset_quantity: DF.Int + available_for_use_date: DF.Date + booked_fixed_asset: DF.Check + calculate_depreciation: DF.Check + capitalized_in: DF.Link | None + company: DF.Link + comprehensive_insurance: DF.Data | None + cost_center: DF.Link | None + custodian: DF.Link | None + customer: DF.Link | None + default_finance_book: DF.Link | None + department: DF.Link | None + depr_entry_posting_status: DF.Literal["", "Successful", "Failed"] + depreciation_method: DF.Literal["", "Straight Line", "Double Declining Balance", "Manual"] + disposal_date: DF.Date | None + finance_books: DF.Table[AssetFinanceBook] + frequency_of_depreciation: DF.Int + gross_purchase_amount: DF.Currency + image: DF.AttachImage | None + insurance_end_date: DF.Date | None + insurance_start_date: DF.Date | None + insured_value: DF.Data | None + insurer: DF.Data | None + is_composite_asset: DF.Check + is_existing_asset: DF.Check + is_fully_depreciated: DF.Check + item_code: DF.Link + item_name: DF.ReadOnly | None + journal_entry_for_scrap: DF.Link | None + location: DF.Link + maintenance_required: DF.Check + naming_series: DF.Literal["ACC-ASS-.YYYY.-"] + next_depreciation_date: DF.Date | None + number_of_depreciations_booked: DF.Int + opening_accumulated_depreciation: DF.Currency + policy_number: DF.Data | None + purchase_date: DF.Date + purchase_invoice: DF.Link | None + purchase_receipt: DF.Link | None + purchase_receipt_amount: DF.Currency + split_from: DF.Link | None + status: DF.Literal[ + "Draft", + "Submitted", + "Partially Depreciated", + "Fully Depreciated", + "Sold", + "Scrapped", + "In Maintenance", + "Out of Order", + "Issue", + "Receipt", + "Capitalized", + "Decapitalized", + ] + supplier: DF.Link | None + total_number_of_depreciations: DF.Int + value_after_depreciation: DF.Currency + # end: auto-generated types + def validate(self): self.validate_asset_values() self.validate_asset_and_reference() diff --git a/erpnext/assets/doctype/asset_activity/asset_activity.py b/erpnext/assets/doctype/asset_activity/asset_activity.py index 28e1b3e32a..a64cb1aba3 100644 --- a/erpnext/assets/doctype/asset_activity/asset_activity.py +++ b/erpnext/assets/doctype/asset_activity/asset_activity.py @@ -6,6 +6,20 @@ from frappe.model.document import Document class AssetActivity(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + asset: DF.Link + date: DF.Datetime + subject: DF.SmallText + user: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 728764be72..66997ca59c 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -49,6 +49,61 @@ force_fields = [ class AssetCapitalization(StockController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.asset_capitalization_asset_item.asset_capitalization_asset_item import ( + AssetCapitalizationAssetItem, + ) + from erpnext.assets.doctype.asset_capitalization_service_item.asset_capitalization_service_item import ( + AssetCapitalizationServiceItem, + ) + from erpnext.assets.doctype.asset_capitalization_stock_item.asset_capitalization_stock_item import ( + AssetCapitalizationStockItem, + ) + + amended_from: DF.Link | None + asset_items: DF.Table[AssetCapitalizationAssetItem] + asset_items_total: DF.Currency + capitalization_method: DF.Literal[ + "", "Create a new composite asset", "Choose a WIP composite asset" + ] + company: DF.Link + cost_center: DF.Link | None + entry_type: DF.Literal["Capitalization", "Decapitalization"] + finance_book: DF.Link | None + naming_series: DF.Literal["ACC-ASC-.YYYY.-"] + posting_date: DF.Date + posting_time: DF.Time + service_items: DF.Table[AssetCapitalizationServiceItem] + service_items_total: DF.Currency + set_posting_time: DF.Check + stock_items: DF.Table[AssetCapitalizationStockItem] + stock_items_total: DF.Currency + target_asset: DF.Link | None + target_asset_location: DF.Link | None + target_asset_name: DF.Data | None + target_batch_no: DF.Link | None + target_fixed_asset_account: DF.Link | None + target_has_batch_no: DF.Check + target_has_serial_no: DF.Check + target_incoming_rate: DF.Currency + target_is_fixed_asset: DF.Check + target_item_code: DF.Link | None + target_item_name: DF.Data | None + target_qty: DF.Float + target_serial_no: DF.SmallText | None + target_stock_uom: DF.Link | None + target_warehouse: DF.Link | None + title: DF.Data | None + total_value: DF.Currency + # end: auto-generated types + def validate(self): self.validate_posting_time() self.set_missing_values(for_validate=True) diff --git a/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.py b/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.py index ba356d6b9f..003973f94d 100644 --- a/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.py +++ b/erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.py @@ -6,4 +6,26 @@ from frappe.model.document import Document class AssetCapitalizationAssetItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + asset: DF.Link + asset_name: DF.Data | None + asset_value: DF.Currency + cost_center: DF.Link | None + current_asset_value: DF.Currency + finance_book: DF.Link | None + fixed_asset_account: DF.Link | None + item_code: DF.Link + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_capitalization_service_item/asset_capitalization_service_item.py b/erpnext/assets/doctype/asset_capitalization_service_item/asset_capitalization_service_item.py index 28d018ee39..93457f8785 100644 --- a/erpnext/assets/doctype/asset_capitalization_service_item/asset_capitalization_service_item.py +++ b/erpnext/assets/doctype/asset_capitalization_service_item/asset_capitalization_service_item.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class AssetCapitalizationServiceItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + cost_center: DF.Link | None + expense_account: DF.Link + item_code: DF.Link | None + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + rate: DF.Currency + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.py b/erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.py index 5d6f98d5cf..122cbb600d 100644 --- a/erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.py +++ b/erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class AssetCapitalizationStockItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + amount: DF.Currency + batch_no: DF.Link | None + cost_center: DF.Link | None + item_code: DF.Link + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + stock_qty: DF.Float + stock_uom: DF.Link + valuation_rate: DF.Currency + warehouse: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py index 8d351412ca..034ec555dc 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.py +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -9,6 +9,25 @@ from frappe.utils import cint, get_link_to_form class AssetCategory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.asset_category_account.asset_category_account import ( + AssetCategoryAccount, + ) + from erpnext.assets.doctype.asset_finance_book.asset_finance_book import AssetFinanceBook + + accounts: DF.Table[AssetCategoryAccount] + asset_category_name: DF.Data + enable_cwip_accounting: DF.Check + finance_books: DF.Table[AssetFinanceBook] + # end: auto-generated types + def validate(self): self.validate_finance_books() self.validate_account_types() diff --git a/erpnext/assets/doctype/asset_category_account/asset_category_account.py b/erpnext/assets/doctype/asset_category_account/asset_category_account.py index e06d233567..2798f1cd6b 100644 --- a/erpnext/assets/doctype/asset_category_account/asset_category_account.py +++ b/erpnext/assets/doctype/asset_category_account/asset_category_account.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class AssetCategoryAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + accumulated_depreciation_account: DF.Link | None + capital_work_in_progress_account: DF.Link | None + company_name: DF.Link + depreciation_expense_account: DF.Link | None + fixed_asset_account: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 6e390ce6f8..0021140282 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -21,6 +21,40 @@ import erpnext class AssetDepreciationSchedule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.depreciation_schedule.depreciation_schedule import ( + DepreciationSchedule, + ) + + amended_from: DF.Link | None + asset: DF.Link + daily_prorata_based: DF.Check + depreciation_method: DF.Literal[ + "", "Straight Line", "Double Declining Balance", "Written Down Value", "Manual" + ] + depreciation_schedule: DF.Table[DepreciationSchedule] + expected_value_after_useful_life: DF.Currency + finance_book: DF.Link | None + finance_book_id: DF.Int + frequency_of_depreciation: DF.Int + gross_purchase_amount: DF.Currency + naming_series: DF.Literal["ACC-ADS-.YYYY.-"] + notes: DF.SmallText | None + number_of_depreciations_booked: DF.Int + opening_accumulated_depreciation: DF.Currency + rate_of_depreciation: DF.Percent + shift_based: DF.Check + status: DF.Literal["Draft", "Active", "Cancelled"] + total_number_of_depreciations: DF.Int + # end: auto-generated types + def before_save(self): if not self.finance_book_id: self.prepare_draft_asset_depr_schedule_data_from_asset_name_and_fb_name( diff --git a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py index 292ca138fd..f812a0816d 100644 --- a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py +++ b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.py @@ -6,4 +6,30 @@ from frappe.model.document import Document class AssetFinanceBook(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + daily_prorata_based: DF.Check + depreciation_method: DF.Literal[ + "", "Straight Line", "Double Declining Balance", "Written Down Value", "Manual" + ] + depreciation_start_date: DF.Date | None + expected_value_after_useful_life: DF.Currency + finance_book: DF.Link | None + frequency_of_depreciation: DF.Int + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate_of_depreciation: DF.Percent + salvage_value_percentage: DF.Percent + shift_based: DF.Check + total_number_of_depreciations: DF.Int + value_after_depreciation: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py index 125d4bff19..063fe994aa 100644 --- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py @@ -10,6 +10,29 @@ from frappe.utils import add_days, add_months, add_years, getdate, nowdate class AssetMaintenance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.asset_maintenance_task.asset_maintenance_task import ( + AssetMaintenanceTask, + ) + + asset_category: DF.ReadOnly | None + asset_maintenance_tasks: DF.Table[AssetMaintenanceTask] + asset_name: DF.Link + company: DF.Link + item_code: DF.ReadOnly | None + item_name: DF.ReadOnly | None + maintenance_manager: DF.Data | None + maintenance_manager_name: DF.ReadOnly | None + maintenance_team: DF.Link + # end: auto-generated types + def validate(self): for task in self.get("asset_maintenance_tasks"): if task.end_date and (getdate(task.start_date) >= getdate(task.end_date)): diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py index ff791b2754..009bcc3e69 100644 --- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py @@ -11,6 +11,34 @@ from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate class AssetMaintenanceLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actions_performed: DF.TextEditor | None + amended_from: DF.Link | None + asset_maintenance: DF.Link | None + asset_name: DF.ReadOnly | None + assign_to_name: DF.ReadOnly | None + certificate_attachement: DF.Attach | None + completion_date: DF.Date | None + description: DF.ReadOnly | None + due_date: DF.Date | None + has_certificate: DF.Check + item_code: DF.ReadOnly | None + item_name: DF.ReadOnly | None + maintenance_status: DF.Literal["Planned", "Completed", "Cancelled", "Overdue"] + maintenance_type: DF.ReadOnly | None + naming_series: DF.Literal["ACC-AML-.YYYY.-"] + periodicity: DF.Data | None + task: DF.Link | None + task_name: DF.Data | None + # end: auto-generated types + def validate(self): if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in [ "Completed", diff --git a/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py index 1078208b2f..f3a21b59ca 100644 --- a/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py +++ b/erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.py @@ -6,4 +6,31 @@ from frappe.model.document import Document class AssetMaintenanceTask(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + assign_to: DF.Link | None + assign_to_name: DF.ReadOnly | None + certificate_required: DF.Check + description: DF.TextEditor | None + end_date: DF.Date | None + last_completion_date: DF.Date | None + maintenance_status: DF.Literal["Planned", "Overdue", "Cancelled"] + maintenance_task: DF.Data + maintenance_type: DF.Literal["Preventive Maintenance", "Calibration"] + next_due_date: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + periodicity: DF.Literal[ + "", "Daily", "Weekly", "Monthly", "Quarterly", "Half-yearly", "Yearly", "2 Yearly", "3 Yearly" + ] + start_date: DF.Date + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py index 938c99b4f6..b2219f0ae0 100644 --- a/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py +++ b/erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class AssetMaintenanceTeam(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.maintenance_team_member.maintenance_team_member import ( + MaintenanceTeamMember, + ) + + company: DF.Link + maintenance_manager: DF.Link | None + maintenance_manager_name: DF.ReadOnly | None + maintenance_team_members: DF.Table[MaintenanceTeamMember] + maintenance_team_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index 620aad80ed..0d8efcb8dd 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -11,6 +11,25 @@ from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activ class AssetMovement(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.asset_movement_item.asset_movement_item import AssetMovementItem + + amended_from: DF.Link | None + assets: DF.Table[AssetMovementItem] + company: DF.Link + purpose: DF.Literal["", "Issue", "Receipt", "Transfer"] + reference_doctype: DF.Link | None + reference_name: DF.DynamicLink | None + transaction_date: DF.Datetime + # end: auto-generated types + def validate(self): self.validate_asset() self.validate_location() diff --git a/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py b/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py index e25226d580..1a5302b9d8 100644 --- a/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py +++ b/erpnext/assets/doctype/asset_movement_item/asset_movement_item.py @@ -7,4 +7,24 @@ from frappe.model.document import Document class AssetMovementItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + asset: DF.Link + asset_name: DF.Data | None + company: DF.Link | None + from_employee: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + source_location: DF.Link | None + target_location: DF.Link | None + to_employee: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 9c2b8bc963..c0fb3c2923 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -17,6 +17,42 @@ from erpnext.controllers.accounts_controller import AccountsController class AssetRepair(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.asset_repair_consumed_item.asset_repair_consumed_item import ( + AssetRepairConsumedItem, + ) + + actions_performed: DF.LongText | None + amended_from: DF.Link | None + asset: DF.Link + asset_name: DF.ReadOnly | None + capitalize_repair_cost: DF.Check + company: DF.Link | None + completion_date: DF.Datetime | None + cost_center: DF.Link | None + description: DF.LongText | None + downtime: DF.Data | None + failure_date: DF.Datetime + increase_in_asset_life: DF.Int + naming_series: DF.Literal["ACC-ASR-.YYYY.-"] + project: DF.Link | None + purchase_invoice: DF.Link | None + repair_cost: DF.Currency + repair_status: DF.Literal["Pending", "Completed", "Cancelled"] + stock_consumption: DF.Check + stock_entry: DF.Link | None + stock_items: DF.Table[AssetRepairConsumedItem] + total_repair_cost: DF.Currency + warehouse: DF.Link | None + # end: auto-generated types + def validate(self): self.asset_doc = frappe.get_doc("Asset", self.asset) self.update_status() diff --git a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py index 2a8d64ef49..ab43cfe62a 100644 --- a/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py +++ b/erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class AssetRepairConsumedItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + consumed_quantity: DF.Data | None + item_code: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + total_value: DF.Currency + valuation_rate: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py index d419ef4c84..13915c7881 100644 --- a/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py +++ b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py @@ -22,6 +22,25 @@ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_sched class AssetShiftAllocation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.assets.doctype.depreciation_schedule.depreciation_schedule import ( + DepreciationSchedule, + ) + + amended_from: DF.Link | None + asset: DF.Link + depreciation_schedule: DF.Table[DepreciationSchedule] + finance_book: DF.Link | None + naming_series: DF.Literal["ACC-ASA-.YYYY.-"] + # end: auto-generated types + def after_insert(self): self.fetch_and_set_depr_schedule() diff --git a/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py index 4c275ce092..365a817ce1 100644 --- a/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py +++ b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py @@ -7,6 +7,19 @@ from frappe.model.document import Document class AssetShiftFactor(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + default: DF.Check + shift_factor: DF.Float + shift_name: DF.Data + # end: auto-generated types + def validate(self): self.validate_default() diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 9be7243602..769571c774 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -19,6 +19,27 @@ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_sched class AssetValueAdjustment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + asset: DF.Link + asset_category: DF.ReadOnly | None + company: DF.Link | None + cost_center: DF.Link | None + current_asset_value: DF.Currency + date: DF.Date + difference_amount: DF.Currency + finance_book: DF.Link | None + journal_entry: DF.Link | None + new_asset_value: DF.Currency + # end: auto-generated types + def validate(self): self.validate_date() self.set_current_asset_value() diff --git a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py index b597c58752..41aade6591 100644 --- a/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py +++ b/erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class DepreciationSchedule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + accumulated_depreciation_amount: DF.Currency + depreciation_amount: DF.Currency + journal_entry: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + schedule_date: DF.Date + shift: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/linked_location/linked_location.py b/erpnext/assets/doctype/linked_location/linked_location.py index e1257f3db1..35e6d8b41d 100644 --- a/erpnext/assets/doctype/linked_location/linked_location.py +++ b/erpnext/assets/doctype/linked_location/linked_location.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class LinkedLocation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + location: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/assets/doctype/location/location.py b/erpnext/assets/doctype/location/location.py index 5bff3dd8c9..01228f42fd 100644 --- a/erpnext/assets/doctype/location/location.py +++ b/erpnext/assets/doctype/location/location.py @@ -13,6 +13,27 @@ EARTH_RADIUS = 6378137 class Location(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + area: DF.Float + area_uom: DF.Link | None + is_container: DF.Check + is_group: DF.Check + latitude: DF.Float + lft: DF.Int + location_name: DF.Data + longitude: DF.Float + old_parent: DF.Data | None + parent_location: DF.Link | None + rgt: DF.Int + # end: auto-generated types + nsm_parent_field = "parent_location" def validate(self): diff --git a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py index c3ede94bc6..80a6a563b8 100644 --- a/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py +++ b/erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class MaintenanceTeamMember(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + full_name: DF.Data | None + maintenance_role: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + team_member: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py index 712caf1f91..2733d07a47 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.py @@ -10,6 +10,20 @@ from pypika import Order class BulkTransactionLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + date: DF.Date | None + failed: DF.Int + log_entries: DF.Int + succeeded: DF.Int + # end: auto-generated types + def db_insert(self, *args, **kwargs): pass diff --git a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.py b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.py index 67795b9d49..9b8e1700eb 100644 --- a/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.py +++ b/erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class BulkTransactionLogDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + date: DF.Date | None + error_description: DF.LongText | None + from_doctype: DF.Link | None + retried: DF.Int + time: DF.Time | None + to_doctype: DF.Link | None + transaction_name: DF.DynamicLink | None + transaction_status: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py index 4680a889d3..ec9b88888b 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.py +++ b/erpnext/buying/doctype/buying_settings/buying_settings.py @@ -9,6 +9,38 @@ from frappe.model.document import Document class BuyingSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_multiple_items: DF.Check + auto_create_purchase_receipt: DF.Check + auto_create_subcontracting_order: DF.Check + backflush_raw_materials_of_subcontract_based_on: DF.Literal[ + "BOM", "Material Transferred for Subcontract" + ] + bill_for_rejected_quantity_in_purchase_invoice: DF.Check + blanket_order_allowance: DF.Float + buying_price_list: DF.Link | None + disable_last_purchase_rate: DF.Check + maintain_same_rate: DF.Check + maintain_same_rate_action: DF.Literal["Stop", "Warn"] + over_transfer_allowance: DF.Float + po_required: DF.Literal["No", "Yes"] + pr_required: DF.Literal["No", "Yes"] + project_update_frequency: DF.Literal["Each Transaction", "Manual"] + role_to_override_stop_action: DF.Link | None + set_landed_cost_based_on_purchase_invoice_rate: DF.Check + show_pay_button: DF.Check + supp_master_name: DF.Literal["Supplier Name", "Naming Series", "Auto Name"] + supplier_group: DF.Link | None + use_transaction_date_exchange_rate: DF.Check + # end: auto-generated types + def validate(self): for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]: frappe.db.set_default(key, self.get(key, "")) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 4b121a806d..5f19657a05 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -36,6 +36,137 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class PurchaseOrder(BuyingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.purchase_taxes_and_charges.purchase_taxes_and_charges import ( + PurchaseTaxesandCharges, + ) + from erpnext.buying.doctype.purchase_order_item.purchase_order_item import PurchaseOrderItem + from erpnext.buying.doctype.purchase_order_item_supplied.purchase_order_item_supplied import ( + PurchaseOrderItemSupplied, + ) + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + advance_paid: DF.Currency + amended_from: DF.Link | None + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + apply_tds: DF.Check + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_tax_withholding_net_total: DF.Currency + base_taxes_and_charges_added: DF.Currency + base_taxes_and_charges_deducted: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + buying_price_list: DF.Link | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.SmallText | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + currency: DF.Link + customer: DF.Link | None + customer_contact_display: DF.SmallText | None + customer_contact_email: DF.Code | None + customer_contact_mobile: DF.SmallText | None + customer_contact_person: DF.Link | None + customer_name: DF.Data | None + disable_rounded_total: DF.Check + discount_amount: DF.Currency + from_date: DF.Date | None + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + inter_company_order_reference: DF.Link | None + is_internal_supplier: DF.Check + is_old_subcontracting_flow: DF.Check + is_subcontracted: DF.Check + items: DF.Table[PurchaseOrderItem] + language: DF.Data | None + letter_head: DF.Link | None + named_place: DF.Data | None + naming_series: DF.Literal["PUR-ORD-.YYYY.-"] + net_total: DF.Currency + order_confirmation_date: DF.Date | None + order_confirmation_no: DF.Data | None + other_charges_calculation: DF.LongText | None + party_account_currency: DF.Link | None + payment_schedule: DF.Table[PaymentSchedule] + payment_terms_template: DF.Link | None + per_billed: DF.Percent + per_received: DF.Percent + plc_conversion_rate: DF.Float + price_list_currency: DF.Link | None + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + ref_sq: DF.Link | None + represents_company: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + scan_barcode: DF.Data | None + schedule_date: DF.Date | None + select_print_heading: DF.Link | None + set_from_warehouse: DF.Link | None + set_reserve_warehouse: DF.Link | None + set_warehouse: DF.Link | None + shipping_address: DF.Link | None + shipping_address_display: DF.SmallText | None + shipping_rule: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "On Hold", + "To Receive and Bill", + "To Bill", + "To Receive", + "Completed", + "Cancelled", + "Closed", + "Delivered", + ] + supplied_items: DF.Table[PurchaseOrderItemSupplied] + supplier: DF.Link + supplier_address: DF.Link | None + supplier_name: DF.Data | None + supplier_warehouse: DF.Link | None + tax_category: DF.Link | None + tax_withholding_category: DF.Link | None + tax_withholding_net_total: DF.Currency + taxes: DF.Table[PurchaseTaxesandCharges] + taxes_and_charges: DF.Link | None + taxes_and_charges_added: DF.Currency + taxes_and_charges_deducted: DF.Currency + tc_name: DF.Link | None + terms: DF.TextEditor | None + title: DF.Data + to_date: DF.Date | None + total: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + transaction_date: DF.Date + # end: auto-generated types + def __init__(self, *args, **kwargs): super(PurchaseOrder, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py index a8bafda002..e9cc2b4eec 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py @@ -7,6 +7,93 @@ from frappe.model.document import Document class PurchaseOrderItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + against_blanket_order: DF.Check + amount: DF.Currency + apply_tds: DF.Check + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + billed_amt: DF.Currency + blanket_order: DF.Link | None + blanket_order_rate: DF.Currency + bom: DF.Link | None + brand: DF.Link | None + company_total_stock: DF.Float + conversion_factor: DF.Float + cost_center: DF.Link | None + delivered_by_supplier: DF.Check + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + expected_delivery_date: DF.Date | None + expense_account: DF.Link | None + fg_item: DF.Link | None + fg_item_qty: DF.Float + from_warehouse: DF.Link | None + image: DF.Attach | None + include_exploded_items: DF.Check + is_fixed_asset: DF.Check + is_free_item: DF.Check + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data + item_tax_rate: DF.Code | None + item_tax_template: DF.Link | None + last_purchase_rate: DF.Currency + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + material_request: DF.Link | None + material_request_item: DF.Data | None + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + product_bundle: DF.Link | None + production_plan: DF.Link | None + production_plan_item: DF.Data | None + production_plan_sub_assembly_item: DF.Data | None + project: DF.Link | None + qty: DF.Float + rate: DF.Currency + rate_with_margin: DF.Currency + received_qty: DF.Float + returned_qty: DF.Float + sales_order: DF.Link | None + sales_order_item: DF.Data | None + sales_order_packed_item: DF.Data | None + schedule_date: DF.Date + stock_qty: DF.Float + stock_uom: DF.Link + stock_uom_rate: DF.Currency + supplier_part_no: DF.Data | None + supplier_quotation: DF.Link | None + supplier_quotation_item: DF.Link | None + total_weight: DF.Float + uom: DF.Link + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + wip_composite_asset: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py index c69b5ed7a4..6844347dd1 100644 --- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py +++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.py @@ -6,4 +6,31 @@ from frappe.model.document import Document class PurchaseOrderItemSupplied(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + bom_detail_no: DF.Data | None + consumed_qty: DF.Float + conversion_factor: DF.Float + main_item_code: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Currency + reference_name: DF.Data | None + required_qty: DF.Float + reserve_warehouse: DF.Link | None + returned_qty: DF.Float + rm_item_code: DF.Link | None + stock_uom: DF.Link | None + supplied_qty: DF.Float + total_supplied_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py index 7b67921232..6ed097100f 100644 --- a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py +++ b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.py @@ -6,4 +6,33 @@ from frappe.model.document import Document class PurchaseReceiptItemSupplied(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + batch_no: DF.Link | None + bom_detail_no: DF.Data | None + consumed_qty: DF.Float + conversion_factor: DF.Float + current_stock: DF.Float + description: DF.TextEditor | None + item_name: DF.Data | None + main_item_code: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + purchase_order: DF.Link | None + rate: DF.Currency + reference_name: DF.Data | None + required_qty: DF.Float + rm_item_code: DF.Link | None + serial_no: DF.Text | None + stock_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 6b39982bb8..eea8cd5cc8 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -23,6 +23,45 @@ STANDARD_USERS = ("Guest", "Administrator") class RequestforQuotation(BuyingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.buying.doctype.request_for_quotation_item.request_for_quotation_item import ( + RequestforQuotationItem, + ) + from erpnext.buying.doctype.request_for_quotation_supplier.request_for_quotation_supplier import ( + RequestforQuotationSupplier, + ) + + amended_from: DF.Link | None + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + company: DF.Link + email_template: DF.Link | None + incoterm: DF.Link | None + items: DF.Table[RequestforQuotationItem] + letter_head: DF.Link | None + message_for_supplier: DF.TextEditor + named_place: DF.Data | None + naming_series: DF.Literal["PUR-RFQ-.YYYY.-"] + opportunity: DF.Link | None + schedule_date: DF.Date | None + select_print_heading: DF.Link | None + send_attached_files: DF.Check + send_document_print: DF.Check + status: DF.Literal["", "Draft", "Submitted", "Cancelled"] + suppliers: DF.Table[RequestforQuotationSupplier] + tc_name: DF.Link | None + terms: DF.TextEditor | None + transaction_date: DF.Date + vendor: DF.Link | None + # end: auto-generated types + def validate(self): self.validate_duplicate_supplier() self.validate_supplier_list() diff --git a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py index 096aedee32..2ea7730721 100644 --- a/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py +++ b/erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.py @@ -6,4 +6,35 @@ from frappe.model.document import Document class RequestforQuotationItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + brand: DF.Link | None + conversion_factor: DF.Float + description: DF.TextEditor | None + image: DF.Attach | None + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + material_request: DF.Link | None + material_request_item: DF.Data | None + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project_name: DF.Link | None + qty: DF.Float + schedule_date: DF.Date + stock_qty: DF.Float + stock_uom: DF.Link + supplier_part_no: DF.Data | None + uom: DF.Link + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py index dbaad478a3..47aa5eee93 100644 --- a/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py +++ b/erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.py @@ -6,4 +6,24 @@ from frappe.model.document import Document class RequestforQuotationSupplier(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + contact: DF.Link | None + email_id: DF.Data | None + email_sent: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + quote_status: DF.Literal["Pending", "Received"] + send_email: DF.Check + supplier: DF.Link + supplier_name: DF.ReadOnly | None + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index b052f564a4..c8ed5aa4a8 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -21,6 +21,60 @@ from erpnext.utilities.transaction_base import TransactionBase class Supplier(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.allowed_to_transact_with.allowed_to_transact_with import ( + AllowedToTransactWith, + ) + from erpnext.accounts.doctype.party_account.party_account import PartyAccount + from erpnext.utilities.doctype.portal_user.portal_user import PortalUser + + accounts: DF.Table[PartyAccount] + allow_purchase_invoice_creation_without_purchase_order: DF.Check + allow_purchase_invoice_creation_without_purchase_receipt: DF.Check + companies: DF.Table[AllowedToTransactWith] + country: DF.Link | None + default_bank_account: DF.Link | None + default_currency: DF.Link | None + default_price_list: DF.Link | None + disabled: DF.Check + email_id: DF.ReadOnly | None + hold_type: DF.Literal["", "All", "Invoices", "Payments"] + image: DF.AttachImage | None + is_frozen: DF.Check + is_internal_supplier: DF.Check + is_transporter: DF.Check + language: DF.Link | None + mobile_no: DF.ReadOnly | None + naming_series: DF.Literal["SUP-.YYYY.-"] + on_hold: DF.Check + payment_terms: DF.Link | None + portal_users: DF.Table[PortalUser] + prevent_pos: DF.Check + prevent_rfqs: DF.Check + primary_address: DF.Text | None + release_date: DF.Date | None + represents_company: DF.Link | None + supplier_details: DF.Text | None + supplier_group: DF.Link | None + supplier_name: DF.Data + supplier_primary_address: DF.Link | None + supplier_primary_contact: DF.Link | None + supplier_type: DF.Literal["Company", "Individual", "Proprietorship", "Partnership"] + tax_category: DF.Link | None + tax_id: DF.Data | None + tax_withholding_category: DF.Link | None + warn_pos: DF.Check + warn_rfqs: DF.Check + website: DF.Data | None + # end: auto-generated types + def onload(self): """Load address and contacts in `__onload`""" load_address_and_contact(self) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 2dd748bc19..bb0c2691dc 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -14,6 +14,95 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class SupplierQuotation(BuyingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.purchase_taxes_and_charges.purchase_taxes_and_charges import ( + PurchaseTaxesandCharges, + ) + from erpnext.buying.doctype.supplier_quotation_item.supplier_quotation_item import ( + SupplierQuotationItem, + ) + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + amended_from: DF.Link | None + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_taxes_and_charges_added: DF.Currency + base_taxes_and_charges_deducted: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + buying_price_list: DF.Link | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + currency: DF.Link + disable_rounded_total: DF.Check + discount_amount: DF.Currency + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + is_subcontracted: DF.Check + items: DF.Table[SupplierQuotationItem] + language: DF.Data | None + letter_head: DF.Link | None + named_place: DF.Data | None + naming_series: DF.Literal["PUR-SQTN-.YYYY.-"] + net_total: DF.Currency + opportunity: DF.Link | None + other_charges_calculation: DF.LongText | None + plc_conversion_rate: DF.Float + price_list_currency: DF.Link | None + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + quotation_number: DF.Data | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + select_print_heading: DF.Link | None + shipping_address: DF.Link | None + shipping_address_display: DF.SmallText | None + shipping_rule: DF.Link | None + status: DF.Literal["", "Draft", "Submitted", "Stopped", "Cancelled", "Expired"] + supplier: DF.Link + supplier_address: DF.Link | None + supplier_name: DF.Data | None + tax_category: DF.Link | None + taxes: DF.Table[PurchaseTaxesandCharges] + taxes_and_charges: DF.Link | None + taxes_and_charges_added: DF.Currency + taxes_and_charges_deducted: DF.Currency + tc_name: DF.Link | None + terms: DF.TextEditor | None + title: DF.Data | None + total: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + transaction_date: DF.Date + valid_till: DF.Date | None + # end: auto-generated types + def validate(self): super(SupplierQuotation, self).validate() diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py index 672de1ac28..d2f4a59930 100644 --- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py @@ -6,4 +6,62 @@ from frappe.model.document import Document class SupplierQuotationItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + brand: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + expected_delivery_date: DF.Date | None + image: DF.Attach | None + is_free_item: DF.Check + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + item_tax_rate: DF.Code | None + item_tax_template: DF.Link | None + lead_time_days: DF.Int + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + material_request: DF.Link | None + material_request_item: DF.Data | None + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + prevdoc_doctype: DF.Data | None + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + project: DF.Link | None + qty: DF.Float + rate: DF.Currency + request_for_quotation: DF.Link | None + request_for_quotation_item: DF.Data | None + sales_order: DF.Link | None + stock_qty: DF.Float + stock_uom: DF.Link + supplier_part_no: DF.Data | None + total_weight: DF.Float + uom: DF.Link + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py index 683a12ac95..0a6024fd84 100644 --- a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py +++ b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py @@ -16,6 +16,38 @@ from erpnext.buying.doctype.supplier_scorecard_period.supplier_scorecard_period class SupplierScorecard(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.buying.doctype.supplier_scorecard_scoring_criteria.supplier_scorecard_scoring_criteria import ( + SupplierScorecardScoringCriteria, + ) + from erpnext.buying.doctype.supplier_scorecard_scoring_standing.supplier_scorecard_scoring_standing import ( + SupplierScorecardScoringStanding, + ) + + criteria: DF.Table[SupplierScorecardScoringCriteria] + employee: DF.Link | None + indicator_color: DF.Data | None + notify_employee: DF.Check + notify_supplier: DF.Check + period: DF.Literal["Per Week", "Per Month", "Per Year"] + prevent_pos: DF.Check + prevent_rfqs: DF.Check + standings: DF.Table[SupplierScorecardScoringStanding] + status: DF.Data | None + supplier: DF.Link | None + supplier_score: DF.Data | None + warn_pos: DF.Check + warn_rfqs: DF.Check + weighting_function: DF.SmallText + # end: auto-generated types + def validate(self): self.validate_standings() self.validate_criteria_weights() diff --git a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py index ab7d4879c4..f19ab94a99 100644 --- a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py @@ -14,6 +14,20 @@ class InvalidFormulaVariable(frappe.ValidationError): class SupplierScorecardCriteria(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + criteria_name: DF.Data + formula: DF.SmallText + max_score: DF.Float + weight: DF.Percent + # end: auto-generated types + def validate(self): self.validate_variables() self.validate_formula() diff --git a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py index 1967df2a26..e6ef166a5b 100644 --- a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py +++ b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py @@ -14,6 +14,32 @@ from erpnext.buying.doctype.supplier_scorecard_criteria.supplier_scorecard_crite class SupplierScorecardPeriod(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.buying.doctype.supplier_scorecard_scoring_criteria.supplier_scorecard_scoring_criteria import ( + SupplierScorecardScoringCriteria, + ) + from erpnext.buying.doctype.supplier_scorecard_scoring_variable.supplier_scorecard_scoring_variable import ( + SupplierScorecardScoringVariable, + ) + + amended_from: DF.Link | None + criteria: DF.Table[SupplierScorecardScoringCriteria] + end_date: DF.Date + naming_series: DF.Literal["PU-SSP-.YYYY.-"] + scorecard: DF.Link + start_date: DF.Date + supplier: DF.Link + total_score: DF.Percent + variables: DF.Table[SupplierScorecardScoringVariable] + # end: auto-generated types + def validate(self): self.validate_criteria_weights() self.calculate_variables() diff --git a/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py b/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py index 3a6de59f34..4c77742723 100644 --- a/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class SupplierScorecardScoringCriteria(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + criteria_name: DF.Link + formula: DF.SmallText | None + max_score: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + score: DF.Percent + weight: DF.Percent + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py b/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py index 8d66e6414b..35e4177b98 100644 --- a/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py +++ b/erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.py @@ -6,4 +6,28 @@ from frappe.model.document import Document class SupplierScorecardScoringStanding(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + employee_link: DF.Link | None + max_grade: DF.Percent + min_grade: DF.Percent + notify_employee: DF.Check + notify_supplier: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + prevent_pos: DF.Check + prevent_rfqs: DF.Check + standing_color: DF.Literal["Blue", "Purple", "Green", "Yellow", "Orange", "Red"] + standing_name: DF.Link | None + warn_pos: DF.Check + warn_rfqs: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py b/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py index f13eb5b420..41b474899e 100644 --- a/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py +++ b/erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class SupplierScorecardScoringVariable(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + param_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + path: DF.Data | None + value: DF.Float + variable_label: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py b/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py index 929e8a363f..690838a28a 100644 --- a/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py +++ b/erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.py @@ -7,6 +7,27 @@ from frappe.model.document import Document class SupplierScorecardStanding(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + employee_link: DF.Link | None + max_grade: DF.Percent + min_grade: DF.Percent + notify_employee: DF.Check + notify_supplier: DF.Check + prevent_pos: DF.Check + prevent_rfqs: DF.Check + standing_color: DF.Literal["Blue", "Purple", "Green", "Yellow", "Orange", "Red"] + standing_name: DF.Data | None + warn_pos: DF.Check + warn_rfqs: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py b/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py index 6c91a049db..19be89d547 100644 --- a/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py +++ b/erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py @@ -16,6 +16,21 @@ class VariablePathNotFound(frappe.ValidationError): class SupplierScorecardVariable(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + is_custom: DF.Check + param_name: DF.Data + path: DF.Data + variable_label: DF.Data + # end: auto-generated types + def validate(self): self.validate_path_exists() diff --git a/erpnext/communication/doctype/communication_medium/communication_medium.py b/erpnext/communication/doctype/communication_medium/communication_medium.py index 6dfdb73b85..a5b30834f1 100644 --- a/erpnext/communication/doctype/communication_medium/communication_medium.py +++ b/erpnext/communication/doctype/communication_medium/communication_medium.py @@ -7,4 +7,24 @@ from frappe.model.document import Document class CommunicationMedium(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.communication.doctype.communication_medium_timeslot.communication_medium_timeslot import ( + CommunicationMediumTimeslot, + ) + + catch_all: DF.Link | None + communication_channel: DF.Literal + communication_medium_type: DF.Literal["Voice", "Email", "Chat"] + disabled: DF.Check + provider: DF.Link | None + timeslots: DF.Table[CommunicationMediumTimeslot] + # end: auto-generated types + pass diff --git a/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py b/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py index b65eba75ed..4cd65fae67 100644 --- a/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py +++ b/erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.py @@ -7,4 +7,23 @@ from frappe.model.document import Document class CommunicationMediumTimeslot(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + day_of_week: DF.Literal[ + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + ] + employee_group: DF.Link + from_time: DF.Time + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + to_time: DF.Time + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index bd49bdc925..7be6fdcc13 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -14,6 +14,26 @@ from frappe.utils.verified_command import get_signed_params class Appointment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + appointment_with: DF.Link | None + calendar_event: DF.Link | None + customer_details: DF.LongText | None + customer_email: DF.Data + customer_name: DF.Data + customer_phone_number: DF.Data | None + customer_skype: DF.Data | None + party: DF.DynamicLink | None + scheduled_time: DF.Datetime + status: DF.Literal["Open", "Unverified", "Closed"] + # end: auto-generated types + def find_lead_by_email(self): lead_list = frappe.get_list( "Lead", filters={"email_id": self.customer_email}, ignore_permissions=True diff --git a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py index e43f4601e9..77e8727ea5 100644 --- a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py +++ b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py @@ -10,6 +10,32 @@ from frappe.model.document import Document class AppointmentBookingSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.automation.doctype.assignment_rule_user.assignment_rule_user import ( + AssignmentRuleUser, + ) + from frappe.types import DF + + from erpnext.crm.doctype.appointment_booking_slots.appointment_booking_slots import ( + AppointmentBookingSlots, + ) + + advance_booking_days: DF.Int + agent_list: DF.TableMultiSelect[AssignmentRuleUser] + appointment_duration: DF.Int + availability_of_slots: DF.Table[AppointmentBookingSlots] + email_reminders: DF.Check + enable_scheduling: DF.Check + holiday_list: DF.Link + number_of_agents: DF.Int + success_redirect_url: DF.Data | None + # end: auto-generated types + agent_list = [] # Hack min_date = "01/01/1970 " format_string = "%d/%m/%Y %H:%M:%S" diff --git a/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py b/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py index 756c8495e0..ee936ddf3f 100644 --- a/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py +++ b/erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class AppointmentBookingSlots(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + day_of_week: DF.Literal[ + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ] + from_time: DF.Time + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + to_time: DF.Time + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py b/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py index 4294e6da2d..67b6fdece8 100644 --- a/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py +++ b/erpnext/crm/doctype/availability_of_slots/availability_of_slots.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class AvailabilityOfSlots(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + day_of_week: DF.Literal[ + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ] + from_time: DF.Time + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + to_time: DF.Time + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/campaign/campaign.py b/erpnext/crm/doctype/campaign/campaign.py index 5d06075bdf..5e14b0e758 100644 --- a/erpnext/crm/doctype/campaign/campaign.py +++ b/erpnext/crm/doctype/campaign/campaign.py @@ -7,6 +7,24 @@ from frappe.model.naming import set_name_by_naming_series class Campaign(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.crm.doctype.campaign_email_schedule.campaign_email_schedule import ( + CampaignEmailSchedule, + ) + + campaign_name: DF.Data + campaign_schedules: DF.Table[CampaignEmailSchedule] + description: DF.Text | None + naming_series: DF.Literal["SAL-CAM-.YYYY.-"] + # end: auto-generated types + def autoname(self): if frappe.defaults.get_global_default("campaign_naming_by") != "Naming Series": self.name = self.campaign_name diff --git a/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py b/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py index de9b5a1192..fdafab235a 100644 --- a/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py +++ b/erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class CampaignEmailSchedule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + email_template: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + send_after_days: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/competitor/competitor.py b/erpnext/crm/doctype/competitor/competitor.py index a292e46104..fdd8cbaa43 100644 --- a/erpnext/crm/doctype/competitor/competitor.py +++ b/erpnext/crm/doctype/competitor/competitor.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class Competitor(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + competitor_name: DF.Data + website: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/competitor_detail/competitor_detail.py b/erpnext/crm/doctype/competitor_detail/competitor_detail.py index 0ef75605b7..6c7984fdc1 100644 --- a/erpnext/crm/doctype/competitor_detail/competitor_detail.py +++ b/erpnext/crm/doctype/competitor_detail/competitor_detail.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class CompetitorDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + competitor: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/contract/contract.py b/erpnext/crm/doctype/contract/contract.py index 1c2470b6e4..6f9dcde05d 100644 --- a/erpnext/crm/doctype/contract/contract.py +++ b/erpnext/crm/doctype/contract/contract.py @@ -9,6 +9,42 @@ from frappe.utils import getdate, nowdate class Contract(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.crm.doctype.contract_fulfilment_checklist.contract_fulfilment_checklist import ( + ContractFulfilmentChecklist, + ) + + amended_from: DF.Link | None + contract_template: DF.Link | None + contract_terms: DF.TextEditor + document_name: DF.DynamicLink | None + document_type: DF.Literal[ + "", "Quotation", "Project", "Sales Order", "Purchase Order", "Sales Invoice", "Purchase Invoice" + ] + end_date: DF.Date | None + fulfilment_deadline: DF.Date | None + fulfilment_status: DF.Literal["N/A", "Unfulfilled", "Partially Fulfilled", "Fulfilled", "Lapsed"] + fulfilment_terms: DF.Table[ContractFulfilmentChecklist] + ip_address: DF.Data | None + is_signed: DF.Check + party_name: DF.DynamicLink + party_type: DF.Literal["Customer", "Supplier", "Employee"] + party_user: DF.Link | None + requires_fulfilment: DF.Check + signed_by_company: DF.Link | None + signed_on: DF.Datetime | None + signee: DF.Data | None + start_date: DF.Date | None + status: DF.Literal["Unsigned", "Active", "Inactive"] + # end: auto-generated types + def autoname(self): name = self.party_name diff --git a/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py b/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py index 4e4e9986d6..43984c3052 100644 --- a/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py +++ b/erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class ContractFulfilmentChecklist(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + fulfilled: DF.Check + notes: DF.Text | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + requirement: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/contract_template/contract_template.py b/erpnext/crm/doctype/contract_template/contract_template.py index a5b0ee08f0..700197500f 100644 --- a/erpnext/crm/doctype/contract_template/contract_template.py +++ b/erpnext/crm/doctype/contract_template/contract_template.py @@ -10,6 +10,24 @@ from frappe.utils.jinja import validate_template class ContractTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.crm.doctype.contract_template_fulfilment_terms.contract_template_fulfilment_terms import ( + ContractTemplateFulfilmentTerms, + ) + + contract_terms: DF.TextEditor | None + fulfilment_terms: DF.Table[ContractTemplateFulfilmentTerms] + requires_fulfilment: DF.Check + title: DF.Data | None + # end: auto-generated types + def validate(self): if self.contract_terms: validate_template(self.contract_terms) diff --git a/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py b/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py index 18600d9918..597940b043 100644 --- a/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py +++ b/erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class ContractTemplateFulfilmentTerms(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + requirement: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/crm_note/crm_note.py b/erpnext/crm/doctype/crm_note/crm_note.py index 6c7eeb4c7e..531978c584 100644 --- a/erpnext/crm/doctype/crm_note/crm_note.py +++ b/erpnext/crm/doctype/crm_note/crm_note.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class CRMNote(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + added_by: DF.Link | None + added_on: DF.Datetime | None + name: DF.Int | None + note: DF.TextEditor | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/crm_settings/crm_settings.py b/erpnext/crm/doctype/crm_settings/crm_settings.py index 98cf7d845e..499a6d723d 100644 --- a/erpnext/crm/doctype/crm_settings/crm_settings.py +++ b/erpnext/crm/doctype/crm_settings/crm_settings.py @@ -6,5 +6,21 @@ from frappe.model.document import Document class CRMSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_lead_duplication_based_on_emails: DF.Check + auto_creation_of_contact: DF.Check + campaign_naming_by: DF.Literal["Campaign Name", "Naming Series"] + carry_forward_communication_and_comments: DF.Check + close_opportunity_after_days: DF.Int + default_valid_till: DF.Data | None + # end: auto-generated types + def validate(self): frappe.db.set_default("campaign_naming_by", self.get("campaign_naming_by", "")) diff --git a/erpnext/crm/doctype/email_campaign/email_campaign.py b/erpnext/crm/doctype/email_campaign/email_campaign.py index 9ec54ffc1e..17cf0e461d 100644 --- a/erpnext/crm/doctype/email_campaign/email_campaign.py +++ b/erpnext/crm/doctype/email_campaign/email_campaign.py @@ -10,6 +10,23 @@ from frappe.utils import add_days, getdate, today class EmailCampaign(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + campaign_name: DF.Link + email_campaign_for: DF.Literal["", "Lead", "Contact", "Email Group"] + end_date: DF.Date | None + recipient: DF.DynamicLink + sender: DF.Link | None + start_date: DF.Date + status: DF.Literal["", "Scheduled", "In Progress", "Completed", "Unsubscribed"] + # end: auto-generated types + def validate(self): self.set_date() # checking if email is set for lead. Not checking for contact as email is a mandatory field for contact. diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index d22cc5548a..f0fc1aa590 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -19,6 +19,72 @@ from erpnext.crm.utils import CRMNote, copy_comments, link_communications, link_ class Lead(SellingController, CRMNote): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.crm.doctype.crm_note.crm_note import CRMNote + + annual_revenue: DF.Currency + blog_subscriber: DF.Check + campaign_name: DF.Link | None + city: DF.Data | None + company: DF.Link | None + company_name: DF.Data | None + country: DF.Link | None + customer: DF.Link | None + disabled: DF.Check + email_id: DF.Data | None + fax: DF.Data | None + first_name: DF.Data | None + gender: DF.Link | None + image: DF.AttachImage | None + industry: DF.Link | None + job_title: DF.Data | None + language: DF.Link | None + last_name: DF.Data | None + lead_name: DF.Data | None + lead_owner: DF.Link | None + market_segment: DF.Link | None + middle_name: DF.Data | None + mobile_no: DF.Data | None + naming_series: DF.Literal["CRM-LEAD-.YYYY.-"] + no_of_employees: DF.Literal["1-10", "11-50", "51-200", "201-500", "501-1000", "1000+"] + notes: DF.Table[CRMNote] + phone: DF.Data | None + phone_ext: DF.Data | None + qualification_status: DF.Literal["Unqualified", "In Process", "Qualified"] + qualified_by: DF.Link | None + qualified_on: DF.Date | None + request_type: DF.Literal[ + "", "Product Enquiry", "Request for Information", "Suggestions", "Other" + ] + salutation: DF.Link | None + source: DF.Link | None + state: DF.Data | None + status: DF.Literal[ + "Lead", + "Open", + "Replied", + "Opportunity", + "Quotation", + "Lost Quotation", + "Interested", + "Converted", + "Do Not Contact", + ] + territory: DF.Link | None + title: DF.Data | None + type: DF.Literal["", "Client", "Channel Partner", "Consultant"] + unsubscribed: DF.Check + website: DF.Data | None + whatsapp_no: DF.Data | None + # end: auto-generated types + def onload(self): customer = frappe.db.get_value("Customer", {"lead_name": self.name}) self.get("__onload").is_customer = customer diff --git a/erpnext/crm/doctype/lead_source/lead_source.py b/erpnext/crm/doctype/lead_source/lead_source.py index d9e0028651..b426a329fa 100644 --- a/erpnext/crm/doctype/lead_source/lead_source.py +++ b/erpnext/crm/doctype/lead_source/lead_source.py @@ -7,4 +7,16 @@ from frappe.model.document import Document class LeadSource(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + details: DF.TextEditor | None + source_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py b/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py index 51e4d5c506..e7115096af 100644 --- a/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py +++ b/erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class LostReasonDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + lost_reason: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/market_segment/market_segment.py b/erpnext/crm/doctype/market_segment/market_segment.py index 766be85704..1631802b00 100644 --- a/erpnext/crm/doctype/market_segment/market_segment.py +++ b/erpnext/crm/doctype/market_segment/market_segment.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class MarketSegment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + market_segment: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 2a8d65f486..72e26de70e 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -25,6 +25,72 @@ from erpnext.utilities.transaction_base import TransactionBase class Opportunity(TransactionBase, CRMNote): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.crm.doctype.competitor_detail.competitor_detail import CompetitorDetail + from erpnext.crm.doctype.crm_note.crm_note import CRMNote + from erpnext.crm.doctype.opportunity_item.opportunity_item import OpportunityItem + from erpnext.crm.doctype.opportunity_lost_reason_detail.opportunity_lost_reason_detail import ( + OpportunityLostReasonDetail, + ) + + address_display: DF.SmallText | None + amended_from: DF.Link | None + annual_revenue: DF.Currency + base_opportunity_amount: DF.Currency + base_total: DF.Currency + campaign: DF.Link | None + city: DF.Data | None + company: DF.Link + competitors: DF.TableMultiSelect[CompetitorDetail] + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.Data | None + contact_person: DF.Link | None + conversion_rate: DF.Float + country: DF.Link | None + currency: DF.Link | None + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + expected_closing: DF.Date | None + first_response_time: DF.Duration | None + industry: DF.Link | None + items: DF.Table[OpportunityItem] + job_title: DF.Data | None + language: DF.Link | None + lost_reasons: DF.TableMultiSelect[OpportunityLostReasonDetail] + market_segment: DF.Link | None + naming_series: DF.Literal["CRM-OPP-.YYYY.-"] + no_of_employees: DF.Literal["1-10", "11-50", "51-200", "201-500", "501-1000", "1000+"] + notes: DF.Table[CRMNote] + opportunity_amount: DF.Currency + opportunity_from: DF.Link + opportunity_owner: DF.Link | None + opportunity_type: DF.Link | None + order_lost_reason: DF.SmallText | None + party_name: DF.DynamicLink + phone: DF.Data | None + phone_ext: DF.Data | None + probability: DF.Percent + sales_stage: DF.Link | None + source: DF.Link | None + state: DF.Data | None + status: DF.Literal["Open", "Quotation", "Converted", "Lost", "Replied", "Closed"] + territory: DF.Link | None + title: DF.Data | None + total: DF.Currency + transaction_date: DF.Date + website: DF.Data | None + whatsapp: DF.Data | None + # end: auto-generated types + def onload(self): ref_doc = frappe.get_doc(self.opportunity_from, self.party_name) load_address_and_contact(ref_doc) diff --git a/erpnext/crm/doctype/opportunity_item/opportunity_item.py b/erpnext/crm/doctype/opportunity_item/opportunity_item.py index 4d285870ce..b3b963eebf 100644 --- a/erpnext/crm/doctype/opportunity_item/opportunity_item.py +++ b/erpnext/crm/doctype/opportunity_item/opportunity_item.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class OpportunityItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + base_amount: DF.Currency + base_rate: DF.Currency + brand: DF.Link | None + description: DF.TextEditor | None + image: DF.Attach | None + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + rate: DF.Currency + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py b/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py index 84a9a52b5b..71f57aefcc 100644 --- a/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py +++ b/erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class OpportunityLostReason(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + lost_reason: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py index d5721850d0..7c434d3513 100644 --- a/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py +++ b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class OpportunityLostReasonDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + lost_reason: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/opportunity_type/opportunity_type.py b/erpnext/crm/doctype/opportunity_type/opportunity_type.py index 1bb31ec859..f944b5c16a 100644 --- a/erpnext/crm/doctype/opportunity_type/opportunity_type.py +++ b/erpnext/crm/doctype/opportunity_type/opportunity_type.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class OpportunityType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/prospect/prospect.py b/erpnext/crm/doctype/prospect/prospect.py index 8b66a83f2a..7ecbe637f0 100644 --- a/erpnext/crm/doctype/prospect/prospect.py +++ b/erpnext/crm/doctype/prospect/prospect.py @@ -12,6 +12,34 @@ from erpnext.crm.utils import CRMNote, copy_comments, link_communications, link_ class Prospect(CRMNote): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.crm.doctype.crm_note.crm_note import CRMNote + from erpnext.crm.doctype.prospect_lead.prospect_lead import ProspectLead + from erpnext.crm.doctype.prospect_opportunity.prospect_opportunity import ProspectOpportunity + + annual_revenue: DF.Currency + company: DF.Link + company_name: DF.Data | None + customer_group: DF.Link | None + fax: DF.Data | None + industry: DF.Link | None + leads: DF.Table[ProspectLead] + market_segment: DF.Link | None + no_of_employees: DF.Literal["1-10", "11-50", "51-200", "201-500", "501-1000", "1000+"] + notes: DF.Table[CRMNote] + opportunities: DF.Table[ProspectOpportunity] + prospect_owner: DF.Link | None + territory: DF.Link | None + website: DF.Data | None + # end: auto-generated types + def onload(self): load_address_and_contact(self) diff --git a/erpnext/crm/doctype/prospect_lead/prospect_lead.py b/erpnext/crm/doctype/prospect_lead/prospect_lead.py index 40edbe0524..f80c51e842 100644 --- a/erpnext/crm/doctype/prospect_lead/prospect_lead.py +++ b/erpnext/crm/doctype/prospect_lead/prospect_lead.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class ProspectLead(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + email: DF.Data | None + lead: DF.Link + lead_name: DF.Data | None + lead_owner: DF.Data | None + mobile_no: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + status: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py b/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py index 8f5d19aaf2..a5f25a9aac 100644 --- a/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py +++ b/erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.py @@ -6,4 +6,26 @@ from frappe.model.document import Document class ProspectOpportunity(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + contact_person: DF.Link | None + currency: DF.Link | None + deal_owner: DF.Data | None + expected_closing: DF.Date | None + name: DF.Int | None + opportunity: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + probability: DF.Percent + stage: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/crm/doctype/sales_stage/sales_stage.py b/erpnext/crm/doctype/sales_stage/sales_stage.py index d2099edd05..aeb4ddbe59 100644 --- a/erpnext/crm/doctype/sales_stage/sales_stage.py +++ b/erpnext/crm/doctype/sales_stage/sales_stage.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class SalesStage(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + stage_name: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index eb99345991..ec7d71e997 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -15,6 +15,22 @@ from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import class PlaidSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + automatic_sync: DF.Check + enable_european_access: DF.Check + enabled: DF.Check + plaid_client_id: DF.Data | None + plaid_env: DF.Literal["sandbox", "development", "production"] + plaid_secret: DF.Password | None + # end: auto-generated types + @staticmethod @frappe.whitelist() def get_link_token(): diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py index da5699776f..ec7a6e98f9 100644 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py +++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py @@ -34,6 +34,36 @@ def callback(*args, **kwargs): class QuickBooksMigrator(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + access_token: DF.SmallText | None + api_endpoint: DF.Data + authorization_endpoint: DF.Data + authorization_url: DF.Data + client_id: DF.Data + client_secret: DF.Data + code: DF.Data | None + company: DF.Link | None + default_cost_center: DF.Link | None + default_shipping_account: DF.Link | None + default_warehouse: DF.Link | None + quickbooks_company_id: DF.Data | None + redirect_url: DF.Data + refresh_token: DF.SmallText | None + scope: DF.Data + status: DF.Literal[ + "Connecting to QuickBooks", "Connected to QuickBooks", "In Progress", "Complete", "Failed" + ] + token_endpoint: DF.Data + undeposited_funds_account: DF.Link | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(QuickBooksMigrator, self).__init__(*args, **kwargs) self.oauth = OAuth2Session( diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py index e6840f505b..8ebca549a0 100644 --- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py +++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py @@ -40,6 +40,39 @@ def new_doc(document): class TallyMigration(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + addresses: DF.Attach | None + chart_of_accounts: DF.Attach | None + day_book_data: DF.Attach | None + default_cost_center: DF.Link | None + default_round_off_account: DF.Link | None + default_uom: DF.Link | None + default_warehouse: DF.Link | None + erpnext_company: DF.Data | None + failed_import_log: DF.Code | None + fixed_errors_log: DF.Code | None + is_day_book_data_imported: DF.Check + is_day_book_data_processed: DF.Check + is_master_data_imported: DF.Check + is_master_data_processed: DF.Check + items: DF.Attach | None + master_data: DF.Attach | None + parties: DF.Attach | None + status: DF.Data | None + tally_company: DF.Data | None + tally_creditors_account: DF.Data + tally_debtors_account: DF.Data + uoms: DF.Attach | None + vouchers: DF.Attach | None + # end: auto-generated types + def validate(self): failed_import_log = json.loads(self.failed_import_log) sorted_failed_import_log = sorted(failed_import_log, key=lambda row: row["doc"]["creation"]) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 60ec49587c..17ad155031 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -643,3 +643,5 @@ extend_bootinfo = [ default_log_clearing_doctypes = { "Repost Item Valuation": 60, } + +export_python_type_annotations = True diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py index e5bb9e8c2e..6100756a6a 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py @@ -11,6 +11,40 @@ from erpnext.utilities.transaction_base import TransactionBase, delete_events class MaintenanceSchedule(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.maintenance.doctype.maintenance_schedule_detail.maintenance_schedule_detail import ( + MaintenanceScheduleDetail, + ) + from erpnext.maintenance.doctype.maintenance_schedule_item.maintenance_schedule_item import ( + MaintenanceScheduleItem, + ) + + address_display: DF.SmallText | None + amended_from: DF.Link | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.Data | None + contact_person: DF.Link | None + customer: DF.Link | None + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + items: DF.Table[MaintenanceScheduleItem] + naming_series: DF.Literal["MAT-MSH-.YYYY.-"] + schedules: DF.Table[MaintenanceScheduleDetail] + status: DF.Literal["", "Draft", "Submitted", "Cancelled"] + territory: DF.Link | None + transaction_date: DF.Date + # end: auto-generated types + @frappe.whitelist() def generate_schedule(self): if self.docstatus != 0: diff --git a/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py b/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py index cb20066da0..0bc3eeea14 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py +++ b/erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class MaintenanceScheduleDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_date: DF.Date | None + completion_status: DF.Literal["Pending", "Partially Completed", "Fully Completed"] + item_code: DF.Link | None + item_name: DF.Data | None + item_reference: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + sales_person: DF.Link | None + scheduled_date: DF.Date + serial_no: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py index b6ce0a50f1..448b081b9b 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py +++ b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.py @@ -6,4 +6,28 @@ from frappe.model.document import Document class MaintenanceScheduleItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor | None + end_date: DF.Date + item_code: DF.Link + item_name: DF.Data | None + no_of_visits: DF.Int + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + periodicity: DF.Literal["", "Weekly", "Monthly", "Quarterly", "Half Yearly", "Yearly", "Random"] + sales_order: DF.Link | None + sales_person: DF.Link | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + start_date: DF.Date + # end: auto-generated types + pass diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py index b900b216e6..e7df4847dd 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py @@ -10,6 +10,42 @@ from erpnext.utilities.transaction_base import TransactionBase class MaintenanceVisit(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.maintenance.doctype.maintenance_visit_purpose.maintenance_visit_purpose import ( + MaintenanceVisitPurpose, + ) + + address_display: DF.SmallText | None + amended_from: DF.Link | None + company: DF.Link + completion_status: DF.Literal["", "Partially Completed", "Fully Completed"] + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.Data | None + contact_person: DF.Link | None + customer: DF.Link + customer_address: DF.Link | None + customer_feedback: DF.SmallText | None + customer_group: DF.Link | None + customer_name: DF.Data | None + maintenance_schedule: DF.Link | None + maintenance_schedule_detail: DF.Link | None + maintenance_type: DF.Literal["", "Scheduled", "Unscheduled", "Breakdown"] + mntc_date: DF.Date + mntc_time: DF.Time | None + naming_series: DF.Literal["MAT-MVS-.YYYY.-"] + purposes: DF.Table[MaintenanceVisitPurpose] + status: DF.Literal["", "Draft", "Cancelled", "Submitted"] + territory: DF.Link | None + # end: auto-generated types + def validate_serial_no(self): for d in self.get("purposes"): if d.serial_no and not frappe.db.exists("Serial No", d.serial_no): diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py index 50d9a4e08a..3686941c64 100644 --- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py +++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class MaintenanceVisitPurpose(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor + item_code: DF.Link | None + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + prevdoc_docname: DF.DynamicLink | None + prevdoc_doctype: DF.Link | None + serial_no: DF.Link | None + service_person: DF.Link + work_done: DF.SmallText + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py index 0135a4f971..b5ab63efd0 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py @@ -13,6 +13,31 @@ from erpnext.stock.doctype.item.item import get_item_defaults class BlanketOrder(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.blanket_order_item.blanket_order_item import BlanketOrderItem + + amended_from: DF.Link | None + blanket_order_type: DF.Literal["", "Selling", "Purchasing"] + company: DF.Link + customer: DF.Link | None + customer_name: DF.Data | None + from_date: DF.Date + items: DF.Table[BlanketOrderItem] + naming_series: DF.Literal["MFG-BLR-.YYYY.-"] + supplier: DF.Link | None + supplier_name: DF.Data | None + tc_name: DF.Link | None + terms: DF.TextEditor | None + to_date: DF.Date + # end: auto-generated types + def validate(self): self.validate_dates() self.validate_duplicate_items() diff --git a/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py b/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py index ebce209fbc..068c2e9118 100644 --- a/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py +++ b/erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class BlanketOrderItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_code: DF.Link + item_name: DF.Data | None + ordered_qty: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + rate: DF.Currency + terms_and_conditions: DF.Text | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 229f8853ff..d48908edfb 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -103,6 +103,71 @@ class BOMTree: class BOM(WebsiteGenerator): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.bom_explosion_item.bom_explosion_item import BOMExplosionItem + from erpnext.manufacturing.doctype.bom_item.bom_item import BOMItem + from erpnext.manufacturing.doctype.bom_operation.bom_operation import BOMOperation + from erpnext.manufacturing.doctype.bom_scrap_item.bom_scrap_item import BOMScrapItem + + allow_alternative_item: DF.Check + amended_from: DF.Link | None + base_operating_cost: DF.Currency + base_raw_material_cost: DF.Currency + base_scrap_material_cost: DF.Currency + base_total_cost: DF.Currency + bom_creator: DF.Link | None + bom_creator_item: DF.Data | None + buying_price_list: DF.Link | None + company: DF.Link + conversion_rate: DF.Float + currency: DF.Link + description: DF.SmallText | None + exploded_items: DF.Table[BOMExplosionItem] + fg_based_operating_cost: DF.Check + has_variants: DF.Check + image: DF.AttachImage | None + inspection_required: DF.Check + is_active: DF.Check + is_default: DF.Check + item: DF.Link + item_name: DF.Data | None + items: DF.Table[BOMItem] + operating_cost: DF.Currency + operating_cost_per_bom_quantity: DF.Currency + operations: DF.Table[BOMOperation] + plc_conversion_rate: DF.Float + price_list_currency: DF.Link | None + process_loss_percentage: DF.Percent + process_loss_qty: DF.Float + project: DF.Link | None + quality_inspection_template: DF.Link | None + quantity: DF.Float + raw_material_cost: DF.Currency + rm_cost_as_per: DF.Literal["Valuation Rate", "Last Purchase Rate", "Price List", "Manual"] + route: DF.SmallText | None + routing: DF.Link | None + scrap_items: DF.Table[BOMScrapItem] + scrap_material_cost: DF.Currency + set_rate_of_sub_assembly_item_based_on_bom: DF.Check + show_in_website: DF.Check + show_items: DF.Check + show_operations: DF.Check + thumbnail: DF.Data | None + total_cost: DF.Currency + transfer_material_against: DF.Literal["", "Work Order", "Job Card"] + uom: DF.Link | None + web_long_description: DF.TextEditor | None + website_image: DF.AttachImage | None + with_operations: DF.Check + # end: auto-generated types + website = frappe._dict( # page_title_field = "item_name", condition_field="show_in_website", diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py index 49041a0929..bd010d9f9a 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py @@ -32,6 +32,39 @@ BOM_ITEM_FIELDS = [ class BOMCreator(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.bom_creator_item.bom_creator_item import BOMCreatorItem + + amended_from: DF.Link | None + buying_price_list: DF.Link | None + company: DF.Link + conversion_rate: DF.Float + currency: DF.Link + default_warehouse: DF.Link | None + error_log: DF.Text | None + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + items: DF.Table[BOMCreatorItem] + plc_conversion_rate: DF.Float + price_list_currency: DF.Link | None + project: DF.Link | None + qty: DF.Float + raw_material_cost: DF.Currency + remarks: DF.TextEditor | None + rm_cost_as_per: DF.Literal["Valuation Rate", "Last Purchase Rate", "Price List", "Manual"] + set_rate_based_on_warehouse: DF.Check + status: DF.Literal["Draft", "Submitted", "In Progress", "Completed", "Failed", "Cancelled"] + uom: DF.Link | None + # end: auto-generated types + def before_save(self): self.set_status() self.set_is_expandable() diff --git a/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.py b/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.py index 350c9180b9..e172f36224 100644 --- a/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.py +++ b/erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.py @@ -6,4 +6,39 @@ from frappe.model.document import Document class BOMCreatorItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + base_amount: DF.Currency + base_rate: DF.Currency + bom_created: DF.Check + conversion_factor: DF.Float + description: DF.SmallText | None + do_not_explode: DF.Check + fg_item: DF.Link + fg_reference_id: DF.Data | None + instruction: DF.SmallText | None + is_expandable: DF.Check + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + parent: DF.Data + parent_row_no: DF.Data | None + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + rate: DF.Currency + source_warehouse: DF.Link | None + sourced_by_supplier: DF.Check + stock_qty: DF.Float + stock_uom: DF.Link | None + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py index cbcba345bc..98e254ffe9 100644 --- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py +++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.py @@ -6,4 +6,30 @@ from frappe.model.document import Document class BOMExplosionItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + description: DF.TextEditor | None + image: DF.Attach | None + include_item_in_manufacturing: DF.Check + item_code: DF.Link | None + item_name: DF.Data | None + operation: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty_consumed_per_unit: DF.Float + rate: DF.Currency + source_warehouse: DF.Link | None + sourced_by_supplier: DF.Check + stock_qty: DF.Float + stock_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.py b/erpnext/manufacturing/doctype/bom_item/bom_item.py index 28a4b20144..466253bf0b 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.py +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.py @@ -6,4 +6,40 @@ from frappe.model.document import Document class BOMItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_alternative_item: DF.Check + amount: DF.Currency + base_amount: DF.Currency + base_rate: DF.Currency + bom_no: DF.Link | None + conversion_factor: DF.Float + description: DF.TextEditor | None + do_not_explode: DF.Check + has_variants: DF.Check + image: DF.Attach | None + include_item_in_manufacturing: DF.Check + item_code: DF.Link + item_name: DF.Data | None + operation: DF.Link | None + original_item: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + qty_consumed_per_unit: DF.Float + rate: DF.Currency + source_warehouse: DF.Link | None + sourced_by_supplier: DF.Check + stock_qty: DF.Float + stock_uom: DF.Link | None + uom: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_operation/bom_operation.py b/erpnext/manufacturing/doctype/bom_operation/bom_operation.py index 0ddc280ac0..66ac02891b 100644 --- a/erpnext/manufacturing/doctype/bom_operation/bom_operation.py +++ b/erpnext/manufacturing/doctype/bom_operation/bom_operation.py @@ -6,4 +6,33 @@ from frappe.model.document import Document class BOMOperation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + base_cost_per_unit: DF.Float + base_hour_rate: DF.Currency + base_operating_cost: DF.Currency + batch_size: DF.Int + cost_per_unit: DF.Float + description: DF.TextEditor | None + fixed_time: DF.Check + hour_rate: DF.Currency + image: DF.Attach | None + operating_cost: DF.Currency + operation: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + sequence_id: DF.Int + set_cost_based_on_bom_qty: DF.Check + time_in_mins: DF.Float + workstation: DF.Link | None + workstation_type: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py index f400303b95..043bbc63b5 100644 --- a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py +++ b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class BOMScrapItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + base_amount: DF.Currency + base_rate: DF.Currency + item_code: DF.Link + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Currency + stock_qty: DF.Float + stock_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_update_batch/bom_update_batch.py b/erpnext/manufacturing/doctype/bom_update_batch/bom_update_batch.py index f952e435e6..c3793bef98 100644 --- a/erpnext/manufacturing/doctype/bom_update_batch/bom_update_batch.py +++ b/erpnext/manufacturing/doctype/bom_update_batch/bom_update_batch.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class BOMUpdateBatch(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + batch_no: DF.Int + boms_updated: DF.LongText | None + level: DF.Int + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + status: DF.Literal["Pending", "Completed"] + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py index e9867468f9..198b9b815c 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py @@ -24,6 +24,27 @@ class BOMMissingError(frappe.ValidationError): class BOMUpdateLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.bom_update_batch.bom_update_batch import BOMUpdateBatch + + amended_from: DF.Link | None + bom_batches: DF.Table[BOMUpdateBatch] + current_bom: DF.Link | None + current_level: DF.Int + error_log: DF.Link | None + new_bom: DF.Link | None + processed_boms: DF.LongText | None + status: DF.Literal["Queued", "In Progress", "Completed", "Failed"] + update_type: DF.Literal["Replace BOM", "Update Cost"] + # end: auto-generated types + @staticmethod def clear_old_logs(days=None): days = days or 90 diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py index d16fcd0832..95521163e5 100644 --- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py @@ -12,6 +12,18 @@ from frappe.model.document import Document class BOMUpdateTool(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + current_bom: DF.Link + new_bom: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py b/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py index 33256a3b31..8c6321f2b7 100644 --- a/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py +++ b/erpnext/manufacturing/doctype/bom_website_item/bom_website_item.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class BOMWebsiteItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor | None + item_code: DF.Link | None + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + website_image: DF.Attach | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py b/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py index f8e279287a..b43b8618d8 100644 --- a/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py +++ b/erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class BOMWebsiteOperation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + operation: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + thumbnail: DF.Data | None + time_in_mins: DF.Float + website_image: DF.Attach | None + workstation: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py b/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py index 460281658a..1366ada255 100644 --- a/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py +++ b/erpnext/manufacturing/doctype/downtime_entry/downtime_entry.py @@ -7,6 +7,33 @@ from frappe.utils import time_diff_in_hours class DowntimeEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + downtime: DF.Float + from_time: DF.Datetime + naming_series: DF.Literal["DT-"] + operator: DF.Link + remarks: DF.Text | None + stop_reason: DF.Literal[ + "", + "Excessive machine set up time", + "Unplanned machine maintenance", + "On-machine press checks", + "Machine operator errors", + "Machine malfunction", + "Electricity down", + "Other", + ] + to_time: DF.Datetime + workstation: DF.Link + # end: auto-generated types + def validate(self): if self.from_time and self.to_time: self.downtime = time_diff_in_hours(self.to_time, self.from_time) * 60 diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index f303531aee..4b1015de68 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -51,6 +51,82 @@ class JobCardOverTransferError(frappe.ValidationError): class JobCard(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.job_card_item.job_card_item import JobCardItem + from erpnext.manufacturing.doctype.job_card_operation.job_card_operation import JobCardOperation + from erpnext.manufacturing.doctype.job_card_scheduled_time.job_card_scheduled_time import ( + JobCardScheduledTime, + ) + from erpnext.manufacturing.doctype.job_card_scrap_item.job_card_scrap_item import ( + JobCardScrapItem, + ) + from erpnext.manufacturing.doctype.job_card_time_log.job_card_time_log import JobCardTimeLog + + actual_end_date: DF.Datetime | None + actual_start_date: DF.Datetime | None + amended_from: DF.Link | None + barcode: DF.Barcode | None + batch_no: DF.Link | None + bom_no: DF.Link | None + company: DF.Link + current_time: DF.Int + employee: DF.TableMultiSelect[JobCardTimeLog] + expected_end_date: DF.Datetime | None + expected_start_date: DF.Datetime | None + for_job_card: DF.Link | None + for_operation: DF.Link | None + for_quantity: DF.Float + hour_rate: DF.Currency + is_corrective_job_card: DF.Check + item_name: DF.ReadOnly | None + items: DF.Table[JobCardItem] + job_started: DF.Check + naming_series: DF.Literal["PO-JOB.#####"] + operation: DF.Link + operation_id: DF.Data | None + operation_row_number: DF.Literal + posting_date: DF.Date | None + process_loss_qty: DF.Float + production_item: DF.Link | None + project: DF.Link | None + quality_inspection: DF.Link | None + quality_inspection_template: DF.Link | None + remarks: DF.SmallText | None + requested_qty: DF.Float + scheduled_time_logs: DF.Table[JobCardScheduledTime] + scrap_items: DF.Table[JobCardScrapItem] + sequence_id: DF.Int + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + started_time: DF.Datetime | None + status: DF.Literal[ + "Open", + "Work In Progress", + "Material Transferred", + "On Hold", + "Submitted", + "Cancelled", + "Completed", + ] + sub_operations: DF.Table[JobCardOperation] + time_logs: DF.Table[JobCardTimeLog] + time_required: DF.Float + total_completed_qty: DF.Float + total_time_in_mins: DF.Float + transferred_qty: DF.Float + wip_warehouse: DF.Link + work_order: DF.Link + workstation: DF.Link + workstation_type: DF.Link | None + # end: auto-generated types + def onload(self): excess_transfer = frappe.db.get_single_value( "Manufacturing Settings", "job_card_excess_transfer" diff --git a/erpnext/manufacturing/doctype/job_card_item/job_card_item.py b/erpnext/manufacturing/doctype/job_card_item/job_card_item.py index 51a7b41f0d..ecf082392a 100644 --- a/erpnext/manufacturing/doctype/job_card_item/job_card_item.py +++ b/erpnext/manufacturing/doctype/job_card_item/job_card_item.py @@ -6,4 +6,27 @@ from frappe.model.document import Document class JobCardItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_alternative_item: DF.Check + description: DF.Text | None + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + required_qty: DF.Float + source_warehouse: DF.Link | None + stock_uom: DF.Link | None + transferred_qty: DF.Float + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py b/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py index de44071c6a..4d32dd4728 100644 --- a/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py +++ b/erpnext/manufacturing/doctype/job_card_operation/job_card_operation.py @@ -7,4 +7,21 @@ from frappe.model.document import Document class JobCardOperation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + completed_qty: DF.Float + completed_time: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + status: DF.Literal["Complete", "Pause", "Pending", "Work In Progress"] + sub_operation: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/job_card_scheduled_time/job_card_scheduled_time.py b/erpnext/manufacturing/doctype/job_card_scheduled_time/job_card_scheduled_time.py index e50b153b9c..b9f44dc4d3 100644 --- a/erpnext/manufacturing/doctype/job_card_scheduled_time/job_card_scheduled_time.py +++ b/erpnext/manufacturing/doctype/job_card_scheduled_time/job_card_scheduled_time.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class JobCardScheduledTime(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from_time: DF.Datetime | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + time_in_mins: DF.Float + to_time: DF.Datetime | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/job_card_scrap_item/job_card_scrap_item.py b/erpnext/manufacturing/doctype/job_card_scrap_item/job_card_scrap_item.py index 372df1b0fa..e4b926efc0 100644 --- a/erpnext/manufacturing/doctype/job_card_scrap_item/job_card_scrap_item.py +++ b/erpnext/manufacturing/doctype/job_card_scrap_item/job_card_scrap_item.py @@ -5,4 +5,22 @@ from frappe.model.document import Document class JobCardScrapItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + item_code: DF.Link + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + stock_qty: DF.Float + stock_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py index 2b3ead383a..ba802a98e8 100644 --- a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py +++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class JobCardTimeLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + completed_qty: DF.Float + employee: DF.Link | None + from_time: DF.Datetime | None + operation: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + time_in_mins: DF.Float + to_time: DF.Datetime | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py index 730a857524..bfc8f4e915 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py @@ -9,6 +9,32 @@ from frappe.utils import cint class ManufacturingSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + add_corrective_operation_cost_in_finished_good_valuation: DF.Check + allow_overtime: DF.Check + allow_production_on_holidays: DF.Check + backflush_raw_materials_based_on: DF.Literal["BOM", "Material Transferred for Manufacture"] + capacity_planning_for_days: DF.Int + default_fg_warehouse: DF.Link | None + default_scrap_warehouse: DF.Link | None + default_wip_warehouse: DF.Link | None + disable_capacity_planning: DF.Check + job_card_excess_transfer: DF.Check + make_serial_no_batch_from_work_order: DF.Check + material_consumption: DF.Check + mins_between_operations: DF.Int + overproduction_percentage_for_sales_order: DF.Percent + overproduction_percentage_for_work_order: DF.Percent + update_bom_costs_automatically: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py index 3d5a7ce3fe..aa1c72294d 100644 --- a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py +++ b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.py @@ -6,4 +6,38 @@ from frappe.model.document import Document class MaterialRequestPlanItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + conversion_factor: DF.Float + description: DF.TextEditor | None + from_warehouse: DF.Link | None + item_code: DF.Link + item_name: DF.Data | None + material_request_type: DF.Literal[ + "", "Purchase", "Material Transfer", "Material Issue", "Manufacture", "Customer Provided" + ] + min_order_qty: DF.Float + ordered_qty: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + projected_qty: DF.Float + quantity: DF.Float + requested_qty: DF.Float + required_bom_qty: DF.Float + reserved_qty_for_production: DF.Float + safety_stock: DF.Float + sales_order: DF.Link | None + schedule_date: DF.Date | None + uom: DF.Link | None + warehouse: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/operation/operation.py b/erpnext/manufacturing/doctype/operation/operation.py index 9c8f9ac8d0..3969291094 100644 --- a/erpnext/manufacturing/doctype/operation/operation.py +++ b/erpnext/manufacturing/doctype/operation/operation.py @@ -8,6 +8,26 @@ from frappe.model.document import Document class Operation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.sub_operation.sub_operation import SubOperation + + batch_size: DF.Int + create_job_card_based_on_batch_size: DF.Check + description: DF.Text | None + is_corrective_operation: DF.Check + quality_inspection_template: DF.Link | None + sub_operations: DF.Table[SubOperation] + total_operation_time: DF.Float + workstation: DF.Link | None + # end: auto-generated types + def validate(self): if not self.description: self.description = self.name diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 6efb762905..955821fc58 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -33,6 +33,81 @@ from erpnext.utilities.transaction_base import validate_uom_is_integer class ProductionPlan(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.material_request_plan_item.material_request_plan_item import ( + MaterialRequestPlanItem, + ) + from erpnext.manufacturing.doctype.production_plan_item.production_plan_item import ( + ProductionPlanItem, + ) + from erpnext.manufacturing.doctype.production_plan_item_reference.production_plan_item_reference import ( + ProductionPlanItemReference, + ) + from erpnext.manufacturing.doctype.production_plan_material_request.production_plan_material_request import ( + ProductionPlanMaterialRequest, + ) + from erpnext.manufacturing.doctype.production_plan_material_request_warehouse.production_plan_material_request_warehouse import ( + ProductionPlanMaterialRequestWarehouse, + ) + from erpnext.manufacturing.doctype.production_plan_sales_order.production_plan_sales_order import ( + ProductionPlanSalesOrder, + ) + from erpnext.manufacturing.doctype.production_plan_sub_assembly_item.production_plan_sub_assembly_item import ( + ProductionPlanSubAssemblyItem, + ) + + amended_from: DF.Link | None + combine_items: DF.Check + combine_sub_items: DF.Check + company: DF.Link + customer: DF.Link | None + for_warehouse: DF.Link | None + from_date: DF.Date | None + from_delivery_date: DF.Date | None + get_items_from: DF.Literal["", "Sales Order", "Material Request"] + ignore_existing_ordered_qty: DF.Check + include_non_stock_items: DF.Check + include_safety_stock: DF.Check + include_subcontracted_items: DF.Check + item_code: DF.Link | None + material_requests: DF.Table[ProductionPlanMaterialRequest] + mr_items: DF.Table[MaterialRequestPlanItem] + naming_series: DF.Literal["MFG-PP-.YYYY.-"] + po_items: DF.Table[ProductionPlanItem] + posting_date: DF.Date + prod_plan_references: DF.Table[ProductionPlanItemReference] + project: DF.Link | None + sales_order_status: DF.Literal["", "To Deliver and Bill", "To Bill", "To Deliver"] + sales_orders: DF.Table[ProductionPlanSalesOrder] + skip_available_sub_assembly_item: DF.Check + status: DF.Literal[ + "", + "Draft", + "Submitted", + "Not Started", + "In Process", + "Completed", + "Closed", + "Cancelled", + "Material Requested", + ] + sub_assembly_items: DF.Table[ProductionPlanSubAssemblyItem] + sub_assembly_warehouse: DF.Link | None + to_date: DF.Date | None + to_delivery_date: DF.Date | None + total_planned_qty: DF.Float + total_produced_qty: DF.Float + warehouse: DF.Link | None + warehouses: DF.TableMultiSelect[ProductionPlanMaterialRequestWarehouse] + # end: auto-generated types + def validate(self): self.set_pending_qty_in_row_without_reference() self.calculate_total_planned_qty() diff --git a/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py b/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py index cc79ac327d..316923bad2 100644 --- a/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py +++ b/erpnext/manufacturing/doctype/production_plan_item/production_plan_item.py @@ -6,4 +6,35 @@ from frappe.model.document import Document class ProductionPlanItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + bom_no: DF.Link + description: DF.TextEditor | None + include_exploded_items: DF.Check + item_code: DF.Link + item_reference: DF.Data | None + material_request: DF.Link | None + material_request_item: DF.Data | None + ordered_qty: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + pending_qty: DF.Float + planned_qty: DF.Float + planned_start_date: DF.Datetime + produced_qty: DF.Float + product_bundle_item: DF.Link | None + sales_order: DF.Link | None + sales_order_item: DF.Data | None + stock_uom: DF.Link + temporary_name: DF.Data | None + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py b/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py index 81d2ecad54..d95bf8c006 100644 --- a/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py +++ b/erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.py @@ -7,4 +7,21 @@ from frappe.model.document import Document class ProductionPlanItemReference(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_reference: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Data | None + sales_order: DF.Link | None + sales_order_item: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py b/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py index 83b17893c0..efcba22c4f 100644 --- a/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py +++ b/erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ProductionPlanMaterialRequest(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + material_request: DF.Link + material_request_date: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py index a66ff44f55..13e27e5187 100644 --- a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py +++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class ProductionPlanMaterialRequestWarehouse(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py b/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py index 3f3852983c..7f793b5868 100644 --- a/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py +++ b/erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class ProductionPlanSalesOrder(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer: DF.Link | None + grand_total: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + sales_order: DF.Link + sales_order_date: DF.Date | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py b/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py index 069667a641..ad1d655de8 100644 --- a/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py +++ b/erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.py @@ -7,4 +7,37 @@ from frappe.model.document import Document class ProductionPlanSubAssemblyItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + bom_level: DF.Int + bom_no: DF.Link | None + description: DF.SmallText | None + fg_warehouse: DF.Link | None + indent: DF.Int + item_name: DF.Data | None + parent: DF.Data + parent_item_code: DF.Link | None + parentfield: DF.Data + parenttype: DF.Data + production_item: DF.Link | None + production_plan_item: DF.Data | None + projected_qty: DF.Float + purchase_order: DF.Link | None + qty: DF.Float + received_qty: DF.Float + schedule_date: DF.Datetime | None + stock_uom: DF.Link | None + supplier: DF.Link | None + type_of_manufacturing: DF.Literal["In House", "Subcontract", "Material Request"] + uom: DF.Link | None + wo_produced_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/routing/routing.py b/erpnext/manufacturing/doctype/routing/routing.py index d4c37cf79e..4bef3800bf 100644 --- a/erpnext/manufacturing/doctype/routing/routing.py +++ b/erpnext/manufacturing/doctype/routing/routing.py @@ -9,6 +9,21 @@ from frappe.utils import cint, flt class Routing(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.bom_operation.bom_operation import BOMOperation + + disabled: DF.Check + operations: DF.Table[BOMOperation] + routing_name: DF.Data | None + # end: auto-generated types + def validate(self): self.calculate_operating_cost() self.set_routing_id() diff --git a/erpnext/manufacturing/doctype/sub_operation/sub_operation.py b/erpnext/manufacturing/doctype/sub_operation/sub_operation.py index c86058eb58..f4bb62e8f6 100644 --- a/erpnext/manufacturing/doctype/sub_operation/sub_operation.py +++ b/erpnext/manufacturing/doctype/sub_operation/sub_operation.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class SubOperation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + operation: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + time_in_mins: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 36a0cae5cc..78bfc767d6 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -64,6 +64,80 @@ class SerialNoQtyError(frappe.ValidationError): class WorkOrder(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.work_order_item.work_order_item import WorkOrderItem + from erpnext.manufacturing.doctype.work_order_operation.work_order_operation import ( + WorkOrderOperation, + ) + + actual_end_date: DF.Datetime | None + actual_operating_cost: DF.Currency + actual_start_date: DF.Datetime | None + additional_operating_cost: DF.Currency + allow_alternative_item: DF.Check + amended_from: DF.Link | None + batch_size: DF.Float + bom_no: DF.Link + company: DF.Link + corrective_operation_cost: DF.Currency + description: DF.SmallText | None + expected_delivery_date: DF.Date | None + fg_warehouse: DF.Link + from_wip_warehouse: DF.Check + has_batch_no: DF.Check + has_serial_no: DF.Check + image: DF.AttachImage | None + item_name: DF.Data | None + lead_time: DF.Float + material_request: DF.Link | None + material_request_item: DF.Data | None + material_transferred_for_manufacturing: DF.Float + naming_series: DF.Literal["MFG-WO-.YYYY.-"] + operations: DF.Table[WorkOrderOperation] + planned_end_date: DF.Datetime | None + planned_operating_cost: DF.Currency + planned_start_date: DF.Datetime + process_loss_qty: DF.Float + produced_qty: DF.Float + product_bundle_item: DF.Link | None + production_item: DF.Link + production_plan: DF.Link | None + production_plan_item: DF.Data | None + production_plan_sub_assembly_item: DF.Data | None + project: DF.Link | None + qty: DF.Float + required_items: DF.Table[WorkOrderItem] + sales_order: DF.Link | None + sales_order_item: DF.Data | None + scrap_warehouse: DF.Link | None + skip_transfer: DF.Check + source_warehouse: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "Submitted", + "Not Started", + "In Process", + "Completed", + "Stopped", + "Closed", + "Cancelled", + ] + stock_uom: DF.Link | None + total_operating_cost: DF.Currency + transfer_material_against: DF.Literal["", "Work Order", "Job Card"] + update_consumed_material_cost_in_project: DF.Check + use_multi_level_bom: DF.Check + wip_warehouse: DF.Link | None + # end: auto-generated types + def onload(self): ms = frappe.get_doc("Manufacturing Settings") self.set_onload("material_consumption", ms.material_consumption) diff --git a/erpnext/manufacturing/doctype/work_order_item/work_order_item.py b/erpnext/manufacturing/doctype/work_order_item/work_order_item.py index 179274707e..267ca5d21d 100644 --- a/erpnext/manufacturing/doctype/work_order_item/work_order_item.py +++ b/erpnext/manufacturing/doctype/work_order_item/work_order_item.py @@ -7,6 +7,34 @@ from frappe.model.document import Document class WorkOrderItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_alternative_item: DF.Check + amount: DF.Currency + available_qty_at_source_warehouse: DF.Float + available_qty_at_wip_warehouse: DF.Float + consumed_qty: DF.Float + description: DF.Text | None + include_item_in_manufacturing: DF.Check + item_code: DF.Link | None + item_name: DF.Data | None + operation: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Currency + required_qty: DF.Float + returned_qty: DF.Float + source_warehouse: DF.Link | None + transferred_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py index 6bda58ea77..5bd3ab1b21 100644 --- a/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py +++ b/erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py @@ -6,4 +6,36 @@ from frappe.model.document import Document class WorkOrderOperation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_end_time: DF.Datetime | None + actual_operating_cost: DF.Currency + actual_operation_time: DF.Float + actual_start_time: DF.Datetime | None + batch_size: DF.Float + bom: DF.Link | None + completed_qty: DF.Float + description: DF.TextEditor | None + hour_rate: DF.Float + operation: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + planned_end_time: DF.Datetime | None + planned_operating_cost: DF.Currency + planned_start_time: DF.Datetime | None + process_loss_qty: DF.Float + sequence_id: DF.Int + status: DF.Literal["Pending", "Work in Progress", "Completed"] + time_in_mins: DF.Float + workstation: DF.Link | None + workstation_type: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py index ac271b7144..0a247fc431 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation.py +++ b/erpnext/manufacturing/doctype/workstation/workstation.py @@ -32,6 +32,31 @@ class OverlapError(frappe.ValidationError): class Workstation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.manufacturing.doctype.workstation_working_hour.workstation_working_hour import ( + WorkstationWorkingHour, + ) + + description: DF.Text | None + holiday_list: DF.Link | None + hour_rate: DF.Currency + hour_rate_consumable: DF.Currency + hour_rate_electricity: DF.Currency + hour_rate_labour: DF.Currency + hour_rate_rent: DF.Currency + production_capacity: DF.Int + working_hours: DF.Table[WorkstationWorkingHour] + workstation_name: DF.Data + workstation_type: DF.Link | None + # end: auto-generated types + def before_save(self): self.set_data_based_on_workstation_type() self.set_hour_rate() diff --git a/erpnext/manufacturing/doctype/workstation_type/workstation_type.py b/erpnext/manufacturing/doctype/workstation_type/workstation_type.py index 8c1e230af0..0f151a2fb2 100644 --- a/erpnext/manufacturing/doctype/workstation_type/workstation_type.py +++ b/erpnext/manufacturing/doctype/workstation_type/workstation_type.py @@ -7,6 +7,23 @@ from frappe.utils import flt class WorkstationType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + hour_rate: DF.Currency + hour_rate_consumable: DF.Currency + hour_rate_electricity: DF.Currency + hour_rate_labour: DF.Currency + hour_rate_rent: DF.Currency + workstation_type: DF.Data + # end: auto-generated types + def before_save(self): self.set_hour_rate() diff --git a/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py b/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py index 99fb5524a9..6754d66fec 100644 --- a/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py +++ b/erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class WorkstationWorkingHour(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + enabled: DF.Check + end_time: DF.Time + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + start_time: DF.Time + # end: auto-generated types + pass diff --git a/erpnext/portal/doctype/homepage/homepage.py b/erpnext/portal/doctype/homepage/homepage.py index c0a0c07d7d..3539b280ca 100644 --- a/erpnext/portal/doctype/homepage/homepage.py +++ b/erpnext/portal/doctype/homepage/homepage.py @@ -8,6 +8,24 @@ from frappe.website.utils import delete_page_cache class Homepage(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link + description: DF.Text + hero_image: DF.AttachImage | None + hero_section: DF.Link | None + hero_section_based_on: DF.Literal["Default", "Slideshow", "Homepage Section"] + slideshow: DF.Link | None + tag_line: DF.Data + title: DF.Data | None + # end: auto-generated types + def validate(self): if not self.description: self.description = frappe._("This is an example website auto-generated from ERPNext") diff --git a/erpnext/portal/doctype/homepage_section/homepage_section.py b/erpnext/portal/doctype/homepage_section/homepage_section.py index 7181affbea..9499ce3232 100644 --- a/erpnext/portal/doctype/homepage_section/homepage_section.py +++ b/erpnext/portal/doctype/homepage_section/homepage_section.py @@ -7,6 +7,25 @@ from frappe.utils import cint class HomepageSection(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.portal.doctype.homepage_section_card.homepage_section_card import ( + HomepageSectionCard, + ) + + no_of_columns: DF.Literal["1", "2", "3", "4", "6"] + section_based_on: DF.Literal["Cards", "Custom HTML"] + section_cards: DF.Table[HomepageSectionCard] + section_html: DF.Code | None + section_order: DF.Int + # end: auto-generated types + @property def column_value(self): return cint(12 / cint(self.no_of_columns or 3)) diff --git a/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py index eeff63c3f3..ce2fe31a98 100644 --- a/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py +++ b/erpnext/portal/doctype/homepage_section_card/homepage_section_card.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class HomepageSectionCard(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + content: DF.Text | None + image: DF.AttachImage | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + route: DF.Data | None + subtitle: DF.Data | None + title: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/portal/doctype/website_attribute/website_attribute.py b/erpnext/portal/doctype/website_attribute/website_attribute.py index 58a73768be..2e4a1e3268 100644 --- a/erpnext/portal/doctype/website_attribute/website_attribute.py +++ b/erpnext/portal/doctype/website_attribute/website_attribute.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class WebsiteAttribute(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + attribute: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/portal/doctype/website_filter_field/website_filter_field.py b/erpnext/portal/doctype/website_filter_field/website_filter_field.py index 8067ebba0f..7c48e9dd2a 100644 --- a/erpnext/portal/doctype/website_filter_field/website_filter_field.py +++ b/erpnext/portal/doctype/website_filter_field/website_filter_field.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class WebsiteFilterField(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + fieldname: DF.Autocomplete | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/activity_cost/activity_cost.py b/erpnext/projects/doctype/activity_cost/activity_cost.py index b99aa1e37d..257bcc4251 100644 --- a/erpnext/projects/doctype/activity_cost/activity_cost.py +++ b/erpnext/projects/doctype/activity_cost/activity_cost.py @@ -12,6 +12,23 @@ class DuplicationError(frappe.ValidationError): class ActivityCost(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + activity_type: DF.Link + billing_rate: DF.Currency + costing_rate: DF.Currency + department: DF.Link | None + employee: DF.Link | None + employee_name: DF.Data | None + title: DF.Data | None + # end: auto-generated types + def validate(self): self.set_title() self.check_unique() diff --git a/erpnext/projects/doctype/activity_type/activity_type.py b/erpnext/projects/doctype/activity_type/activity_type.py index 5151098bec..b5903bbb11 100644 --- a/erpnext/projects/doctype/activity_type/activity_type.py +++ b/erpnext/projects/doctype/activity_type/activity_type.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class ActivityType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + activity_type: DF.Data + billing_rate: DF.Currency + costing_rate: DF.Currency + disabled: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/dependent_task/dependent_task.py b/erpnext/projects/doctype/dependent_task/dependent_task.py index 73ce8f9c3d..f4c276263f 100644 --- a/erpnext/projects/doctype/dependent_task/dependent_task.py +++ b/erpnext/projects/doctype/dependent_task/dependent_task.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class DependentTask(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + task: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/project_template/project_template.py b/erpnext/projects/doctype/project_template/project_template.py index 89afb1bd77..c08fc9d87f 100644 --- a/erpnext/projects/doctype/project_template/project_template.py +++ b/erpnext/projects/doctype/project_template/project_template.py @@ -9,6 +9,22 @@ from frappe.utils import get_link_to_form class ProjectTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.projects.doctype.project_template_task.project_template_task import ( + ProjectTemplateTask, + ) + + project_type: DF.Link | None + tasks: DF.Table[ProjectTemplateTask] + # end: auto-generated types + def validate(self): self.validate_dependencies() diff --git a/erpnext/projects/doctype/project_template_task/project_template_task.py b/erpnext/projects/doctype/project_template_task/project_template_task.py index 01ec93500c..d0d031b28f 100644 --- a/erpnext/projects/doctype/project_template_task/project_template_task.py +++ b/erpnext/projects/doctype/project_template_task/project_template_task.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class ProjectTemplateTask(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + subject: DF.ReadOnly | None + task: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/project_type/project_type.py b/erpnext/projects/doctype/project_type/project_type.py index 4a3724d6a5..38e3155e87 100644 --- a/erpnext/projects/doctype/project_type/project_type.py +++ b/erpnext/projects/doctype/project_type/project_type.py @@ -8,6 +8,18 @@ from frappe.model.document import Document class ProjectType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.Text | None + project_type: DF.Data + # end: auto-generated types + def on_trash(self): if self.name == "External": frappe.throw(_("You cannot delete Project Type 'External'")) diff --git a/erpnext/projects/doctype/project_update/project_update.py b/erpnext/projects/doctype/project_update/project_update.py index 175f787a30..53934d051d 100644 --- a/erpnext/projects/doctype/project_update/project_update.py +++ b/erpnext/projects/doctype/project_update/project_update.py @@ -7,6 +7,25 @@ from frappe.model.document import Document class ProjectUpdate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.projects.doctype.project_user.project_user import ProjectUser + + amended_from: DF.Link | None + date: DF.Date | None + naming_series: DF.Data | None + project: DF.Link + sent: DF.Check + time: DF.Time | None + users: DF.Table[ProjectUser] + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/project_user/project_user.py b/erpnext/projects/doctype/project_user/project_user.py index a52bcb170a..358a16a9e0 100644 --- a/erpnext/projects/doctype/project_user/project_user.py +++ b/erpnext/projects/doctype/project_user/project_user.py @@ -6,4 +6,24 @@ from frappe.model.document import Document class ProjectUser(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + email: DF.ReadOnly | None + full_name: DF.ReadOnly | None + image: DF.ReadOnly | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project_status: DF.Text | None + user: DF.Link + view_attachments: DF.Check + welcome_email_sent: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/projects_settings/projects_settings.py b/erpnext/projects/doctype/projects_settings/projects_settings.py index db1dc45d76..9d940184d9 100644 --- a/erpnext/projects/doctype/projects_settings/projects_settings.py +++ b/erpnext/projects/doctype/projects_settings/projects_settings.py @@ -6,4 +6,17 @@ from frappe.model.document import Document class ProjectsSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + ignore_employee_time_overlap: DF.Check + ignore_user_time_overlap: DF.Check + ignore_workstation_time_overlap: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 333d4d9b6a..22df846e39 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -18,6 +18,56 @@ class CircularReferenceError(frappe.ValidationError): class Task(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.projects.doctype.task_depends_on.task_depends_on import TaskDependsOn + + act_end_date: DF.Date | None + act_start_date: DF.Date | None + actual_time: DF.Float + closing_date: DF.Date | None + color: DF.Color | None + company: DF.Link | None + completed_by: DF.Link | None + completed_on: DF.Date | None + department: DF.Link | None + depends_on: DF.Table[TaskDependsOn] + depends_on_tasks: DF.Code | None + description: DF.TextEditor | None + duration: DF.Int + exp_end_date: DF.Date | None + exp_start_date: DF.Date | None + expected_time: DF.Float + is_group: DF.Check + is_milestone: DF.Check + is_template: DF.Check + issue: DF.Link | None + lft: DF.Int + old_parent: DF.Data | None + parent_task: DF.Link | None + priority: DF.Literal["Low", "Medium", "High", "Urgent"] + progress: DF.Percent + project: DF.Link | None + review_date: DF.Date | None + rgt: DF.Int + start: DF.Int + status: DF.Literal[ + "Open", "Working", "Pending Review", "Overdue", "Template", "Completed", "Cancelled" + ] + subject: DF.Data + task_weight: DF.Float + template_task: DF.Data | None + total_billing_amount: DF.Currency + total_costing_amount: DF.Currency + type: DF.Link | None + # end: auto-generated types + nsm_parent_field = "parent_task" def get_customer_details(self): diff --git a/erpnext/projects/doctype/task_depends_on/task_depends_on.py b/erpnext/projects/doctype/task_depends_on/task_depends_on.py index 0db1f81f28..c1cc21a1a0 100644 --- a/erpnext/projects/doctype/task_depends_on/task_depends_on.py +++ b/erpnext/projects/doctype/task_depends_on/task_depends_on.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class TaskDependsOn(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project: DF.Text | None + subject: DF.Text | None + task: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/task_type/task_type.py b/erpnext/projects/doctype/task_type/task_type.py index 08bed6973d..40d69e2bf1 100644 --- a/erpnext/projects/doctype/task_type/task_type.py +++ b/erpnext/projects/doctype/task_type/task_type.py @@ -7,4 +7,16 @@ from frappe.model.document import Document class TaskType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + weight: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py index d527a3c922..cd61da1849 100644 --- a/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py +++ b/erpnext/projects/doctype/timesheet_detail/timesheet_detail.py @@ -6,4 +6,38 @@ from frappe.model.document import Document class TimesheetDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + activity_type: DF.Link | None + base_billing_amount: DF.Currency + base_billing_rate: DF.Currency + base_costing_amount: DF.Currency + base_costing_rate: DF.Currency + billing_amount: DF.Currency + billing_hours: DF.Float + billing_rate: DF.Currency + completed: DF.Check + costing_amount: DF.Currency + costing_rate: DF.Currency + description: DF.SmallText | None + expected_hours: DF.Float + from_time: DF.Datetime | None + hours: DF.Float + is_billable: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project: DF.Link | None + project_name: DF.Data | None + sales_invoice: DF.Link | None + task: DF.Link | None + to_time: DF.Datetime | None + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/non_conformance/non_conformance.py b/erpnext/quality_management/doctype/non_conformance/non_conformance.py index a2198f374a..5817b99956 100644 --- a/erpnext/quality_management/doctype/non_conformance/non_conformance.py +++ b/erpnext/quality_management/doctype/non_conformance/non_conformance.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class NonConformance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + corrective_action: DF.TextEditor | None + details: DF.TextEditor | None + full_name: DF.Data | None + preventive_action: DF.TextEditor | None + procedure: DF.Link + process_owner: DF.Data | None + status: DF.Literal["Open", "Resolved", "Cancelled"] + subject: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_action/quality_action.py b/erpnext/quality_management/doctype/quality_action/quality_action.py index f7cd94dad3..3ef46e394e 100644 --- a/erpnext/quality_management/doctype/quality_action/quality_action.py +++ b/erpnext/quality_management/doctype/quality_action/quality_action.py @@ -6,5 +6,27 @@ from frappe.model.document import Document class QualityAction(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_action_resolution.quality_action_resolution import ( + QualityActionResolution, + ) + + corrective_preventive: DF.Literal["Corrective", "Preventive"] + date: DF.Date | None + feedback: DF.Link | None + goal: DF.Link | None + procedure: DF.Link | None + resolutions: DF.Table[QualityActionResolution] + review: DF.Link | None + status: DF.Literal["Open", "Completed"] + # end: auto-generated types + def validate(self): self.status = "Open" if any([d.status == "Open" for d in self.resolutions]) else "Completed" diff --git a/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py index 7ede3e4de0..5bdd513540 100644 --- a/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py +++ b/erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class QualityActionResolution(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + completion_by: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + problem: DF.LongText | None + resolution: DF.TextEditor | None + responsible: DF.Link | None + status: DF.Literal["Open", "Completed"] + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py index cc8ce26b58..8dc806163f 100644 --- a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py +++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.py @@ -7,6 +7,24 @@ from frappe.model.document import Document class QualityFeedback(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_feedback_parameter.quality_feedback_parameter import ( + QualityFeedbackParameter, + ) + + document_name: DF.DynamicLink + document_type: DF.Literal["User", "Customer"] + parameters: DF.Table[QualityFeedbackParameter] + template: DF.Link + # end: auto-generated types + @frappe.whitelist() def set_parameters(self): if self.template and not getattr(self, "parameters", []): diff --git a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py index ff2c841576..a86ba32aaf 100644 --- a/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py +++ b/erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class QualityFeedbackParameter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + feedback: DF.TextEditor | None + parameter: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rating: DF.Literal["", "1", "2", "3", "4", "5"] + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py index 4590f9d3a0..df9def3219 100644 --- a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py +++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class QualityFeedbackTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_feedback_template_parameter.quality_feedback_template_parameter import ( + QualityFeedbackTemplateParameter, + ) + + parameters: DF.Table[QualityFeedbackTemplateParameter] + template: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py index 13e215f954..7795dabf75 100644 --- a/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py +++ b/erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class QualityFeedbackTemplateParameter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parameter: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_goal/quality_goal.py b/erpnext/quality_management/doctype/quality_goal/quality_goal.py index 22ba81073d..6bcc7439f5 100644 --- a/erpnext/quality_management/doctype/quality_goal/quality_goal.py +++ b/erpnext/quality_management/doctype/quality_goal/quality_goal.py @@ -6,5 +6,56 @@ from frappe.model.document import Document class QualityGoal(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_goal_objective.quality_goal_objective import ( + QualityGoalObjective, + ) + + date: DF.Literal[ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "30", + ] + frequency: DF.Literal["None", "Daily", "Weekly", "Monthly", "Quarterly"] + goal: DF.Data + objectives: DF.Table[QualityGoalObjective] + procedure: DF.Link | None + weekday: DF.Literal["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] + # end: auto-generated types + def validate(self): pass diff --git a/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py index eaa8db2156..325c2e4d22 100644 --- a/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py +++ b/erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class QualityGoalObjective(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + objective: DF.Text + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + target: DF.Data | None + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py index 481b3c17f1..a8dd5647af 100644 --- a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py +++ b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.py @@ -6,4 +6,24 @@ from frappe.model.document import Document class QualityMeeting(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_meeting_agenda.quality_meeting_agenda import ( + QualityMeetingAgenda, + ) + from erpnext.quality_management.doctype.quality_meeting_minutes.quality_meeting_minutes import ( + QualityMeetingMinutes, + ) + + agenda: DF.Table[QualityMeetingAgenda] + minutes: DF.Table[QualityMeetingMinutes] + status: DF.Literal["Open", "Closed"] + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py index c2f5b3f17c..edf4fd665b 100644 --- a/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py +++ b/erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class QualityMeetingAgenda(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + agenda: DF.TextEditor | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py index f6998df35c..c6237d9804 100644 --- a/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py +++ b/erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class QualityMeetingMinutes(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + document_name: DF.DynamicLink | None + document_type: DF.Literal["Quality Review", "Quality Action", "Quality Feedback"] + minute: DF.TextEditor | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py index 6834abc9d4..8a67d92d1c 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py @@ -8,6 +8,29 @@ from frappe.utils.nestedset import NestedSet class QualityProcedure(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_procedure_process.quality_procedure_process import ( + QualityProcedureProcess, + ) + + is_group: DF.Check + lft: DF.Int + old_parent: DF.Data | None + parent_quality_procedure: DF.Link | None + process_owner: DF.Link | None + process_owner_full_name: DF.Data | None + processes: DF.Table[QualityProcedureProcess] + quality_procedure_name: DF.Data + rgt: DF.Int + # end: auto-generated types + nsm_parent_field = "parent_quality_procedure" def before_save(self): diff --git a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py index a03c871a85..2626fbdb8b 100644 --- a/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py +++ b/erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class QualityProcedureProcess(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + procedure: DF.Link | None + process_description: DF.TextEditor | None + # end: auto-generated types + pass diff --git a/erpnext/quality_management/doctype/quality_review/quality_review.py b/erpnext/quality_management/doctype/quality_review/quality_review.py index f691005566..bf4a4036d8 100644 --- a/erpnext/quality_management/doctype/quality_review/quality_review.py +++ b/erpnext/quality_management/doctype/quality_review/quality_review.py @@ -7,6 +7,26 @@ from frappe.model.document import Document class QualityReview(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.quality_management.doctype.quality_review_objective.quality_review_objective import ( + QualityReviewObjective, + ) + + additional_information: DF.Text | None + date: DF.Date | None + goal: DF.Link + procedure: DF.Link | None + reviews: DF.Table[QualityReviewObjective] + status: DF.Literal["Open", "Passed", "Failed"] + # end: auto-generated types + def validate(self): # fetch targets from goal if not self.reviews: diff --git a/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py index 462a97118e..9406f58e1c 100644 --- a/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py +++ b/erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class QualityReviewObjective(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + objective: DF.Text | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + review: DF.TextEditor | None + status: DF.Literal["Open", "Passed", "Failed"] + target: DF.Data | None + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py index c52685e330..bf338d6513 100644 --- a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py +++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py @@ -18,6 +18,24 @@ import erpnext class ImportSupplierInvoice(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link + default_buying_price_list: DF.Link + invoice_series: DF.Literal["ACC-PINV-.YYYY.-"] + item_code: DF.Link + status: DF.Data | None + supplier_group: DF.Link + tax_account: DF.Link + zip_file: DF.Attach | None + # end: auto-generated types + def validate(self): if not frappe.db.get_value("Stock Settings", fieldname="stock_uom"): frappe.throw(_("Please set default UOM in Stock Settings")) diff --git a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py index 6ae04c165c..72b3a49d2a 100644 --- a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py +++ b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py @@ -11,6 +11,26 @@ from erpnext.accounts.utils import get_fiscal_year class LowerDeductionCertificate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + certificate_limit: DF.Currency + certificate_no: DF.Data + company: DF.Link + fiscal_year: DF.Link + pan_no: DF.Data + rate: DF.Percent + supplier: DF.Link + tax_withholding_category: DF.Link + valid_from: DF.Date + valid_upto: DF.Date + # end: auto-generated types + def validate(self): self.validate_dates() self.validate_supplier_against_tax_category() diff --git a/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py b/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py index 4c3e8a78e9..aa3cd4b05a 100644 --- a/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py +++ b/erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class SouthAfricaVATSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.south_africa_vat_account.south_africa_vat_account import ( + SouthAfricaVATAccount, + ) + + company: DF.Link + vat_accounts: DF.Table[SouthAfricaVATAccount] + # end: auto-generated types + pass diff --git a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py index f2fc34d391..0a69aedb32 100644 --- a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py +++ b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class UAEVATAccount(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py index 1af32e4be3..95ffdd39f8 100644 --- a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py +++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class UAEVATSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.regional.doctype.uae_vat_account.uae_vat_account import UAEVATAccount + + company: DF.Link + uae_vat_accounts: DF.Table[UAEVATAccount] + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 88ed1c6667..96df0ed733 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -23,6 +23,70 @@ from erpnext.utilities.transaction_base import TransactionBase class Customer(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.allowed_to_transact_with.allowed_to_transact_with import ( + AllowedToTransactWith, + ) + from erpnext.accounts.doctype.party_account.party_account import PartyAccount + from erpnext.selling.doctype.customer_credit_limit.customer_credit_limit import ( + CustomerCreditLimit, + ) + from erpnext.selling.doctype.sales_team.sales_team import SalesTeam + from erpnext.utilities.doctype.portal_user.portal_user import PortalUser + + account_manager: DF.Link | None + accounts: DF.Table[PartyAccount] + companies: DF.Table[AllowedToTransactWith] + credit_limits: DF.Table[CustomerCreditLimit] + customer_details: DF.Text | None + customer_group: DF.Link | None + customer_name: DF.Data + customer_pos_id: DF.Data | None + customer_primary_address: DF.Link | None + customer_primary_contact: DF.Link | None + customer_type: DF.Literal["Company", "Individual", "Proprietorship", "Partnership"] + default_bank_account: DF.Link | None + default_commission_rate: DF.Float + default_currency: DF.Link | None + default_price_list: DF.Link | None + default_sales_partner: DF.Link | None + disabled: DF.Check + dn_required: DF.Check + email_id: DF.ReadOnly | None + gender: DF.Link | None + image: DF.AttachImage | None + industry: DF.Link | None + is_frozen: DF.Check + is_internal_customer: DF.Check + language: DF.Link | None + lead_name: DF.Link | None + loyalty_program: DF.Link | None + loyalty_program_tier: DF.Data | None + market_segment: DF.Link | None + mobile_no: DF.ReadOnly | None + naming_series: DF.Literal["CUST-.YYYY.-"] + opportunity_name: DF.Link | None + payment_terms: DF.Link | None + portal_users: DF.Table[PortalUser] + primary_address: DF.Text | None + represents_company: DF.Link | None + sales_team: DF.Table[SalesTeam] + salutation: DF.Link | None + so_required: DF.Check + tax_category: DF.Link | None + tax_id: DF.Data | None + tax_withholding_category: DF.Link | None + territory: DF.Link | None + website: DF.Data | None + # end: auto-generated types + def onload(self): """Load address and contacts in `__onload`""" load_address_and_contact(self) diff --git a/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py index 193027b89a..fcc6c6e6db 100644 --- a/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py +++ b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class CustomerCreditLimit(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + bypass_credit_limit_check: DF.Check + company: DF.Link | None + credit_limit: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/industry_type/industry_type.py b/erpnext/selling/doctype/industry_type/industry_type.py index fbe0131dd3..aedec5fa94 100644 --- a/erpnext/selling/doctype/industry_type/industry_type.py +++ b/erpnext/selling/doctype/industry_type/industry_type.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class IndustryType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + industry: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/installation_note/installation_note.py b/erpnext/selling/doctype/installation_note/installation_note.py index 0ef4754bc6..d1bfd910f9 100644 --- a/erpnext/selling/doctype/installation_note/installation_note.py +++ b/erpnext/selling/doctype/installation_note/installation_note.py @@ -11,6 +11,38 @@ from erpnext.utilities.transaction_base import TransactionBase class InstallationNote(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.selling.doctype.installation_note_item.installation_note_item import ( + InstallationNoteItem, + ) + + address_display: DF.SmallText | None + amended_from: DF.Link | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + customer: DF.Link + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + inst_date: DF.Date + inst_time: DF.Time | None + items: DF.Table[InstallationNoteItem] + naming_series: DF.Literal["MAT-INS-.YYYY.-"] + remarks: DF.SmallText | None + status: DF.Literal["Draft", "Submitted", "Cancelled"] + territory: DF.Link + # end: auto-generated types + def __init__(self, *args, **kwargs): super(InstallationNote, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/selling/doctype/installation_note_item/installation_note_item.py b/erpnext/selling/doctype/installation_note_item/installation_note_item.py index 2169a7b614..8566ab06a4 100644 --- a/erpnext/selling/doctype/installation_note_item/installation_note_item.py +++ b/erpnext/selling/doctype/installation_note_item/installation_note_item.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class InstallationNoteItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor | None + item_code: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + prevdoc_detail_docname: DF.Data | None + prevdoc_docname: DF.Data | None + prevdoc_doctype: DF.Data | None + qty: DF.Float + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/party_specific_item/party_specific_item.py b/erpnext/selling/doctype/party_specific_item/party_specific_item.py index 0aef7d362e..cce29f0ed2 100644 --- a/erpnext/selling/doctype/party_specific_item/party_specific_item.py +++ b/erpnext/selling/doctype/party_specific_item/party_specific_item.py @@ -7,6 +7,20 @@ from frappe.model.document import Document class PartySpecificItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + based_on_value: DF.DynamicLink + party: DF.DynamicLink + party_type: DF.Literal["Customer", "Supplier"] + restrict_based_on: DF.Literal["Item", "Item Group", "Brand"] + # end: auto-generated types + def validate(self): exists = frappe.db.exists( { diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index 3d4ffebbfb..66327426ac 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -9,6 +9,22 @@ from frappe.utils import get_link_to_form class ProductBundle(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.selling.doctype.product_bundle_item.product_bundle_item import ProductBundleItem + + description: DF.Data | None + disabled: DF.Check + items: DF.Table[ProductBundleItem] + new_item_code: DF.Link + # end: auto-generated types + def autoname(self): self.name = self.new_item_code diff --git a/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py b/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py index 5c95a555c8..285ad5d575 100644 --- a/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py +++ b/erpnext/selling/doctype/product_bundle_item/product_bundle_item.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class ProductBundleItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor | None + item_code: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + rate: DF.Float + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 95d2d2c577..8d3bb78740 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -13,6 +13,109 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class Quotation(SellingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, + ) + from erpnext.crm.doctype.competitor_detail.competitor_detail import CompetitorDetail + from erpnext.selling.doctype.quotation_item.quotation_item import QuotationItem + from erpnext.setup.doctype.quotation_lost_reason_detail.quotation_lost_reason_detail import ( + QuotationLostReasonDetail, + ) + from erpnext.stock.doctype.packed_item.packed_item import PackedItem + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + amended_from: DF.Link | None + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + campaign: DF.Link | None + company: DF.Link + company_address: DF.Link | None + company_address_display: DF.SmallText | None + competitors: DF.TableMultiSelect[CompetitorDetail] + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + coupon_code: DF.Link | None + currency: DF.Link + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + discount_amount: DF.Currency + enq_det: DF.Text | None + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + items: DF.Table[QuotationItem] + language: DF.Data | None + letter_head: DF.Link | None + lost_reasons: DF.TableMultiSelect[QuotationLostReasonDetail] + named_place: DF.Data | None + naming_series: DF.Literal["SAL-QTN-.YYYY.-"] + net_total: DF.Currency + opportunity: DF.Link | None + order_lost_reason: DF.SmallText | None + order_type: DF.Literal["", "Sales", "Maintenance", "Shopping Cart"] + other_charges_calculation: DF.LongText | None + packed_items: DF.Table[PackedItem] + party_name: DF.DynamicLink | None + payment_schedule: DF.Table[PaymentSchedule] + payment_terms_template: DF.Link | None + plc_conversion_rate: DF.Float + price_list_currency: DF.Link + pricing_rules: DF.Table[PricingRuleDetail] + quotation_to: DF.Link + referral_sales_partner: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + selling_price_list: DF.Link + shipping_address: DF.SmallText | None + shipping_address_name: DF.Link | None + shipping_rule: DF.Link | None + source: DF.Link | None + status: DF.Literal[ + "Draft", "Open", "Replied", "Partially Ordered", "Ordered", "Lost", "Cancelled", "Expired" + ] + supplier_quotation: DF.Link | None + tax_category: DF.Link | None + taxes: DF.Table[SalesTaxesandCharges] + taxes_and_charges: DF.Link | None + tc_name: DF.Link | None + terms: DF.TextEditor | None + territory: DF.Link | None + title: DF.Data | None + total: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + transaction_date: DF.Date + valid_till: DF.Date | None + # end: auto-generated types + def set_indicator(self): if self.docstatus == 1: self.indicator_color = "blue" diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.py b/erpnext/selling/doctype/quotation_item/quotation_item.py index 8c2aabbf3f..f209762c3b 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.py +++ b/erpnext/selling/doctype/quotation_item/quotation_item.py @@ -6,4 +6,67 @@ from frappe.model.document import Document class QuotationItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + additional_notes: DF.Text | None + against_blanket_order: DF.Check + amount: DF.Currency + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + blanket_order: DF.Link | None + blanket_order_rate: DF.Currency + brand: DF.Link | None + conversion_factor: DF.Float + customer_item_code: DF.Data | None + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + gross_profit: DF.Currency + has_alternative_item: DF.Check + image: DF.Attach | None + is_alternative: DF.Check + is_free_item: DF.Check + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data + item_tax_rate: DF.Code | None + item_tax_template: DF.Link | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + prevdoc_docname: DF.DynamicLink | None + prevdoc_doctype: DF.Link | None + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + projected_qty: DF.Float + qty: DF.Float + rate: DF.Currency + rate_with_margin: DF.Currency + stock_qty: DF.Float + stock_uom: DF.Link | None + stock_uom_rate: DF.Currency + total_weight: DF.Float + uom: DF.Link + valuation_rate: DF.Currency + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index a23599b180..fd6c0273ef 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -46,6 +46,139 @@ class WarehouseRequired(frappe.ValidationError): class SalesOrder(SellingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.payment_schedule.payment_schedule import PaymentSchedule + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, + ) + from erpnext.selling.doctype.sales_order_item.sales_order_item import SalesOrderItem + from erpnext.selling.doctype.sales_team.sales_team import SalesTeam + from erpnext.stock.doctype.packed_item.packed_item import PackedItem + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + advance_paid: DF.Currency + amended_from: DF.Link | None + amount_eligible_for_commission: DF.Currency + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + billing_status: DF.Literal["Not Billed", "Fully Billed", "Partly Billed", "Closed"] + campaign: DF.Link | None + commission_rate: DF.Float + company: DF.Link + company_address: DF.Link | None + company_address_display: DF.SmallText | None + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + contact_phone: DF.Data | None + conversion_rate: DF.Float + cost_center: DF.Link | None + coupon_code: DF.Link | None + currency: DF.Link + customer: DF.Link + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + delivery_date: DF.Date | None + delivery_status: DF.Literal[ + "Not Delivered", "Fully Delivered", "Partly Delivered", "Closed", "Not Applicable" + ] + disable_rounded_total: DF.Check + discount_amount: DF.Currency + dispatch_address: DF.SmallText | None + dispatch_address_name: DF.Link | None + from_date: DF.Date | None + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + inter_company_order_reference: DF.Link | None + is_internal_customer: DF.Check + items: DF.Table[SalesOrderItem] + language: DF.Data | None + letter_head: DF.Link | None + loyalty_amount: DF.Currency + loyalty_points: DF.Int + named_place: DF.Data | None + naming_series: DF.Literal["SAL-ORD-.YYYY.-"] + net_total: DF.Currency + order_type: DF.Literal["", "Sales", "Maintenance", "Shopping Cart"] + other_charges_calculation: DF.LongText | None + packed_items: DF.Table[PackedItem] + party_account_currency: DF.Link | None + payment_schedule: DF.Table[PaymentSchedule] + payment_terms_template: DF.Link | None + per_billed: DF.Percent + per_delivered: DF.Percent + per_picked: DF.Percent + plc_conversion_rate: DF.Float + po_date: DF.Date | None + po_no: DF.Data | None + price_list_currency: DF.Link + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + represents_company: DF.Link | None + reserve_stock: DF.Check + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + sales_partner: DF.Link | None + sales_team: DF.Table[SalesTeam] + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + selling_price_list: DF.Link + set_warehouse: DF.Link | None + shipping_address: DF.SmallText | None + shipping_address_name: DF.Link | None + shipping_rule: DF.Link | None + skip_delivery_note: DF.Check + source: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "On Hold", + "To Deliver and Bill", + "To Bill", + "To Deliver", + "Completed", + "Cancelled", + "Closed", + ] + tax_category: DF.Link | None + tax_id: DF.Data | None + taxes: DF.Table[SalesTaxesandCharges] + taxes_and_charges: DF.Link | None + tc_name: DF.Link | None + terms: DF.TextEditor | None + territory: DF.Link | None + title: DF.Data | None + to_date: DF.Date | None + total: DF.Currency + total_commission: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + transaction_date: DF.Date + # end: auto-generated types + def __init__(self, *args, **kwargs): super(SalesOrder, self).__init__(*args, **kwargs) diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.py b/erpnext/selling/doctype/sales_order_item/sales_order_item.py index 83d3f3bc07..25f5b4b0e7 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.py +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.py @@ -7,6 +7,90 @@ from frappe.model.document import Document class SalesOrderItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + additional_notes: DF.Text | None + against_blanket_order: DF.Check + amount: DF.Currency + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + billed_amt: DF.Currency + blanket_order: DF.Link | None + blanket_order_rate: DF.Currency + bom_no: DF.Link | None + brand: DF.Link | None + conversion_factor: DF.Float + customer_item_code: DF.Data | None + delivered_by_supplier: DF.Check + delivered_qty: DF.Float + delivery_date: DF.Date | None + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + ensure_delivery_based_on_produced_serial_no: DF.Check + grant_commission: DF.Check + gross_profit: DF.Currency + image: DF.Attach | None + is_free_item: DF.Check + item_code: DF.Link | None + item_group: DF.Link | None + item_name: DF.Data + item_tax_rate: DF.Code | None + item_tax_template: DF.Link | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + material_request: DF.Link | None + material_request_item: DF.Data | None + net_amount: DF.Currency + net_rate: DF.Currency + ordered_qty: DF.Float + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + picked_qty: DF.Float + planned_qty: DF.Float + prevdoc_docname: DF.Link | None + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + produced_qty: DF.Float + production_plan_qty: DF.Float + projected_qty: DF.Float + purchase_order: DF.Link | None + purchase_order_item: DF.Data | None + qty: DF.Float + quotation_item: DF.Data | None + rate: DF.Currency + rate_with_margin: DF.Currency + reserve_stock: DF.Check + returned_qty: DF.Float + stock_qty: DF.Float + stock_reserved_qty: DF.Float + stock_uom: DF.Link | None + stock_uom_rate: DF.Currency + supplier: DF.Link | None + target_warehouse: DF.Link | None + total_weight: DF.Float + transaction_date: DF.Date | None + uom: DF.Link + valuation_rate: DF.Currency + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + work_order_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py b/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py index 0a07073af0..d156cccff6 100644 --- a/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py +++ b/erpnext/selling/doctype/sales_partner_type/sales_partner_type.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class SalesPartnerType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + sales_partner_type: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/sales_team/sales_team.py b/erpnext/selling/doctype/sales_team/sales_team.py index d3eae3a597..6b4d6d5c9d 100644 --- a/erpnext/selling/doctype/sales_team/sales_team.py +++ b/erpnext/selling/doctype/sales_team/sales_team.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class SalesTeam(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allocated_amount: DF.Currency + allocated_percentage: DF.Float + commission_rate: DF.Data | None + contact_no: DF.Data | None + incentives: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + sales_person: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.py b/erpnext/selling/doctype/selling_settings/selling_settings.py index d977807e7d..24fe909a7a 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.py +++ b/erpnext/selling/doctype/selling_settings/selling_settings.py @@ -11,6 +11,37 @@ from frappe.utils import cint class SellingSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_against_multiple_purchase_orders: DF.Check + allow_multiple_items: DF.Check + allow_negative_rates_for_items: DF.Check + allow_sales_order_creation_for_expired_quotation: DF.Check + blanket_order_allowance: DF.Float + cust_master_name: DF.Literal["Customer Name", "Naming Series", "Auto Name"] + customer_group: DF.Link | None + dn_required: DF.Literal["No", "Yes"] + dont_reserve_sales_order_qty_on_sales_return: DF.Check + editable_bundle_item_rates: DF.Check + editable_price_list_rate: DF.Check + enable_discount_accounting: DF.Check + hide_tax_id: DF.Check + maintain_same_rate_action: DF.Literal["Stop", "Warn"] + maintain_same_sales_rate: DF.Check + role_to_override_stop_action: DF.Link | None + sales_update_frequency: DF.Literal["Monthly", "Each Transaction", "Daily"] + selling_price_list: DF.Link | None + so_required: DF.Literal["No", "Yes"] + territory: DF.Link | None + validate_selling_price: DF.Check + # end: auto-generated types + def on_update(self): self.toggle_hide_tax_id() self.toggle_editable_rate_for_bundle_items() diff --git a/erpnext/selling/doctype/sms_center/sms_center.py b/erpnext/selling/doctype/sms_center/sms_center.py index cdc7397e1e..99f035141c 100644 --- a/erpnext/selling/doctype/sms_center/sms_center.py +++ b/erpnext/selling/doctype/sms_center/sms_center.py @@ -10,6 +10,35 @@ from frappe.utils import cstr class SMSCenter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + branch: DF.Link | None + customer: DF.Link | None + department: DF.Link | None + message: DF.Text + receiver_list: DF.Code | None + sales_partner: DF.Link | None + send_to: DF.Literal[ + "", + "All Contact", + "All Customer Contact", + "All Supplier Contact", + "All Sales Partner Contact", + "All Lead (Open)", + "All Employee (Active)", + "All Sales Person", + ] + supplier: DF.Link | None + total_characters: DF.Int + total_messages: DF.Int + # end: auto-generated types + @frappe.whitelist() def create_receiver_list(self): rec, where_clause = "", "" diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index fd5a2012c7..feb14a8a4c 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -10,6 +10,16 @@ from erpnext.utilities.transaction_base import TransactionBase class AuthorizationControl(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + # end: auto-generated types + def get_appr_user_role(self, det, doctype_name, total, based_on, condition, master_name, company): amt_list, appr_users, appr_roles = [], [], [] users, roles = "", "" diff --git a/erpnext/setup/doctype/authorization_rule/authorization_rule.py b/erpnext/setup/doctype/authorization_rule/authorization_rule.py index 9e64e55ff4..b65a327ef7 100644 --- a/erpnext/setup/doctype/authorization_rule/authorization_rule.py +++ b/erpnext/setup/doctype/authorization_rule/authorization_rule.py @@ -9,6 +9,45 @@ from frappe.utils import cstr, flt class AuthorizationRule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + approving_role: DF.Link | None + approving_user: DF.Link | None + based_on: DF.Literal[ + "", + "Grand Total", + "Average Discount", + "Customerwise Discount", + "Itemwise Discount", + "Item Group wise Discount", + "Not Applicable", + ] + company: DF.Link | None + customer_or_item: DF.Literal["Customer", "Item", "Item Group"] + master_name: DF.DynamicLink | None + system_role: DF.Link | None + system_user: DF.Link | None + to_designation: DF.Link | None + to_emp: DF.Link | None + transaction: DF.Literal[ + "", + "Sales Order", + "Purchase Order", + "Quotation", + "Delivery Note", + "Sales Invoice", + "Purchase Invoice", + "Purchase Receipt", + ] + value: DF.Float + # end: auto-generated types + def check_duplicate_entry(self): exists = frappe.db.sql( """select name, docstatus from `tabAuthorization Rule` diff --git a/erpnext/setup/doctype/branch/branch.py b/erpnext/setup/doctype/branch/branch.py index 133ada05bf..58d17829c6 100644 --- a/erpnext/setup/doctype/branch/branch.py +++ b/erpnext/setup/doctype/branch/branch.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class Branch(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + branch: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/brand/brand.py b/erpnext/setup/doctype/brand/brand.py index 1bb6fc9f16..cf3f474439 100644 --- a/erpnext/setup/doctype/brand/brand.py +++ b/erpnext/setup/doctype/brand/brand.py @@ -9,6 +9,22 @@ from frappe.model.document import Document class Brand(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.item_default.item_default import ItemDefault + + brand: DF.Data + brand_defaults: DF.Table[ItemDefault] + description: DF.Text | None + image: DF.AttachImage | None + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 3413702c5a..0e8ee2dda4 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -19,6 +19,90 @@ from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_ch class Company(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + abbr: DF.Data + accumulated_depreciation_account: DF.Link | None + allow_account_creation_against_child_company: DF.Check + asset_received_but_not_billed: DF.Link | None + auto_err_frequency: DF.Literal["Daily", "Weekly"] + auto_exchange_rate_revaluation: DF.Check + book_advance_payments_in_separate_party_account: DF.Check + capital_work_in_progress_account: DF.Link | None + chart_of_accounts: DF.Literal + company_description: DF.TextEditor | None + company_logo: DF.AttachImage | None + company_name: DF.Data + cost_center: DF.Link | None + country: DF.Link + create_chart_of_accounts_based_on: DF.Literal["", "Standard Template", "Existing Company"] + credit_limit: DF.Currency + date_of_commencement: DF.Date | None + date_of_establishment: DF.Date | None + date_of_incorporation: DF.Date | None + default_advance_paid_account: DF.Link | None + default_advance_received_account: DF.Link | None + default_bank_account: DF.Link | None + default_buying_terms: DF.Link | None + default_cash_account: DF.Link | None + default_currency: DF.Link + default_deferred_expense_account: DF.Link | None + default_deferred_revenue_account: DF.Link | None + default_discount_account: DF.Link | None + default_expense_account: DF.Link | None + default_finance_book: DF.Link | None + default_holiday_list: DF.Link | None + default_in_transit_warehouse: DF.Link | None + default_income_account: DF.Link | None + default_inventory_account: DF.Link | None + default_letter_head: DF.Link | None + default_payable_account: DF.Link | None + default_provisional_account: DF.Link | None + default_receivable_account: DF.Link | None + default_selling_terms: DF.Link | None + default_warehouse_for_sales_return: DF.Link | None + depreciation_cost_center: DF.Link | None + depreciation_expense_account: DF.Link | None + disposal_account: DF.Link | None + domain: DF.Data | None + email: DF.Data | None + enable_perpetual_inventory: DF.Check + enable_provisional_accounting_for_non_stock_items: DF.Check + exception_budget_approver_role: DF.Link | None + exchange_gain_loss_account: DF.Link | None + existing_company: DF.Link | None + fax: DF.Data | None + is_group: DF.Check + lft: DF.Int + monthly_sales_target: DF.Currency + old_parent: DF.Data | None + parent_company: DF.Link | None + payment_terms: DF.Link | None + phone_no: DF.Data | None + registration_details: DF.Code | None + rgt: DF.Int + round_off_account: DF.Link | None + round_off_cost_center: DF.Link | None + sales_monthly_history: DF.SmallText | None + series_for_depreciation_entry: DF.Data | None + stock_adjustment_account: DF.Link | None + stock_received_but_not_billed: DF.Link | None + submit_err_jv: DF.Check + tax_id: DF.Data | None + total_monthly_sales: DF.Currency + transactions_annual_history: DF.Code | None + unrealized_exchange_gain_loss_account: DF.Link | None + unrealized_profit_loss_account: DF.Link | None + website: DF.Data | None + write_off_account: DF.Link | None + # end: auto-generated types + nsm_parent_field = "parent_company" def onload(self): diff --git a/erpnext/setup/doctype/currency_exchange/currency_exchange.py b/erpnext/setup/doctype/currency_exchange/currency_exchange.py index f9f3b3a7dc..735734b9da 100644 --- a/erpnext/setup/doctype/currency_exchange/currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/currency_exchange.py @@ -10,6 +10,22 @@ from frappe.utils import cint, formatdate, get_datetime_str, nowdate class CurrencyExchange(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + date: DF.Date + exchange_rate: DF.Float + for_buying: DF.Check + for_selling: DF.Check + from_currency: DF.Link + to_currency: DF.Link + # end: auto-generated types + def autoname(self): purpose = "" if not self.date: diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index 246cc195e1..89b89addd4 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -8,6 +8,31 @@ from frappe.utils.nestedset import NestedSet, get_root_of class CustomerGroup(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.party_account.party_account import PartyAccount + from erpnext.selling.doctype.customer_credit_limit.customer_credit_limit import ( + CustomerCreditLimit, + ) + + accounts: DF.Table[PartyAccount] + credit_limits: DF.Table[CustomerCreditLimit] + customer_group_name: DF.Data + default_price_list: DF.Link | None + is_group: DF.Check + lft: DF.Int + old_parent: DF.Link | None + parent_customer_group: DF.Link | None + payment_terms: DF.Link | None + rgt: DF.Int + # end: auto-generated types + nsm_parent_field = "parent_customer_group" def validate(self): diff --git a/erpnext/setup/doctype/department/department.py b/erpnext/setup/doctype/department/department.py index 1745178574..6b090f8af7 100644 --- a/erpnext/setup/doctype/department/department.py +++ b/erpnext/setup/doctype/department/department.py @@ -9,6 +9,24 @@ from erpnext.utilities.transaction_base import delete_events class Department(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + company: DF.Link + department_name: DF.Data + disabled: DF.Check + is_group: DF.Check + lft: DF.Int + old_parent: DF.Data | None + parent_department: DF.Link | None + rgt: DF.Int + # end: auto-generated types + nsm_parent_field = "parent_department" def autoname(self): diff --git a/erpnext/setup/doctype/designation/designation.py b/erpnext/setup/doctype/designation/designation.py index d7be55cad6..9ba9e80584 100644 --- a/erpnext/setup/doctype/designation/designation.py +++ b/erpnext/setup/doctype/designation/designation.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class Designation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.Text | None + designation_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/driver/driver.py b/erpnext/setup/doctype/driver/driver.py index 26981890ed..4faa8e3fdc 100644 --- a/erpnext/setup/doctype/driver/driver.py +++ b/erpnext/setup/doctype/driver/driver.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class Driver(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.driving_license_category.driving_license_category import ( + DrivingLicenseCategory, + ) + + address: DF.Link | None + cell_number: DF.Data | None + driving_license_category: DF.Table[DrivingLicenseCategory] + employee: DF.Link | None + expiry_date: DF.Date | None + full_name: DF.Data + issuing_date: DF.Date | None + license_number: DF.Data | None + naming_series: DF.Literal["HR-DRI-.YYYY.-"] + status: DF.Literal["Active", "Suspended", "Left"] + transporter: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/driving_license_category/driving_license_category.py b/erpnext/setup/doctype/driving_license_category/driving_license_category.py index a1a6d55cb4..c06ce7dadb 100644 --- a/erpnext/setup/doctype/driving_license_category/driving_license_category.py +++ b/erpnext/setup/doctype/driving_license_category/driving_license_category.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class DrivingLicenseCategory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.Data | None + expiry_date: DF.Date | None + issuing_date: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 6ed44fff68..53b353dd8a 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -30,6 +30,50 @@ from frappe.model.document import Document class EmailDigest(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.email_digest_recipient.email_digest_recipient import ( + EmailDigestRecipient, + ) + + add_quote: DF.Check + bank_balance: DF.Check + calendar_events: DF.Check + company: DF.Link + credit_balance: DF.Check + enabled: DF.Check + expense_year_to_date: DF.Check + expenses_booked: DF.Check + frequency: DF.Literal["Daily", "Weekly", "Monthly"] + income: DF.Check + income_year_to_date: DF.Check + invoiced_amount: DF.Check + issue: DF.Check + new_quotations: DF.Check + next_send: DF.Data | None + notifications: DF.Check + payables: DF.Check + pending_quotations: DF.Check + project: DF.Check + purchase_invoice: DF.Check + purchase_order: DF.Check + purchase_orders_items_overdue: DF.Check + purchase_orders_to_bill: DF.Check + purchase_orders_to_receive: DF.Check + recipients: DF.TableMultiSelect[EmailDigestRecipient] + sales_invoice: DF.Check + sales_order: DF.Check + sales_orders_to_bill: DF.Check + sales_orders_to_deliver: DF.Check + todo_list: DF.Check + # end: auto-generated types + def __init__(self, *args, **kwargs): super(EmailDigest, self).__init__(*args, **kwargs) diff --git a/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py b/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py index 06bf6273c0..3316ca03c5 100644 --- a/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py +++ b/erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class EmailDigestRecipient(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + recipient: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/employee_education/employee_education.py b/erpnext/setup/doctype/employee_education/employee_education.py index ded583bf01..8ef77f5ab6 100644 --- a/erpnext/setup/doctype/employee_education/employee_education.py +++ b/erpnext/setup/doctype/employee_education/employee_education.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class EmployeeEducation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + class_per: DF.Data | None + level: DF.Literal["Graduate", "Post Graduate", "Under Graduate"] + maj_opt_subj: DF.Text | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qualification: DF.Data | None + school_univ: DF.SmallText | None + year_of_passing: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/employee_external_work_history/employee_external_work_history.py b/erpnext/setup/doctype/employee_external_work_history/employee_external_work_history.py index d594fbf0f0..96b9064be0 100644 --- a/erpnext/setup/doctype/employee_external_work_history/employee_external_work_history.py +++ b/erpnext/setup/doctype/employee_external_work_history/employee_external_work_history.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class EmployeeExternalWorkHistory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + address: DF.SmallText | None + company_name: DF.Data | None + contact: DF.Data | None + designation: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + salary: DF.Currency + total_experience: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/employee_group/employee_group.py b/erpnext/setup/doctype/employee_group/employee_group.py index c4ce083c94..1891328c1c 100644 --- a/erpnext/setup/doctype/employee_group/employee_group.py +++ b/erpnext/setup/doctype/employee_group/employee_group.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class EmployeeGroup(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.employee_group_table.employee_group_table import EmployeeGroupTable + + employee_group_name: DF.Data + employee_list: DF.Table[EmployeeGroupTable] + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/employee_group_table/employee_group_table.py b/erpnext/setup/doctype/employee_group_table/employee_group_table.py index adf6ca2668..3775e0ce14 100644 --- a/erpnext/setup/doctype/employee_group_table/employee_group_table.py +++ b/erpnext/setup/doctype/employee_group_table/employee_group_table.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class EmployeeGroupTable(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + employee: DF.Link | None + employee_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + user_id: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/employee_internal_work_history/employee_internal_work_history.py b/erpnext/setup/doctype/employee_internal_work_history/employee_internal_work_history.py index 6225de6014..9f62684f33 100644 --- a/erpnext/setup/doctype/employee_internal_work_history/employee_internal_work_history.py +++ b/erpnext/setup/doctype/employee_internal_work_history/employee_internal_work_history.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class EmployeeInternalWorkHistory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + branch: DF.Link | None + department: DF.Link | None + designation: DF.Link | None + from_date: DF.Date | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + to_date: DF.Date | None + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py index fc80483e8e..4b7f642747 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/global_defaults.py @@ -23,6 +23,24 @@ from frappe.model.document import Document class GlobalDefaults(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + country: DF.Link | None + default_company: DF.Link | None + default_currency: DF.Link + default_distance_unit: DF.Link | None + demo_company: DF.Link | None + disable_in_words: DF.Check + disable_rounded_total: DF.Check + hide_currency_symbol: DF.Literal["", "No", "Yes"] + # end: auto-generated types + def on_update(self): """update defaults""" for key in keydict: diff --git a/erpnext/setup/doctype/holiday/holiday.py b/erpnext/setup/doctype/holiday/holiday.py index 85ca0b74fc..b226203216 100644 --- a/erpnext/setup/doctype/holiday/holiday.py +++ b/erpnext/setup/doctype/holiday/holiday.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class Holiday(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor + holiday_date: DF.Date + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + weekly_off: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/holiday_list/holiday_list.py b/erpnext/setup/doctype/holiday_list/holiday_list.py index df5b40762c..1afee41ac3 100644 --- a/erpnext/setup/doctype/holiday_list/holiday_list.py +++ b/erpnext/setup/doctype/holiday_list/holiday_list.py @@ -16,6 +16,29 @@ class OverlapError(frappe.ValidationError): class HolidayList(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.holiday.holiday import Holiday + + color: DF.Color | None + country: DF.Autocomplete | None + from_date: DF.Date + holiday_list_name: DF.Data + holidays: DF.Table[Holiday] + subdivision: DF.Autocomplete | None + to_date: DF.Date + total_holidays: DF.Int + weekly_off: DF.Literal[ + "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ] + # end: auto-generated types + def validate(self): self.validate_days() self.total_holidays = len(self.holidays) diff --git a/erpnext/setup/doctype/incoterm/incoterm.py b/erpnext/setup/doctype/incoterm/incoterm.py index 7e2e622c24..17305e9fde 100644 --- a/erpnext/setup/doctype/incoterm/incoterm.py +++ b/erpnext/setup/doctype/incoterm/incoterm.py @@ -6,6 +6,19 @@ from frappe.model.document import Document class Incoterm(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + code: DF.Data + description: DF.LongText | None + title: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index fe7a241dc4..fd65ab6417 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -9,6 +9,28 @@ from frappe.utils.nestedset import NestedSet class ItemGroup(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.item_default.item_default import ItemDefault + from erpnext.stock.doctype.item_tax.item_tax import ItemTax + + image: DF.AttachImage | None + is_group: DF.Check + item_group_defaults: DF.Table[ItemDefault] + item_group_name: DF.Data + lft: DF.Int + old_parent: DF.Link | None + parent_item_group: DF.Link | None + rgt: DF.Int + taxes: DF.Table[ItemTax] + # end: auto-generated types + def validate(self): if not self.parent_item_group and not frappe.flags.in_test: if frappe.db.exists("Item Group", _("All Item Groups")): diff --git a/erpnext/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py index cf7cba8452..76b985be6c 100644 --- a/erpnext/setup/doctype/party_type/party_type.py +++ b/erpnext/setup/doctype/party_type/party_type.py @@ -7,6 +7,18 @@ from frappe.model.document import Document class PartyType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_type: DF.Literal["Payable", "Receivable"] + party_type: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/print_heading/print_heading.py b/erpnext/setup/doctype/print_heading/print_heading.py index 3a2f15f4b2..8e1a8fba2f 100644 --- a/erpnext/setup/doctype/print_heading/print_heading.py +++ b/erpnext/setup/doctype/print_heading/print_heading.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class PrintHeading(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + print_heading: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py index 651705c6e5..fb9730e3d7 100644 --- a/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py +++ b/erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class QuotationLostReason(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + order_lost_reason: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py index dda64e9c62..87f700b36c 100644 --- a/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py +++ b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class QuotationLostReasonDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + lost_reason: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.py b/erpnext/setup/doctype/sales_partner/sales_partner.py index c3136715fe..1047360b84 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/sales_partner.py @@ -9,6 +9,30 @@ from frappe.website.website_generator import WebsiteGenerator class SalesPartner(WebsiteGenerator): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.target_detail.target_detail import TargetDetail + + commission_rate: DF.Float + description: DF.TextEditor | None + introduction: DF.Text | None + logo: DF.Attach | None + partner_name: DF.Data + partner_type: DF.Link | None + partner_website: DF.Data | None + referral_code: DF.Data | None + route: DF.Data | None + show_in_website: DF.Check + targets: DF.Table[TargetDetail] + territory: DF.Link + # end: auto-generated types + website = frappe._dict( page_title_field="partner_name", condition_field="show_in_website", diff --git a/erpnext/setup/doctype/sales_person/sales_person.py b/erpnext/setup/doctype/sales_person/sales_person.py index beff7f5374..c2615d37c2 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.py +++ b/erpnext/setup/doctype/sales_person/sales_person.py @@ -16,6 +16,29 @@ from erpnext import get_default_currency class SalesPerson(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.target_detail.target_detail import TargetDetail + + commission_rate: DF.Data | None + department: DF.Link | None + employee: DF.Link | None + enabled: DF.Check + is_group: DF.Check + lft: DF.Int + old_parent: DF.Data | None + parent_sales_person: DF.Link | None + rgt: DF.Int + sales_person_name: DF.Data + targets: DF.Table[TargetDetail] + # end: auto-generated types + nsm_parent_field = "parent_sales_person" def validate(self): diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.py b/erpnext/setup/doctype/supplier_group/supplier_group.py index 9d2b733b74..b639b96250 100644 --- a/erpnext/setup/doctype/supplier_group/supplier_group.py +++ b/erpnext/setup/doctype/supplier_group/supplier_group.py @@ -7,6 +7,26 @@ from frappe.utils.nestedset import NestedSet, get_root_of class SupplierGroup(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.party_account.party_account import PartyAccount + + accounts: DF.Table[PartyAccount] + is_group: DF.Check + lft: DF.Int + old_parent: DF.Link | None + parent_supplier_group: DF.Link | None + payment_terms: DF.Link | None + rgt: DF.Int + supplier_group_name: DF.Data + # end: auto-generated types + nsm_parent_field = "parent_supplier_group" def validate(self): diff --git a/erpnext/setup/doctype/target_detail/target_detail.py b/erpnext/setup/doctype/target_detail/target_detail.py index e27f5b6020..86d94b2ad4 100644 --- a/erpnext/setup/doctype/target_detail/target_detail.py +++ b/erpnext/setup/doctype/target_detail/target_detail.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class TargetDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + distribution_id: DF.Link + fiscal_year: DF.Link + item_group: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + target_amount: DF.Float + target_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py b/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py index 344f6c6a19..73b5919f4d 100644 --- a/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py +++ b/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py @@ -12,6 +12,21 @@ from frappe.utils.jinja import validate_template class TermsandConditions(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + buying: DF.Check + disabled: DF.Check + selling: DF.Check + terms: DF.TextEditor | None + title: DF.Data + # end: auto-generated types + def validate(self): if self.terms: validate_template(self.terms) diff --git a/erpnext/setup/doctype/territory/territory.py b/erpnext/setup/doctype/territory/territory.py index 9bb5569de5..1cc3f6272d 100644 --- a/erpnext/setup/doctype/territory/territory.py +++ b/erpnext/setup/doctype/territory/territory.py @@ -9,6 +9,26 @@ from frappe.utils.nestedset import NestedSet, get_root_of class Territory(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.target_detail.target_detail import TargetDetail + + is_group: DF.Check + lft: DF.Int + old_parent: DF.Link | None + parent_territory: DF.Link | None + rgt: DF.Int + targets: DF.Table[TargetDetail] + territory_manager: DF.Link | None + territory_name: DF.Data + # end: auto-generated types + nsm_parent_field = "parent_territory" def validate(self): diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py index d266285b29..7182201517 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py @@ -10,6 +10,25 @@ from frappe.utils import cint, create_batch class TransactionDeletionRecord(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.setup.doctype.transaction_deletion_record_item.transaction_deletion_record_item import ( + TransactionDeletionRecordItem, + ) + + amended_from: DF.Link | None + company: DF.Link + doctypes: DF.Table[TransactionDeletionRecordItem] + doctypes_to_be_ignored: DF.Table[TransactionDeletionRecordItem] + status: DF.Literal["Draft", "Completed"] + # end: auto-generated types + def __init__(self, *args, **kwargs): super(TransactionDeletionRecord, self).__init__(*args, **kwargs) self.batch_size = 5000 diff --git a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py index 92ca8a2ac7..f154cdb247 100644 --- a/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py +++ b/erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class TransactionDeletionRecordItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + doctype_name: DF.Link + no_of_docs: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/uom/uom.py b/erpnext/setup/doctype/uom/uom.py index ddb512a085..0e674c1fae 100644 --- a/erpnext/setup/doctype/uom/uom.py +++ b/erpnext/setup/doctype/uom/uom.py @@ -6,4 +6,17 @@ from frappe.model.document import Document class UOM(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + enabled: DF.Check + must_be_whole_number: DF.Check + uom_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py b/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py index 12642fe7e2..00d2000947 100644 --- a/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py +++ b/erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class UOMConversionFactor(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + category: DF.Link + from_uom: DF.Link + to_uom: DF.Link + value: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/setup/doctype/vehicle/vehicle.py b/erpnext/setup/doctype/vehicle/vehicle.py index 6a1b75ca0b..4a6146b5e1 100644 --- a/erpnext/setup/doctype/vehicle/vehicle.py +++ b/erpnext/setup/doctype/vehicle/vehicle.py @@ -9,6 +9,36 @@ from frappe.utils import getdate class Vehicle(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + acquisition_date: DF.Date | None + amended_from: DF.Link | None + carbon_check_date: DF.Date | None + chassis_no: DF.Data | None + color: DF.Data | None + doors: DF.Int + employee: DF.Link | None + end_date: DF.Date | None + fuel_type: DF.Literal["Petrol", "Diesel", "Natural Gas", "Electric"] + insurance_company: DF.Data | None + last_odometer: DF.Int + license_plate: DF.Data + location: DF.Data | None + make: DF.Data + model: DF.Data + policy_no: DF.Data | None + start_date: DF.Date | None + uom: DF.Link + vehicle_value: DF.Currency + wheels: DF.Int + # end: auto-generated types + def validate(self): if getdate(self.start_date) > getdate(self.end_date): frappe.throw(_("Insurance Start date should be less than Insurance End date")) diff --git a/erpnext/setup/doctype/website_item_group/website_item_group.py b/erpnext/setup/doctype/website_item_group/website_item_group.py index 87fcb98453..3d2b6e8e34 100644 --- a/erpnext/setup/doctype/website_item_group/website_item_group.py +++ b/erpnext/setup/doctype/website_item_group/website_item_group.py @@ -8,4 +8,18 @@ from frappe.model.document import Document class WebsiteItemGroup(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_group: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 5919d7c7f8..7b23f9ec01 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -87,6 +87,33 @@ def get_batch_naming_series(): class Batch(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + batch_id: DF.Data + batch_qty: DF.Float + description: DF.SmallText | None + disabled: DF.Check + expiry_date: DF.Date | None + image: DF.AttachImage | None + item: DF.Link + item_name: DF.Data | None + manufacturing_date: DF.Date | None + parent_batch: DF.Link | None + produced_qty: DF.Float + qty_to_produce: DF.Float + reference_doctype: DF.Link | None + reference_name: DF.DynamicLink | None + stock_uom: DF.Link | None + supplier: DF.Link | None + use_batchwise_valuation: DF.Check + # end: auto-generated types + def autoname(self): """Generate random ID for batch if not specified""" diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index 8b2e5cf9ec..93109858a6 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -10,6 +10,31 @@ from frappe.utils import flt class Bin(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + indented_qty: DF.Float + item_code: DF.Link + ordered_qty: DF.Float + planned_qty: DF.Float + projected_qty: DF.Float + reserved_qty: DF.Float + reserved_qty_for_production: DF.Float + reserved_qty_for_production_plan: DF.Float + reserved_qty_for_sub_contract: DF.Float + reserved_stock: DF.Float + stock_uom: DF.Link | None + stock_value: DF.Float + valuation_rate: DF.Float + warehouse: DF.Link + # end: auto-generated types + def before_save(self): if self.get("__islocal") or not self.stock_uom: self.stock_uom = frappe.get_cached_value("Item", self.item_code, "stock_uom") diff --git a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py index b0499bfe86..7db8522f63 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py @@ -15,6 +15,27 @@ from erpnext.stock.report.stock_balance.stock_balance import execute class ClosingStockBalance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + company: DF.Link | None + from_date: DF.Date | None + include_uom: DF.Link | None + item_code: DF.Link | None + item_group: DF.Link | None + naming_series: DF.Literal["CBAL-.#####"] + status: DF.Literal["Draft", "Queued", "In Progress", "Completed", "Failed", "Canceled"] + to_date: DF.Date | None + warehouse: DF.Link | None + warehouse_type: DF.Link | None + # end: auto-generated types + def before_save(self): self.set_status() diff --git a/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py b/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py index b52acb1ad6..d0328292e2 100644 --- a/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py +++ b/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class CustomsTariffNumber(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.Data | None + tariff_number: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index f240136e9c..e44736b56e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -18,6 +18,128 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class DeliveryNote(SellingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, + ) + from erpnext.selling.doctype.sales_team.sales_team import SalesTeam + from erpnext.stock.doctype.delivery_note_item.delivery_note_item import DeliveryNoteItem + from erpnext.stock.doctype.packed_item.packed_item import PackedItem + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + amended_from: DF.Link | None + amount_eligible_for_commission: DF.Currency + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + campaign: DF.Link | None + commission_rate: DF.Float + company: DF.Link + company_address: DF.Link | None + company_address_display: DF.SmallText | None + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + currency: DF.Link + customer: DF.Link + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + disable_rounded_total: DF.Check + discount_amount: DF.Currency + dispatch_address: DF.SmallText | None + dispatch_address_name: DF.Link | None + driver: DF.Link | None + driver_name: DF.Data | None + excise_page: DF.Data | None + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + installation_status: DF.Literal + instructions: DF.Text | None + inter_company_reference: DF.Link | None + is_internal_customer: DF.Check + is_return: DF.Check + issue_credit_note: DF.Check + items: DF.Table[DeliveryNoteItem] + language: DF.Data | None + letter_head: DF.Link | None + lr_date: DF.Date | None + lr_no: DF.Data | None + named_place: DF.Data | None + naming_series: DF.Literal["MAT-DN-.YYYY.-", "MAT-DN-RET-.YYYY.-"] + net_total: DF.Currency + other_charges_calculation: DF.LongText | None + packed_items: DF.Table[PackedItem] + per_billed: DF.Percent + per_installed: DF.Percent + per_returned: DF.Percent + pick_list: DF.Link | None + plc_conversion_rate: DF.Float + po_date: DF.Date | None + po_no: DF.SmallText | None + posting_date: DF.Date + posting_time: DF.Time + price_list_currency: DF.Link + pricing_rules: DF.Table[PricingRuleDetail] + print_without_amount: DF.Check + project: DF.Link | None + represents_company: DF.Link | None + return_against: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + sales_partner: DF.Link | None + sales_team: DF.Table[SalesTeam] + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + selling_price_list: DF.Link + set_posting_time: DF.Check + set_target_warehouse: DF.Link | None + set_warehouse: DF.Link | None + shipping_address: DF.SmallText | None + shipping_address_name: DF.Link | None + shipping_rule: DF.Link | None + source: DF.Link | None + status: DF.Literal["", "Draft", "To Bill", "Completed", "Return Issued", "Cancelled", "Closed"] + tax_category: DF.Link | None + tax_id: DF.Data | None + taxes: DF.Table[SalesTaxesandCharges] + taxes_and_charges: DF.Link | None + tc_name: DF.Link | None + terms: DF.TextEditor | None + territory: DF.Link | None + title: DF.Data | None + total: DF.Currency + total_commission: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + transporter: DF.Link | None + transporter_name: DF.Data | None + vehicle_no: DF.Data | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(DeliveryNote, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py index cd0d7251ae..c11c4103e5 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.py @@ -6,4 +6,85 @@ from frappe.model.document import Document class DeliveryNoteItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_batch_qty: DF.Float + actual_qty: DF.Float + against_sales_invoice: DF.Link | None + against_sales_order: DF.Link | None + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + barcode: DF.Data | None + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + batch_no: DF.Link | None + billed_amt: DF.Currency + brand: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + customer_item_code: DF.Data | None + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Float + dn_detail: DF.Data | None + expense_account: DF.Link | None + grant_commission: DF.Check + has_item_scanned: DF.Check + image: DF.Attach | None + incoming_rate: DF.Currency + installed_qty: DF.Float + is_free_item: DF.Check + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data + item_tax_rate: DF.SmallText | None + item_tax_template: DF.Link | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + material_request: DF.Link | None + material_request_item: DF.Data | None + net_amount: DF.Currency + net_rate: DF.Currency + packed_qty: DF.Float + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + pick_list_item: DF.Data | None + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + project: DF.Link | None + purchase_order: DF.Link | None + purchase_order_item: DF.Data | None + qty: DF.Float + quality_inspection: DF.Link | None + rate: DF.Currency + rate_with_margin: DF.Currency + received_qty: DF.Float + returned_qty: DF.Float + serial_and_batch_bundle: DF.Link | None + serial_no: DF.Text | None + si_detail: DF.Data | None + so_detail: DF.Data | None + stock_qty: DF.Float + stock_uom: DF.Link + stock_uom_rate: DF.Currency + target_warehouse: DF.Link | None + total_weight: DF.Float + uom: DF.Link + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/delivery_settings/delivery_settings.py b/erpnext/stock/doctype/delivery_settings/delivery_settings.py index ab1ca80e39..776fbcbd1b 100644 --- a/erpnext/stock/doctype/delivery_settings/delivery_settings.py +++ b/erpnext/stock/doctype/delivery_settings/delivery_settings.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class DeliverySettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + dispatch_attachment: DF.Link | None + dispatch_template: DF.Link | None + send_with_attachment: DF.Check + stop_delay: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.py b/erpnext/stock/doctype/delivery_stop/delivery_stop.py index 9da8bfa986..fbfbe94264 100644 --- a/erpnext/stock/doctype/delivery_stop/delivery_stop.py +++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.py @@ -6,4 +6,33 @@ from frappe.model.document import Document class DeliveryStop(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + address: DF.Link + contact: DF.Link | None + customer: DF.Link | None + customer_address: DF.SmallText | None + customer_contact: DF.SmallText | None + delivery_note: DF.Link | None + details: DF.TextEditor | None + distance: DF.Float + email_sent_to: DF.Data | None + estimated_arrival: DF.Datetime | None + grand_total: DF.Currency + lat: DF.Float + lng: DF.Float + locked: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + uom: DF.Link | None + visited: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index c531a8769c..cb9fc5b087 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -12,6 +12,33 @@ from frappe.utils import cint, get_datetime, get_link_to_form class DeliveryTrip(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.delivery_stop.delivery_stop import DeliveryStop + + amended_from: DF.Link | None + company: DF.Link + delivery_stops: DF.Table[DeliveryStop] + departure_time: DF.Datetime + driver: DF.Link | None + driver_address: DF.Link | None + driver_email: DF.Data | None + driver_name: DF.Data | None + email_notification_sent: DF.Check + employee: DF.Link | None + naming_series: DF.Literal["MAT-DT-.YYYY.-"] + status: DF.Literal["Draft", "Scheduled", "In Transit", "Completed", "Cancelled"] + total_distance: DF.Float + uom: DF.Link | None + vehicle: DF.Link + # end: auto-generated types + def __init__(self, *args, **kwargs): super(DeliveryTrip, self).__init__(*args, **kwargs) diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index 257d18fc33..60624d4164 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -20,6 +20,30 @@ class CanNotBeDefaultDimension(frappe.ValidationError): class InventoryDimension(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + apply_to_all_doctypes: DF.Check + condition: DF.Code | None + dimension_name: DF.Data + disabled: DF.Check + document_type: DF.Link | None + fetch_from_parent: DF.Literal + istable: DF.Check + mandatory_depends_on: DF.SmallText | None + reference_document: DF.Link + reqd: DF.Check + source_fieldname: DF.Data | None + target_fieldname: DF.Data | None + type_of_transaction: DF.Literal["", "Inward", "Outward", "Both"] + validate_negative_stock: DF.Check + # end: auto-generated types + def onload(self): if not self.is_new() and frappe.db.has_column("Stock Ledger Entry", self.target_fieldname): self.set_onload("has_stock_ledger", self.has_stock_ledger()) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index cb34497f28..2d9e11ab84 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -52,6 +52,106 @@ class DataValidationError(frappe.ValidationError): class Item(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.item_barcode.item_barcode import ItemBarcode + from erpnext.stock.doctype.item_customer_detail.item_customer_detail import ItemCustomerDetail + from erpnext.stock.doctype.item_default.item_default import ItemDefault + from erpnext.stock.doctype.item_reorder.item_reorder import ItemReorder + from erpnext.stock.doctype.item_supplier.item_supplier import ItemSupplier + from erpnext.stock.doctype.item_tax.item_tax import ItemTax + from erpnext.stock.doctype.item_variant_attribute.item_variant_attribute import ( + ItemVariantAttribute, + ) + from erpnext.stock.doctype.uom_conversion_detail.uom_conversion_detail import UOMConversionDetail + + allow_alternative_item: DF.Check + allow_negative_stock: DF.Check + asset_category: DF.Link | None + asset_naming_series: DF.Literal + attributes: DF.Table[ItemVariantAttribute] + auto_create_assets: DF.Check + barcodes: DF.Table[ItemBarcode] + batch_number_series: DF.Data | None + brand: DF.Link | None + country_of_origin: DF.Link | None + create_new_batch: DF.Check + customer: DF.Link | None + customer_code: DF.SmallText | None + customer_items: DF.Table[ItemCustomerDetail] + customs_tariff_number: DF.Link | None + default_bom: DF.Link | None + default_item_manufacturer: DF.Link | None + default_manufacturer_part_no: DF.Data | None + default_material_request_type: DF.Literal[ + "Purchase", "Material Transfer", "Material Issue", "Manufacture", "Customer Provided" + ] + delivered_by_supplier: DF.Check + description: DF.TextEditor | None + disabled: DF.Check + enable_deferred_expense: DF.Check + enable_deferred_revenue: DF.Check + end_of_life: DF.Date | None + grant_commission: DF.Check + has_batch_no: DF.Check + has_expiry_date: DF.Check + has_serial_no: DF.Check + has_variants: DF.Check + image: DF.AttachImage | None + include_item_in_manufacturing: DF.Check + inspection_required_before_delivery: DF.Check + inspection_required_before_purchase: DF.Check + is_customer_provided_item: DF.Check + is_fixed_asset: DF.Check + is_grouped_asset: DF.Check + is_purchase_item: DF.Check + is_sales_item: DF.Check + is_stock_item: DF.Check + is_sub_contracted_item: DF.Check + item_code: DF.Data + item_defaults: DF.Table[ItemDefault] + item_group: DF.Link + item_name: DF.Data | None + last_purchase_rate: DF.Float + lead_time_days: DF.Int + max_discount: DF.Float + min_order_qty: DF.Float + naming_series: DF.Literal["STO-ITEM-.YYYY.-"] + no_of_months: DF.Int + no_of_months_exp: DF.Int + opening_stock: DF.Float + over_billing_allowance: DF.Float + over_delivery_receipt_allowance: DF.Float + purchase_uom: DF.Link | None + quality_inspection_template: DF.Link | None + reorder_levels: DF.Table[ItemReorder] + retain_sample: DF.Check + safety_stock: DF.Float + sales_uom: DF.Link | None + sample_quantity: DF.Int + serial_no_series: DF.Data | None + shelf_life_in_days: DF.Int + standard_rate: DF.Currency + stock_uom: DF.Link + supplier_items: DF.Table[ItemSupplier] + taxes: DF.Table[ItemTax] + total_projected_qty: DF.Float + uoms: DF.Table[UOMConversionDetail] + valuation_method: DF.Literal["", "FIFO", "Moving Average", "LIFO"] + valuation_rate: DF.Currency + variant_based_on: DF.Literal["Item Attribute", "Manufacturer"] + variant_of: DF.Link | None + warranty_period: DF.Data | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + # end: auto-generated types + def onload(self): self.set_onload("stock_exists", self.stock_ledger_created()) self.set_onload("asset_naming_series", get_asset_naming_series()) diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py index 0c24d3c780..83bee9c321 100644 --- a/erpnext/stock/doctype/item_alternative/item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/item_alternative.py @@ -8,6 +8,21 @@ from frappe.model.document import Document class ItemAlternative(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + alternative_item_code: DF.Link | None + alternative_item_name: DF.ReadOnly | None + item_code: DF.Link | None + item_name: DF.ReadOnly | None + two_way: DF.Check + # end: auto-generated types + def validate(self): self.has_alternative_item() self.validate_alternative_item() diff --git a/erpnext/stock/doctype/item_attribute/item_attribute.py b/erpnext/stock/doctype/item_attribute/item_attribute.py index ac4c313e28..7b341b2248 100644 --- a/erpnext/stock/doctype/item_attribute/item_attribute.py +++ b/erpnext/stock/doctype/item_attribute/item_attribute.py @@ -19,6 +19,24 @@ class ItemAttributeIncrementError(frappe.ValidationError): class ItemAttribute(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.item_attribute_value.item_attribute_value import ItemAttributeValue + + attribute_name: DF.Data + from_range: DF.Float + increment: DF.Float + item_attribute_values: DF.Table[ItemAttributeValue] + numeric_values: DF.Check + to_range: DF.Float + # end: auto-generated types + def __setup__(self): self.flags.ignore_these_exceptions_in_test = [InvalidItemAttributeValueError] diff --git a/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py b/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py index bc6fb4f399..0ddc86752d 100644 --- a/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py +++ b/erpnext/stock/doctype/item_attribute_value/item_attribute_value.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ItemAttributeValue(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + abbr: DF.Data + attribute_value: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.py b/erpnext/stock/doctype/item_barcode/item_barcode.py index c2c042143e..e38b95bad5 100644 --- a/erpnext/stock/doctype/item_barcode/item_barcode.py +++ b/erpnext/stock/doctype/item_barcode/item_barcode.py @@ -6,4 +6,36 @@ from frappe.model.document import Document class ItemBarcode(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + barcode: DF.Data + barcode_type: DF.Literal[ + "", + "EAN", + "UPC-A", + "CODE-39", + "EAN-12", + "EAN-8", + "GS1", + "GTIN", + "ISBN", + "ISBN-10", + "ISBN-13", + "ISSN", + "JAN", + "PZN", + "UPC", + ] + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py b/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py index ba81b443bb..b0978e388e 100644 --- a/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py +++ b/erpnext/stock/doctype/item_customer_detail/item_customer_detail.py @@ -6,4 +6,20 @@ from frappe.model.document import Document class ItemCustomerDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + customer_group: DF.Link | None + customer_name: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + ref_code: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_default/item_default.py b/erpnext/stock/doctype/item_default/item_default.py index 8a9693e3a6..10dae2bc1c 100644 --- a/erpnext/stock/doctype/item_default/item_default.py +++ b/erpnext/stock/doctype/item_default/item_default.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class ItemDefault(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + buying_cost_center: DF.Link | None + company: DF.Link + default_discount_account: DF.Link | None + default_price_list: DF.Link | None + default_provisional_account: DF.Link | None + default_supplier: DF.Link | None + default_warehouse: DF.Link | None + deferred_expense_account: DF.Link | None + deferred_revenue_account: DF.Link | None + expense_account: DF.Link | None + income_account: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + selling_cost_center: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py index b65ba98a8b..ed004d523e 100644 --- a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py +++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py @@ -8,6 +8,22 @@ from frappe.model.document import Document class ItemManufacturer(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + is_default: DF.Check + item_code: DF.Link + item_name: DF.Data | None + manufacturer: DF.Link + manufacturer_part_no: DF.Data + # end: auto-generated types + def validate(self): self.validate_duplicate_entry() self.manage_default_item_manufacturer() diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py index 54d1ae634f..89a130a6bf 100644 --- a/erpnext/stock/doctype/item_price/item_price.py +++ b/erpnext/stock/doctype/item_price/item_price.py @@ -15,6 +15,35 @@ class ItemPriceDuplicateItem(frappe.ValidationError): class ItemPrice(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + batch_no: DF.Link | None + brand: DF.Link | None + buying: DF.Check + currency: DF.Link | None + customer: DF.Link | None + item_code: DF.Link + item_description: DF.Text | None + item_name: DF.Data | None + lead_time_days: DF.Int + note: DF.Text | None + packing_unit: DF.Int + price_list: DF.Link + price_list_rate: DF.Currency + reference: DF.Data | None + selling: DF.Check + supplier: DF.Link | None + uom: DF.Link | None + valid_from: DF.Date | None + valid_upto: DF.Date | None + # end: auto-generated types + def validate(self): self.validate_item() self.validate_dates() diff --git a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py index 6cadb9973c..b6ade8afae 100644 --- a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py +++ b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class ItemQualityInspectionParameter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + acceptance_formula: DF.Code | None + formula_based_criteria: DF.Check + max_value: DF.Float + min_value: DF.Float + numeric: DF.Check + parameter_group: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + specification: DF.Link + value: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_reorder/item_reorder.py b/erpnext/stock/doctype/item_reorder/item_reorder.py index c3cc69b320..94f92f2c09 100644 --- a/erpnext/stock/doctype/item_reorder/item_reorder.py +++ b/erpnext/stock/doctype/item_reorder/item_reorder.py @@ -8,4 +8,22 @@ from frappe.model.document import Document class ItemReorder(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + material_request_type: DF.Literal["Purchase", "Transfer", "Material Issue", "Manufacture"] + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + warehouse: DF.Link + warehouse_group: DF.Link | None + warehouse_reorder_level: DF.Float + warehouse_reorder_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_supplier/item_supplier.py b/erpnext/stock/doctype/item_supplier/item_supplier.py index 84f5556661..955aea3a42 100644 --- a/erpnext/stock/doctype/item_supplier/item_supplier.py +++ b/erpnext/stock/doctype/item_supplier/item_supplier.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ItemSupplier(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + supplier: DF.Link + supplier_part_no: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_tax/item_tax.py b/erpnext/stock/doctype/item_tax/item_tax.py index aa827198a9..4b8adb9b96 100644 --- a/erpnext/stock/doctype/item_tax/item_tax.py +++ b/erpnext/stock/doctype/item_tax/item_tax.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class ItemTax(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_tax_template: DF.Link + maximum_net_rate: DF.Float + minimum_net_rate: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + tax_category: DF.Link | None + valid_from: DF.Date | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_variant/item_variant.py b/erpnext/stock/doctype/item_variant/item_variant.py index f1580fcba9..94db29e628 100644 --- a/erpnext/stock/doctype/item_variant/item_variant.py +++ b/erpnext/stock/doctype/item_variant/item_variant.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class ItemVariant(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + item_attribute: DF.Link + item_attribute_value: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py b/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py index 76b88b85c0..756b742176 100644 --- a/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py +++ b/erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.py @@ -6,4 +6,24 @@ from frappe.model.document import Document class ItemVariantAttribute(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + attribute: DF.Link + attribute_value: DF.Data | None + from_range: DF.Float + increment: DF.Float + numeric_values: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + to_range: DF.Float + variant_of: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py index c3edba321c..a4bdc0ba78 100644 --- a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py +++ b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py @@ -8,6 +8,21 @@ from frappe.model.document import Document class ItemVariantSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.variant_field.variant_field import VariantField + + allow_rename_attribute_value: DF.Check + do_not_update_variants: DF.Check + fields: DF.Table[VariantField] + # end: auto-generated types + invalid_fields_for_copy_fields_in_variants = ["barcodes"] def set_default_fields(self): diff --git a/erpnext/stock/doctype/item_website_specification/item_website_specification.py b/erpnext/stock/doctype/item_website_specification/item_website_specification.py index af9612c186..7ac02f6c22 100644 --- a/erpnext/stock/doctype/item_website_specification/item_website_specification.py +++ b/erpnext/stock/doctype/item_website_specification/item_website_specification.py @@ -8,4 +8,19 @@ from frappe.model.document import Document class ItemWebsiteSpecification(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor | None + label: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py index 35a3740564..67f695ac17 100644 --- a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py +++ b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.py @@ -6,4 +6,28 @@ from frappe.model.document import Document class LandedCostItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + applicable_charges: DF.Currency + cost_center: DF.Link | None + description: DF.TextEditor + is_fixed_asset: DF.Check + item_code: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + purchase_receipt_item: DF.Data | None + qty: DF.Float + rate: DF.Currency + receipt_document: DF.DynamicLink | None + receipt_document_type: DF.Literal["Purchase Invoice", "Purchase Receipt"] + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py b/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py index f5bbc4ad52..9f0ffb8956 100644 --- a/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py +++ b/erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.py @@ -6,4 +6,22 @@ from frappe.model.document import Document class LandedCostPurchaseReceipt(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + grand_total: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + posting_date: DF.Date | None + receipt_document: DF.DynamicLink + receipt_document_type: DF.Literal["", "Purchase Invoice", "Purchase Receipt"] + supplier: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py index a4a1c58396..8509cb71d8 100644 --- a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py +++ b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class LandedCostTaxesandCharges(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account_currency: DF.Link | None + amount: DF.Currency + base_amount: DF.Currency + description: DF.SmallText + exchange_rate: DF.Float + expense_account: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index 8bbc660899..30b26a0e2b 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -15,6 +15,33 @@ from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos class LandedCostVoucher(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.landed_cost_item.landed_cost_item import LandedCostItem + from erpnext.stock.doctype.landed_cost_purchase_receipt.landed_cost_purchase_receipt import ( + LandedCostPurchaseReceipt, + ) + from erpnext.stock.doctype.landed_cost_taxes_and_charges.landed_cost_taxes_and_charges import ( + LandedCostTaxesandCharges, + ) + + amended_from: DF.Link | None + company: DF.Link + distribute_charges_based_on: DF.Literal["Qty", "Amount", "Distribute Manually"] + items: DF.Table[LandedCostItem] + naming_series: DF.Literal["MAT-LCV-.YYYY.-"] + posting_date: DF.Date + purchase_receipts: DF.Table[LandedCostPurchaseReceipt] + taxes: DF.Table[LandedCostTaxesandCharges] + total_taxes_and_charges: DF.Currency + # end: auto-generated types + @frappe.whitelist() def get_items_from_purchase_receipts(self): self.set("items", []) diff --git a/erpnext/stock/doctype/manufacturer/manufacturer.py b/erpnext/stock/doctype/manufacturer/manufacturer.py index 426affc40b..5e559d05ad 100644 --- a/erpnext/stock/doctype/manufacturer/manufacturer.py +++ b/erpnext/stock/doctype/manufacturer/manufacturer.py @@ -7,6 +7,22 @@ from frappe.model.document import Document class Manufacturer(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + country: DF.Link | None + full_name: DF.Data | None + logo: DF.AttachImage | None + notes: DF.SmallText | None + short_name: DF.Data + website: DF.Data | None + # end: auto-generated types + def onload(self): """Load address and contacts in `__onload`""" load_address_and_contact(self) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index ecdec800e5..7df74f81ab 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -23,6 +23,55 @@ form_grid_templates = {"items": "templates/form_grid/material_request_grid.html" class MaterialRequest(BuyingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.material_request_item.material_request_item import MaterialRequestItem + + amended_from: DF.Link | None + company: DF.Link + customer: DF.Link | None + items: DF.Table[MaterialRequestItem] + job_card: DF.Link | None + letter_head: DF.Link | None + material_request_type: DF.Literal[ + "Purchase", "Material Transfer", "Material Issue", "Manufacture", "Customer Provided" + ] + naming_series: DF.Literal["MAT-MR-.YYYY.-"] + per_ordered: DF.Percent + per_received: DF.Percent + scan_barcode: DF.Data | None + schedule_date: DF.Date | None + select_print_heading: DF.Link | None + set_from_warehouse: DF.Link | None + set_warehouse: DF.Link | None + status: DF.Literal[ + "", + "Draft", + "Submitted", + "Stopped", + "Cancelled", + "Pending", + "Partially Ordered", + "Partially Received", + "Ordered", + "Issued", + "Transferred", + "Received", + ] + tc_name: DF.Link | None + terms: DF.TextEditor | None + title: DF.Data | None + transaction_date: DF.Date + transfer_status: DF.Literal["", "Not Started", "In Transit", "Completed"] + work_order: DF.Link | None + # end: auto-generated types + def check_if_already_pulled(self): pass diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.py b/erpnext/stock/doctype/material_request_item/material_request_item.py index 08c9ed2742..2bed596292 100644 --- a/erpnext/stock/doctype/material_request_item/material_request_item.py +++ b/erpnext/stock/doctype/material_request_item/material_request_item.py @@ -9,6 +9,54 @@ from frappe.model.document import Document class MaterialRequestItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + amount: DF.Currency + bom_no: DF.Link | None + brand: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + description: DF.TextEditor | None + expense_account: DF.Link | None + from_warehouse: DF.Link | None + image: DF.AttachImage | None + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + job_card_item: DF.Data | None + lead_time_date: DF.Date | None + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + material_request_plan_item: DF.Data | None + min_order_qty: DF.Float + ordered_qty: DF.Float + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + production_plan: DF.Link | None + project: DF.Link | None + projected_qty: DF.Float + qty: DF.Float + rate: DF.Currency + received_qty: DF.Float + sales_order: DF.Link | None + sales_order_item: DF.Data | None + schedule_date: DF.Date + stock_qty: DF.Float + stock_uom: DF.Link + uom: DF.Link + warehouse: DF.Link | None + wip_composite_asset: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 35701c90de..ed667c2b99 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -14,6 +14,42 @@ from erpnext.stock.get_item_details import get_item_details, get_price_list_rate class PackedItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_batch_qty: DF.Float + actual_qty: DF.Float + batch_no: DF.Link | None + conversion_factor: DF.Float + description: DF.TextEditor | None + incoming_rate: DF.Currency + item_code: DF.Link | None + item_name: DF.Data | None + ordered_qty: DF.Float + packed_qty: DF.Float + page_break: DF.Check + parent: DF.Data + parent_detail_docname: DF.Data | None + parent_item: DF.Link | None + parentfield: DF.Data + parenttype: DF.Data + picked_qty: DF.Float + prevdoc_doctype: DF.Data | None + projected_qty: DF.Float + qty: DF.Float + rate: DF.Currency + serial_and_batch_bundle: DF.Link | None + serial_no: DF.Text | None + target_warehouse: DF.Link | None + uom: DF.Link | None + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py index 6ea5938917..88acfe83f2 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -10,6 +10,29 @@ from erpnext.controllers.status_updater import StatusUpdater class PackingSlip(StatusUpdater): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.packing_slip_item.packing_slip_item import PackingSlipItem + + amended_from: DF.Link | None + delivery_note: DF.Link + from_case_no: DF.Int + gross_weight_pkg: DF.Float + gross_weight_uom: DF.Link | None + items: DF.Table[PackingSlipItem] + letter_head: DF.Link | None + naming_series: DF.Literal["MAT-PAC-.YYYY.-"] + net_weight_pkg: DF.Float + net_weight_uom: DF.Link | None + to_case_no: DF.Int + # end: auto-generated types + def __init__(self, *args, **kwargs) -> None: super(PackingSlip, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py b/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py index ec148aa5bc..fa883c1740 100644 --- a/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py +++ b/erpnext/stock/doctype/packing_slip_item/packing_slip_item.py @@ -8,4 +8,28 @@ from frappe.model.document import Document class PackingSlipItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + batch_no: DF.Link | None + description: DF.TextEditor | None + dn_detail: DF.Data | None + item_code: DF.Link + item_name: DF.Data | None + net_weight: DF.Float + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + pi_detail: DF.Data | None + qty: DF.Float + stock_uom: DF.Link | None + weight_uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index e7f620496c..545e45f3d8 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -29,6 +29,34 @@ from erpnext.stock.serial_batch_bundle import SerialBatchCreation class PickList(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.pick_list_item.pick_list_item import PickListItem + + amended_from: DF.Link | None + company: DF.Link + customer: DF.Link | None + customer_name: DF.Data | None + for_qty: DF.Float + group_same_items: DF.Check + locations: DF.Table[PickListItem] + material_request: DF.Link | None + naming_series: DF.Literal["STO-PICK-.YYYY.-"] + parent_warehouse: DF.Link | None + prompt_qty: DF.Check + purpose: DF.Literal["Material Transfer for Manufacture", "Material Transfer", "Delivery"] + scan_barcode: DF.Data | None + scan_mode: DF.Check + status: DF.Literal["Draft", "Open", "Completed", "Cancelled"] + work_order: DF.Link | None + # end: auto-generated types + def onload(self) -> None: if frappe.get_cached_value("Stock Settings", None, "enable_stock_reservation"): if self.has_unreserved_stock(): diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.py b/erpnext/stock/doctype/pick_list_item/pick_list_item.py index 6ecccb1248..6e5a94e446 100644 --- a/erpnext/stock/doctype/pick_list_item/pick_list_item.py +++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.py @@ -7,4 +7,37 @@ from frappe.model.document import Document class PickListItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + batch_no: DF.Link | None + conversion_factor: DF.Float + description: DF.Text | None + item_code: DF.Link + item_group: DF.Data | None + item_name: DF.Data | None + material_request: DF.Link | None + material_request_item: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + picked_qty: DF.Float + product_bundle_item: DF.Data | None + qty: DF.Float + sales_order: DF.Link | None + sales_order_item: DF.Data | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + stock_qty: DF.Float + stock_reserved_qty: DF.Float + stock_uom: DF.Link | None + uom: DF.Link | None + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/price_list/price_list.py b/erpnext/stock/doctype/price_list/price_list.py index 21c0f18cc3..580c7c00b1 100644 --- a/erpnext/stock/doctype/price_list/price_list.py +++ b/erpnext/stock/doctype/price_list/price_list.py @@ -9,6 +9,25 @@ from frappe.utils import cint class PriceList(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.price_list_country.price_list_country import PriceListCountry + + buying: DF.Check + countries: DF.Table[PriceListCountry] + currency: DF.Link + enabled: DF.Check + price_list_name: DF.Data + price_not_uom_dependent: DF.Check + selling: DF.Check + # end: auto-generated types + def validate(self): if not cint(self.buying) and not cint(self.selling): throw(_("Price List must be applicable for Buying or Selling")) diff --git a/erpnext/stock/doctype/price_list_country/price_list_country.py b/erpnext/stock/doctype/price_list_country/price_list_country.py index 94e1107b2c..574d7e0051 100644 --- a/erpnext/stock/doctype/price_list_country/price_list_country.py +++ b/erpnext/stock/doctype/price_list_country/price_list_country.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class PriceListCountry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + country: DF.Link + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 8647528ea5..907bc6712f 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -21,6 +21,118 @@ form_grid_templates = {"items": "templates/form_grid/item_grid.html"} class PurchaseReceipt(BuyingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.pricing_rule_detail.pricing_rule_detail import PricingRuleDetail + from erpnext.accounts.doctype.purchase_taxes_and_charges.purchase_taxes_and_charges import ( + PurchaseTaxesandCharges, + ) + from erpnext.buying.doctype.purchase_receipt_item_supplied.purchase_receipt_item_supplied import ( + PurchaseReceiptItemSupplied, + ) + from erpnext.stock.doctype.purchase_receipt_item.purchase_receipt_item import PurchaseReceiptItem + + additional_discount_percentage: DF.Float + address_display: DF.SmallText | None + amended_from: DF.Link | None + apply_discount_on: DF.Literal["", "Grand Total", "Net Total"] + apply_putaway_rule: DF.Check + auto_repeat: DF.Link | None + base_discount_amount: DF.Currency + base_grand_total: DF.Currency + base_in_words: DF.Data | None + base_net_total: DF.Currency + base_rounded_total: DF.Currency + base_rounding_adjustment: DF.Currency + base_taxes_and_charges_added: DF.Currency + base_taxes_and_charges_deducted: DF.Currency + base_total: DF.Currency + base_total_taxes_and_charges: DF.Currency + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + buying_price_list: DF.Link | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.SmallText | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + conversion_rate: DF.Float + cost_center: DF.Link | None + currency: DF.Link + disable_rounded_total: DF.Check + discount_amount: DF.Currency + grand_total: DF.Currency + group_same_items: DF.Check + ignore_pricing_rule: DF.Check + in_words: DF.Data | None + incoterm: DF.Link | None + instructions: DF.SmallText | None + inter_company_reference: DF.Link | None + is_internal_supplier: DF.Check + is_old_subcontracting_flow: DF.Check + is_return: DF.Check + is_subcontracted: DF.Check + items: DF.Table[PurchaseReceiptItem] + language: DF.Data | None + letter_head: DF.Link | None + lr_date: DF.Date | None + lr_no: DF.Data | None + named_place: DF.Data | None + naming_series: DF.Literal["MAT-PRE-.YYYY.-", "MAT-PR-RET-.YYYY.-"] + net_total: DF.Currency + other_charges_calculation: DF.LongText | None + per_billed: DF.Percent + per_returned: DF.Percent + plc_conversion_rate: DF.Float + posting_date: DF.Date + posting_time: DF.Time + price_list_currency: DF.Link | None + pricing_rules: DF.Table[PricingRuleDetail] + project: DF.Link | None + range: DF.Data | None + rejected_warehouse: DF.Link | None + remarks: DF.SmallText | None + represents_company: DF.Link | None + return_against: DF.Link | None + rounded_total: DF.Currency + rounding_adjustment: DF.Currency + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + set_from_warehouse: DF.Link | None + set_posting_time: DF.Check + set_warehouse: DF.Link | None + shipping_address: DF.Link | None + shipping_address_display: DF.SmallText | None + shipping_rule: DF.Link | None + status: DF.Literal["", "Draft", "To Bill", "Completed", "Return Issued", "Cancelled", "Closed"] + subcontracting_receipt: DF.Link | None + supplied_items: DF.Table[PurchaseReceiptItemSupplied] + supplier: DF.Link + supplier_address: DF.Link | None + supplier_delivery_note: DF.Data | None + supplier_name: DF.Data | None + supplier_warehouse: DF.Link | None + tax_category: DF.Link | None + taxes: DF.Table[PurchaseTaxesandCharges] + taxes_and_charges: DF.Link | None + taxes_and_charges_added: DF.Currency + taxes_and_charges_deducted: DF.Currency + tc_name: DF.Link | None + terms: DF.TextEditor | None + title: DF.Data | None + total: DF.Currency + total_net_weight: DF.Float + total_qty: DF.Float + total_taxes_and_charges: DF.Currency + transporter_name: DF.Data | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(PurchaseReceipt, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py index b4b9fd3363..aed8d21dae 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py @@ -6,4 +6,104 @@ from frappe.model.document import Document class PurchaseReceiptItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + asset_category: DF.Link | None + asset_location: DF.Link | None + barcode: DF.Data | None + base_amount: DF.Currency + base_net_amount: DF.Currency + base_net_rate: DF.Currency + base_price_list_rate: DF.Currency + base_rate: DF.Currency + base_rate_with_margin: DF.Currency + batch_no: DF.Link | None + billed_amt: DF.Currency + bom: DF.Link | None + brand: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + delivery_note_item: DF.Data | None + description: DF.TextEditor | None + discount_amount: DF.Currency + discount_percentage: DF.Percent + expense_account: DF.Link | None + from_warehouse: DF.Link | None + has_item_scanned: DF.Check + image: DF.Attach | None + include_exploded_items: DF.Check + is_fixed_asset: DF.Check + is_free_item: DF.Check + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data + item_tax_amount: DF.Currency + item_tax_rate: DF.Code | None + item_tax_template: DF.Link | None + landed_cost_voucher_amount: DF.Currency + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + margin_rate_or_amount: DF.Float + margin_type: DF.Literal["", "Percentage", "Amount"] + material_request: DF.Link | None + material_request_item: DF.Data | None + net_amount: DF.Currency + net_rate: DF.Currency + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + price_list_rate: DF.Currency + pricing_rules: DF.SmallText | None + product_bundle: DF.Link | None + project: DF.Link | None + provisional_expense_account: DF.Link | None + purchase_invoice: DF.Link | None + purchase_invoice_item: DF.Data | None + purchase_order: DF.Link | None + purchase_order_item: DF.Data | None + purchase_receipt_item: DF.Data | None + putaway_rule: DF.Link | None + qty: DF.Float + quality_inspection: DF.Link | None + rate: DF.Currency + rate_difference_with_purchase_invoice: DF.Currency + rate_with_margin: DF.Currency + received_qty: DF.Float + received_stock_qty: DF.Float + rejected_qty: DF.Float + rejected_serial_and_batch_bundle: DF.Link | None + rejected_serial_no: DF.Text | None + rejected_warehouse: DF.Link | None + retain_sample: DF.Check + returned_qty: DF.Float + rm_supp_cost: DF.Currency + sales_order: DF.Link | None + sales_order_item: DF.Data | None + sample_quantity: DF.Int + schedule_date: DF.Date | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.Text | None + stock_qty: DF.Float + stock_uom: DF.Link + stock_uom_rate: DF.Currency + subcontracting_receipt_item: DF.Data | None + supplier_part_no: DF.Data | None + total_weight: DF.Float + uom: DF.Link + valuation_rate: DF.Currency + warehouse: DF.Link | None + weight_per_unit: DF.Float + weight_uom: DF.Link | None + wip_composite_asset: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py index 0a04210e0b..3fc4e01bdc 100644 --- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py @@ -15,6 +15,27 @@ from erpnext.stock.utils import get_stock_balance class PutawayRule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + capacity: DF.Float + company: DF.Link + conversion_factor: DF.Float + disable: DF.Check + item_code: DF.Link + item_name: DF.Data | None + priority: DF.Int + stock_capacity: DF.Float + stock_uom: DF.Link | None + uom: DF.Link | None + warehouse: DF.Link + # end: auto-generated types + def validate(self): self.validate_duplicate_rule() self.validate_warehouse_and_company() diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 9673c81e55..4464ea820e 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -14,6 +14,49 @@ from erpnext.stock.doctype.quality_inspection_template.quality_inspection_templa class QualityInspection(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.quality_inspection_reading.quality_inspection_reading import ( + QualityInspectionReading, + ) + + amended_from: DF.Link | None + batch_no: DF.Link | None + bom_no: DF.Link | None + description: DF.SmallText | None + inspected_by: DF.Link + inspection_type: DF.Literal["", "Incoming", "Outgoing", "In Process"] + item_code: DF.Link + item_name: DF.Data | None + item_serial_no: DF.Link | None + manual_inspection: DF.Check + naming_series: DF.Literal["MAT-QA-.YYYY.-"] + quality_inspection_template: DF.Link | None + readings: DF.Table[QualityInspectionReading] + reference_name: DF.DynamicLink + reference_type: DF.Literal[ + "", + "Purchase Receipt", + "Purchase Invoice", + "Subcontracting Receipt", + "Delivery Note", + "Sales Invoice", + "Stock Entry", + "Job Card", + ] + remarks: DF.Text | None + report_date: DF.Date + sample_size: DF.Float + status: DF.Literal["", "Accepted", "Rejected"] + verified_by: DF.Data | None + # end: auto-generated types + def validate(self): if not self.readings and self.item_code: self.get_item_specification_details() diff --git a/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py b/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py index d5123c7ce6..310915f075 100644 --- a/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py +++ b/erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.py @@ -7,4 +7,17 @@ from frappe.model.document import Document class QualityInspectionParameter(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.TextEditor | None + parameter: DF.Data + parameter_group: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py b/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py index 26e9361516..01053765f3 100644 --- a/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py +++ b/erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.py @@ -7,4 +7,15 @@ from frappe.model.document import Document class QualityInspectionParameterGroup(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + group_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py b/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py index 81454f110b..0ba90081d8 100644 --- a/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py +++ b/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.py @@ -6,4 +6,38 @@ from frappe.model.document import Document class QualityInspectionReading(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + acceptance_formula: DF.Code | None + formula_based_criteria: DF.Check + manual_inspection: DF.Check + max_value: DF.Float + min_value: DF.Float + numeric: DF.Check + parameter_group: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + reading_10: DF.Data | None + reading_1: DF.Data | None + reading_2: DF.Data | None + reading_3: DF.Data | None + reading_4: DF.Data | None + reading_5: DF.Data | None + reading_6: DF.Data | None + reading_7: DF.Data | None + reading_8: DF.Data | None + reading_9: DF.Data | None + reading_value: DF.Data | None + specification: DF.Link + status: DF.Literal["", "Accepted", "Rejected"] + value: DF.Data | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py index 9b8f5d6378..44b77350b4 100644 --- a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py +++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py @@ -7,6 +7,22 @@ from frappe.model.document import Document class QualityInspectionTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.item_quality_inspection_parameter.item_quality_inspection_parameter import ( + ItemQualityInspectionParameter, + ) + + item_quality_inspection_parameter: DF.Table[ItemQualityInspectionParameter] + quality_inspection_template_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py index 846be0b9bd..34fb68c1b7 100644 --- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py +++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py @@ -10,6 +10,24 @@ from erpnext.stock.utils import get_stock_balance, get_stock_value_on class QuickStockBalance(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + date: DF.Date + item: DF.Link + item_barcode: DF.Data | None + item_description: DF.SmallText | None + item_name: DF.Data | None + qty: DF.Float + value: DF.Currency + warehouse: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index f128c8e206..97ada06e1d 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -25,6 +25,37 @@ RecoverableErrors = (JobTimeoutException, QueryDeadlockError, QueryTimeoutError) class RepostItemValuation(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + affected_transactions: DF.Code | None + allow_negative_stock: DF.Check + allow_zero_rate: DF.Check + amended_from: DF.Link | None + based_on: DF.Literal["Transaction", "Item and Warehouse"] + company: DF.Link | None + current_index: DF.Int + distinct_item_and_warehouse: DF.Code | None + error_log: DF.LongText | None + gl_reposting_index: DF.Int + item_code: DF.Link | None + items_to_be_repost: DF.Code | None + posting_date: DF.Date + posting_time: DF.Time | None + reposting_data_file: DF.Attach | None + status: DF.Literal["Queued", "In Progress", "Completed", "Skipped", "Failed"] + total_reposting_count: DF.Int + via_landed_cost_voucher: DF.Check + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + warehouse: DF.Link | None + # end: auto-generated types + @staticmethod def clear_old_logs(days=None): days = days or 90 diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 3c824fd590..f0cff21a42 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -44,6 +44,42 @@ class SerialNoWarehouseError(frappe.ValidationError): class SerialandBatchBundle(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.serial_and_batch_entry.serial_and_batch_entry import ( + SerialandBatchEntry, + ) + + amended_from: DF.Link | None + avg_rate: DF.Float + company: DF.Link + entries: DF.Table[SerialandBatchEntry] + has_batch_no: DF.Check + has_serial_no: DF.Check + is_cancelled: DF.Check + is_rejected: DF.Check + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + naming_series: DF.Literal["SABB-.########"] + posting_date: DF.Date | None + posting_time: DF.Time | None + returned_against: DF.Data | None + total_amount: DF.Float + total_qty: DF.Float + type_of_transaction: DF.Literal["", "Inward", "Outward", "Maintenance", "Asset Repair"] + voucher_detail_no: DF.Data | None + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link + warehouse: DF.Link | None + # end: auto-generated types + def validate(self): self.validate_serial_and_batch_no() self.validate_duplicate_serial_and_batch_no() diff --git a/erpnext/stock/doctype/serial_and_batch_entry/serial_and_batch_entry.py b/erpnext/stock/doctype/serial_and_batch_entry/serial_and_batch_entry.py index 337403e2e1..c849e682cc 100644 --- a/erpnext/stock/doctype/serial_and_batch_entry/serial_and_batch_entry.py +++ b/erpnext/stock/doctype/serial_and_batch_entry/serial_and_batch_entry.py @@ -6,4 +6,27 @@ from frappe.model.document import Document class SerialandBatchEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + batch_no: DF.Link | None + delivered_qty: DF.Float + incoming_rate: DF.Float + is_outward: DF.Check + outgoing_rate: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + serial_no: DF.Link | None + stock_queue: DF.SmallText | None + stock_value_difference: DF.Float + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index ba9482a7ba..d562560da1 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -27,6 +27,39 @@ class SerialNoWarehouseError(ValidationError): class SerialNo(StockController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amc_expiry_date: DF.Date | None + asset: DF.Link | None + asset_status: DF.Literal["", "Issue", "Receipt", "Transfer"] + batch_no: DF.Link | None + brand: DF.Link | None + company: DF.Link + delivery_document_type: DF.Link | None + description: DF.Text | None + employee: DF.Link | None + item_code: DF.Link + item_group: DF.Link | None + item_name: DF.Data | None + location: DF.Link | None + maintenance_status: DF.Literal[ + "", "Under Warranty", "Out of Warranty", "Under AMC", "Out of AMC" + ] + purchase_rate: DF.Float + serial_no: DF.Data + status: DF.Literal["", "Active", "Inactive", "Delivered", "Expired"] + warehouse: DF.Link | None + warranty_expiry_date: DF.Date | None + warranty_period: DF.Int + work_order: DF.Link | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(SerialNo, self).__init__(*args, **kwargs) self.via_stock_ledger = False diff --git a/erpnext/stock/doctype/shipment/shipment.py b/erpnext/stock/doctype/shipment/shipment.py index 42a67f42be..346e70e606 100644 --- a/erpnext/stock/doctype/shipment/shipment.py +++ b/erpnext/stock/doctype/shipment/shipment.py @@ -12,6 +12,65 @@ from erpnext.accounts.party import get_party_shipping_address class Shipment(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.shipment_delivery_note.shipment_delivery_note import ( + ShipmentDeliveryNote, + ) + from erpnext.stock.doctype.shipment_parcel.shipment_parcel import ShipmentParcel + + amended_from: DF.Link | None + awb_number: DF.Data | None + carrier: DF.Data | None + carrier_service: DF.Data | None + delivery_address: DF.SmallText | None + delivery_address_name: DF.Link + delivery_company: DF.Link | None + delivery_contact: DF.SmallText | None + delivery_contact_email: DF.Data | None + delivery_contact_name: DF.Link | None + delivery_customer: DF.Link | None + delivery_supplier: DF.Link | None + delivery_to: DF.Data | None + delivery_to_type: DF.Literal["Company", "Customer", "Supplier"] + description_of_content: DF.SmallText + incoterm: DF.Link | None + pallets: DF.Literal["No", "Yes"] + parcel_template: DF.Link | None + pickup: DF.Data | None + pickup_address: DF.SmallText | None + pickup_address_name: DF.Link + pickup_company: DF.Link | None + pickup_contact: DF.SmallText | None + pickup_contact_email: DF.Data | None + pickup_contact_name: DF.Link | None + pickup_contact_person: DF.Link | None + pickup_customer: DF.Link | None + pickup_date: DF.Date + pickup_from: DF.Time + pickup_from_type: DF.Literal["Company", "Customer", "Supplier"] + pickup_supplier: DF.Link | None + pickup_to: DF.Time + pickup_type: DF.Literal["Pickup", "Self delivery"] + service_provider: DF.Data | None + shipment_amount: DF.Currency + shipment_delivery_note: DF.Table[ShipmentDeliveryNote] + shipment_id: DF.Data | None + shipment_parcel: DF.Table[ShipmentParcel] + shipment_type: DF.Literal["Goods", "Documents"] + status: DF.Literal["Draft", "Submitted", "Booked", "Cancelled", "Completed"] + tracking_status: DF.Literal["", "In Progress", "Delivered", "Returned", "Lost"] + tracking_status_info: DF.Data | None + tracking_url: DF.SmallText | None + value_of_goods: DF.Currency + # end: auto-generated types + def validate(self): self.validate_weight() self.validate_pickup_time() diff --git a/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py index 2b58a39dfb..fb5e61665c 100644 --- a/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py +++ b/erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class ShipmentDeliveryNote(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + delivery_note: DF.Link + grand_total: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py index a6070213bb..f789f07ce3 100644 --- a/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py +++ b/erpnext/stock/doctype/shipment_parcel/shipment_parcel.py @@ -7,4 +7,22 @@ from frappe.model.document import Document class ShipmentParcel(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + count: DF.Int + height: DF.Int + length: DF.Int + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + weight: DF.Float + width: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py index a5de312d6b..054c0f379a 100644 --- a/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py +++ b/erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class ShipmentParcelTemplate(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + height: DF.Int + length: DF.Int + parcel_template_name: DF.Data + weight: DF.Float + width: DF.Int + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index b06de2e2fc..8158b99f93 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -74,6 +74,82 @@ form_grid_templates = {"items": "templates/form_grid/stock_entry_grid.html"} class StockEntry(StockController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.landed_cost_taxes_and_charges.landed_cost_taxes_and_charges import ( + LandedCostTaxesandCharges, + ) + from erpnext.stock.doctype.stock_entry_detail.stock_entry_detail import StockEntryDetail + + add_to_transit: DF.Check + additional_costs: DF.Table[LandedCostTaxesandCharges] + address_display: DF.SmallText | None + amended_from: DF.Link | None + apply_putaway_rule: DF.Check + bom_no: DF.Link | None + company: DF.Link + credit_note: DF.Link | None + delivery_note_no: DF.Link | None + fg_completed_qty: DF.Float + from_bom: DF.Check + from_warehouse: DF.Link | None + inspection_required: DF.Check + is_opening: DF.Literal["No", "Yes"] + is_return: DF.Check + items: DF.Table[StockEntryDetail] + job_card: DF.Link | None + letter_head: DF.Link | None + naming_series: DF.Literal["MAT-STE-.YYYY.-"] + outgoing_stock_entry: DF.Link | None + per_transferred: DF.Percent + pick_list: DF.Link | None + posting_date: DF.Date | None + posting_time: DF.Time | None + process_loss_percentage: DF.Percent + process_loss_qty: DF.Float + project: DF.Link | None + purchase_order: DF.Link | None + purchase_receipt_no: DF.Link | None + purpose: DF.Literal[ + "Material Issue", + "Material Receipt", + "Material Transfer", + "Material Transfer for Manufacture", + "Material Consumption for Manufacture", + "Manufacture", + "Repack", + "Send to Subcontractor", + ] + remarks: DF.Text | None + sales_invoice_no: DF.Link | None + scan_barcode: DF.Data | None + select_print_heading: DF.Link | None + set_posting_time: DF.Check + source_address_display: DF.SmallText | None + source_warehouse_address: DF.Link | None + stock_entry_type: DF.Link + subcontracting_order: DF.Link | None + supplier: DF.Link | None + supplier_address: DF.Link | None + supplier_name: DF.Data | None + target_address_display: DF.SmallText | None + target_warehouse_address: DF.Link | None + to_warehouse: DF.Link | None + total_additional_costs: DF.Currency + total_amount: DF.Currency + total_incoming_value: DF.Currency + total_outgoing_value: DF.Currency + use_multi_level_bom: DF.Check + value_difference: DF.Currency + work_order: DF.Link | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(StockEntry, self).__init__(*args, **kwargs) if self.purchase_order: diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py index 000ff2dcf8..b2fc1f52e1 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py @@ -6,4 +6,65 @@ from frappe.model.document import Document class StockEntryDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + additional_cost: DF.Currency + against_stock_entry: DF.Link | None + allow_alternative_item: DF.Check + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + attach_something_here: DF.Attach | None + barcode: DF.Data | None + basic_amount: DF.Currency + basic_rate: DF.Currency + batch_no: DF.Link | None + bom_no: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + description: DF.TextEditor | None + expense_account: DF.Link | None + has_item_scanned: DF.Check + image: DF.Attach | None + is_finished_item: DF.Check + is_scrap_item: DF.Check + item_code: DF.Link + item_group: DF.Data | None + item_name: DF.Data | None + job_card_item: DF.Data | None + material_request: DF.Link | None + material_request_item: DF.Link | None + original_item: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + po_detail: DF.Data | None + project: DF.Link | None + putaway_rule: DF.Link | None + qty: DF.Float + quality_inspection: DF.Link | None + reference_purchase_receipt: DF.Link | None + retain_sample: DF.Check + s_warehouse: DF.Link | None + sample_quantity: DF.Int + sco_rm_detail: DF.Data | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + set_basic_rate_manually: DF.Check + ste_detail: DF.Data | None + stock_uom: DF.Link + subcontracted_item: DF.Link | None + t_warehouse: DF.Link | None + transfer_qty: DF.Float + transferred_qty: DF.Float + uom: DF.Link + valuation_rate: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py index 7258cfbe2c..034223122f 100644 --- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py +++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py @@ -7,6 +7,28 @@ from frappe.model.document import Document class StockEntryType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + add_to_transit: DF.Check + purpose: DF.Literal[ + "", + "Material Issue", + "Material Receipt", + "Material Transfer", + "Material Transfer for Manufacture", + "Material Consumption for Manufacture", + "Manufacture", + "Repack", + "Send to Subcontractor", + ] + # end: auto-generated types + def validate(self): if self.add_to_transit and self.purpose != "Material Transfer": self.add_to_transit = 0 diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index c1b205132c..e62f0b2ac7 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -29,6 +29,46 @@ exclude_from_linked_with = True class StockLedgerEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + actual_qty: DF.Float + auto_created_serial_and_batch_bundle: DF.Check + batch_no: DF.Data | None + company: DF.Link | None + dependant_sle_voucher_detail_no: DF.Data | None + fiscal_year: DF.Data | None + has_batch_no: DF.Check + has_serial_no: DF.Check + incoming_rate: DF.Currency + is_adjustment_entry: DF.Check + is_cancelled: DF.Check + item_code: DF.Link | None + outgoing_rate: DF.Currency + posting_date: DF.Date | None + posting_time: DF.Time | None + project: DF.Link | None + qty_after_transaction: DF.Float + recalculate_rate: DF.Check + serial_and_batch_bundle: DF.Link | None + serial_no: DF.LongText | None + stock_queue: DF.Text | None + stock_uom: DF.Link | None + stock_value: DF.Currency + stock_value_difference: DF.Currency + to_rename: DF.Check + valuation_rate: DF.Currency + voucher_detail_no: DF.Data | None + voucher_no: DF.DynamicLink | None + voucher_type: DF.Link | None + warehouse: DF.Link | None + # end: auto-generated types + def autoname(self): """ Temporarily name doc for fast insertion diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 1bf143b49c..e8d652e2b2 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -29,6 +29,34 @@ class EmptyStockReconciliationItemsError(frappe.ValidationError): class StockReconciliation(StockController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.stock_reconciliation_item.stock_reconciliation_item import ( + StockReconciliationItem, + ) + + amended_from: DF.Link | None + company: DF.Link + cost_center: DF.Link | None + difference_amount: DF.Currency + expense_account: DF.Link | None + items: DF.Table[StockReconciliationItem] + naming_series: DF.Literal["MAT-RECO-.YYYY.-"] + posting_date: DF.Date + posting_time: DF.Time + purpose: DF.Literal["", "Opening Stock", "Stock Reconciliation"] + scan_barcode: DF.Data | None + scan_mode: DF.Check + set_posting_time: DF.Check + set_warehouse: DF.Link | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(StockReconciliation, self).__init__(*args, **kwargs) self.head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"] diff --git a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py index b3b5d082c9..c82cdf58de 100644 --- a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py +++ b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.py @@ -6,4 +6,36 @@ from frappe.model.document import Document class StockReconciliationItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + allow_zero_valuation_rate: DF.Check + amount: DF.Currency + amount_difference: DF.Currency + barcode: DF.Data | None + batch_no: DF.Link | None + current_amount: DF.Currency + current_qty: DF.Float + current_serial_and_batch_bundle: DF.Link | None + current_serial_no: DF.LongText | None + current_valuation_rate: DF.Currency + has_item_scanned: DF.Data | None + item_code: DF.Link + item_name: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + qty: DF.Float + quantity_difference: DF.ReadOnly | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.LongText | None + valuation_rate: DF.Currency + warehouse: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py index 51fb5ac4c4..50f39817ff 100644 --- a/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py +++ b/erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.py @@ -8,6 +8,24 @@ from frappe.utils import add_to_date, get_datetime, get_time_str, time_diff_in_h class StockRepostingSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + end_time: DF.Time | None + item_based_reposting: DF.Check + limit_reposting_timeslot: DF.Check + limits_dont_apply_on: DF.Literal[ + "", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + ] + notify_reposting_error_to_role: DF.Link | None + start_time: DF.Time | None + # end: auto-generated types + def validate(self): self.set_minimum_reposting_time_slot() diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py index cbfa4e0a43..85550c2b7d 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -13,6 +13,43 @@ from erpnext.stock.utils import get_or_make_bin class StockReservationEntry(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.serial_and_batch_entry.serial_and_batch_entry import ( + SerialandBatchEntry, + ) + + amended_from: DF.Link | None + available_qty: DF.Float + company: DF.Link | None + delivered_qty: DF.Float + from_voucher_detail_no: DF.Data | None + from_voucher_no: DF.DynamicLink | None + from_voucher_type: DF.Literal["", "Pick List", "Purchase Receipt"] + has_batch_no: DF.Check + has_serial_no: DF.Check + item_code: DF.Link | None + project: DF.Link | None + reservation_based_on: DF.Literal["Qty", "Serial and Batch"] + reserved_qty: DF.Float + sb_entries: DF.Table[SerialandBatchEntry] + status: DF.Literal[ + "Draft", "Partially Reserved", "Reserved", "Partially Delivered", "Delivered", "Cancelled" + ] + stock_uom: DF.Link | None + voucher_detail_no: DF.Data | None + voucher_no: DF.DynamicLink | None + voucher_qty: DF.Float + voucher_type: DF.Literal["", "Sales Order"] + warehouse: DF.Link | None + # end: auto-generated types + def validate(self) -> None: from erpnext.stock.utils import validate_disabled_warehouse, validate_warehouse_company diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py index c7afb105b1..088c7cdfe1 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/stock_settings.py @@ -15,6 +15,51 @@ from erpnext.stock.utils import check_pending_reposting class StockSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + action_if_quality_inspection_is_not_submitted: DF.Literal["Stop", "Warn"] + action_if_quality_inspection_is_rejected: DF.Literal["Stop", "Warn"] + allow_from_dn: DF.Check + allow_from_pr: DF.Check + allow_negative_stock: DF.Check + allow_partial_reservation: DF.Check + allow_to_edit_stock_uom_qty_for_purchase: DF.Check + allow_to_edit_stock_uom_qty_for_sales: DF.Check + auto_create_serial_and_batch_bundle_for_outward: DF.Check + auto_indent: DF.Check + auto_insert_price_list_rate_if_missing: DF.Check + auto_reserve_serial_and_batch: DF.Check + auto_reserve_stock_for_sales_order_on_purchase: DF.Check + clean_description_html: DF.Check + default_warehouse: DF.Link | None + disable_serial_no_and_batch_selector: DF.Check + enable_stock_reservation: DF.Check + item_group: DF.Link | None + item_naming_by: DF.Literal["Item Code", "Naming Series"] + mr_qty_allowance: DF.Float + naming_series_prefix: DF.Data | None + over_delivery_receipt_allowance: DF.Float + pick_serial_and_batch_based_on: DF.Literal["FIFO", "LIFO", "Expiry"] + reorder_email_notify: DF.Check + role_allowed_to_create_edit_back_dated_transactions: DF.Link | None + role_allowed_to_over_deliver_receive: DF.Link | None + sample_retention_warehouse: DF.Link | None + show_barcode_field: DF.Check + stock_auth_role: DF.Link | None + stock_frozen_upto: DF.Date | None + stock_frozen_upto_days: DF.Int + stock_uom: DF.Link | None + update_existing_price_list_rate: DF.Check + use_naming_series: DF.Check + valuation_method: DF.Literal["FIFO", "Moving Average", "LIFO"] + # end: auto-generated types + def validate(self): for key in [ "item_naming_by", diff --git a/erpnext/stock/doctype/uom_category/uom_category.py b/erpnext/stock/doctype/uom_category/uom_category.py index 844f6e6364..edbd1b9614 100644 --- a/erpnext/stock/doctype/uom_category/uom_category.py +++ b/erpnext/stock/doctype/uom_category/uom_category.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class UOMCategory(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + category_name: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py b/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py index e17a01eabc..d73ba65ca9 100644 --- a/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py +++ b/erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.py @@ -6,4 +6,19 @@ from frappe.model.document import Document class UOMConversionDetail(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + conversion_factor: DF.Float + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + uom: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/variant_field/variant_field.py b/erpnext/stock/doctype/variant_field/variant_field.py index e8e02a0e85..65c9ee7d52 100644 --- a/erpnext/stock/doctype/variant_field/variant_field.py +++ b/erpnext/stock/doctype/variant_field/variant_field.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class VariantField(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + field_name: DF.Autocomplete + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 430a8d17e0..ef9b12eca2 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -13,6 +13,35 @@ from erpnext.stock import get_warehouse_account class Warehouse(NestedSet): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + account: DF.Link | None + address_line_1: DF.Data | None + address_line_2: DF.Data | None + city: DF.Data | None + company: DF.Link + default_in_transit_warehouse: DF.Link | None + disabled: DF.Check + email_id: DF.Data | None + is_group: DF.Check + lft: DF.Int + mobile_no: DF.Data | None + old_parent: DF.Link | None + parent_warehouse: DF.Link | None + phone_no: DF.Data | None + pin: DF.Data | None + rgt: DF.Int + state: DF.Data | None + warehouse_name: DF.Data + warehouse_type: DF.Link | None + # end: auto-generated types + nsm_parent_field = "parent_warehouse" def autoname(self): diff --git a/erpnext/stock/doctype/warehouse_type/warehouse_type.py b/erpnext/stock/doctype/warehouse_type/warehouse_type.py index 3e07fe7d3c..91c83ba344 100644 --- a/erpnext/stock/doctype/warehouse_type/warehouse_type.py +++ b/erpnext/stock/doctype/warehouse_type/warehouse_type.py @@ -7,4 +7,15 @@ from frappe.model.document import Document class WarehouseType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.py b/erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.py index 49ba98653f..6a889b16d8 100644 --- a/erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.py +++ b/erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.py @@ -8,6 +8,25 @@ from frappe.utils import flt class SubcontractingBOM(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + conversion_factor: DF.Float + finished_good: DF.Link + finished_good_bom: DF.Link + finished_good_qty: DF.Float + finished_good_uom: DF.Link | None + is_active: DF.Check + service_item: DF.Link + service_item_qty: DF.Float + service_item_uom: DF.Link + # end: auto-generated types + def validate(self): self.validate_finished_good() self.validate_service_item() diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 6a658460da..68d98fc734 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -13,6 +13,73 @@ from erpnext.stock.utils import get_bin class SubcontractingOrder(SubcontractingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.landed_cost_taxes_and_charges.landed_cost_taxes_and_charges import ( + LandedCostTaxesandCharges, + ) + from erpnext.subcontracting.doctype.subcontracting_order_item.subcontracting_order_item import ( + SubcontractingOrderItem, + ) + from erpnext.subcontracting.doctype.subcontracting_order_service_item.subcontracting_order_service_item import ( + SubcontractingOrderServiceItem, + ) + from erpnext.subcontracting.doctype.subcontracting_order_supplied_item.subcontracting_order_supplied_item import ( + SubcontractingOrderSuppliedItem, + ) + + additional_costs: DF.Table[LandedCostTaxesandCharges] + address_display: DF.SmallText | None + amended_from: DF.Link | None + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.SmallText | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + cost_center: DF.Link | None + distribute_additional_costs_based_on: DF.Literal["Qty", "Amount"] + items: DF.Table[SubcontractingOrderItem] + letter_head: DF.Link | None + naming_series: DF.Literal["SC-ORD-.YYYY.-"] + per_received: DF.Percent + project: DF.Link | None + purchase_order: DF.Link + schedule_date: DF.Date | None + select_print_heading: DF.Link | None + service_items: DF.Table[SubcontractingOrderServiceItem] + set_reserve_warehouse: DF.Link | None + set_warehouse: DF.Link | None + shipping_address: DF.Link | None + shipping_address_display: DF.SmallText | None + status: DF.Literal[ + "Draft", + "Open", + "Partially Received", + "Completed", + "Material Transferred", + "Partial Material Transferred", + "Cancelled", + ] + supplied_items: DF.Table[SubcontractingOrderSuppliedItem] + supplier: DF.Link + supplier_address: DF.Link | None + supplier_name: DF.Data + supplier_warehouse: DF.Link + title: DF.Data | None + total: DF.Currency + total_additional_costs: DF.Currency + total_qty: DF.Float + transaction_date: DF.Date + # end: auto-generated types + def before_validate(self): super(SubcontractingOrder, self).before_validate() diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py index 174f5b212c..fcd143c1dd 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py @@ -6,4 +6,43 @@ from frappe.model.document import Document class SubcontractingOrderItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + additional_cost_per_qty: DF.Currency + amount: DF.Currency + bom: DF.Link + conversion_factor: DF.Float + cost_center: DF.Link | None + description: DF.TextEditor + expected_delivery_date: DF.Date | None + expense_account: DF.Link | None + image: DF.Attach | None + include_exploded_items: DF.Check + item_code: DF.Link + item_name: DF.Data + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project: DF.Link | None + purchase_order_item: DF.Data | None + qty: DF.Float + rate: DF.Currency + received_qty: DF.Float + returned_qty: DF.Float + rm_cost_per_qty: DF.Currency + schedule_date: DF.Date | None + service_cost_per_qty: DF.Currency + stock_uom: DF.Link + warehouse: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py index ad6289d923..cc4901baf4 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.py @@ -6,4 +6,25 @@ from frappe.model.document import Document class SubcontractingOrderServiceItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + fg_item: DF.Link + fg_item_qty: DF.Float + item_code: DF.Link + item_name: DF.Data + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + purchase_order_item: DF.Data | None + qty: DF.Float + rate: DF.Currency + # end: auto-generated types + pass diff --git a/erpnext/subcontracting/doctype/subcontracting_order_supplied_item/subcontracting_order_supplied_item.py b/erpnext/subcontracting/doctype/subcontracting_order_supplied_item/subcontracting_order_supplied_item.py index 5619e3b79a..4892601d08 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_supplied_item/subcontracting_order_supplied_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_order_supplied_item/subcontracting_order_supplied_item.py @@ -6,4 +6,31 @@ from frappe.model.document import Document class SubcontractingOrderSuppliedItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + bom_detail_no: DF.Data | None + consumed_qty: DF.Float + conversion_factor: DF.Float + main_item_code: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Currency + reference_name: DF.Data | None + required_qty: DF.Float + reserve_warehouse: DF.Link | None + returned_qty: DF.Float + rm_item_code: DF.Link | None + stock_uom: DF.Link | None + supplied_qty: DF.Float + total_supplied_qty: DF.Float + # end: auto-generated types + pass diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 6df9129700..1a5deb68df 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -13,6 +13,76 @@ from erpnext.stock.stock_ledger import get_valuation_rate class SubcontractingReceipt(SubcontractingController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.stock.doctype.landed_cost_taxes_and_charges.landed_cost_taxes_and_charges import ( + LandedCostTaxesandCharges, + ) + from erpnext.subcontracting.doctype.subcontracting_receipt_item.subcontracting_receipt_item import ( + SubcontractingReceiptItem, + ) + from erpnext.subcontracting.doctype.subcontracting_receipt_supplied_item.subcontracting_receipt_supplied_item import ( + SubcontractingReceiptSuppliedItem, + ) + + additional_costs: DF.Table[LandedCostTaxesandCharges] + address_display: DF.SmallText | None + amended_from: DF.Link | None + auto_repeat: DF.Link | None + bill_date: DF.Date | None + bill_no: DF.Data | None + billing_address: DF.Link | None + billing_address_display: DF.SmallText | None + company: DF.Link + contact_display: DF.SmallText | None + contact_email: DF.SmallText | None + contact_mobile: DF.SmallText | None + contact_person: DF.Link | None + cost_center: DF.Link | None + distribute_additional_costs_based_on: DF.Literal["Qty", "Amount"] + in_words: DF.Data | None + instructions: DF.SmallText | None + is_return: DF.Check + items: DF.Table[SubcontractingReceiptItem] + language: DF.Data | None + letter_head: DF.Link | None + lr_date: DF.Date | None + lr_no: DF.Data | None + naming_series: DF.Literal["MAT-SCR-.YYYY.-", "MAT-SCR-RET-.YYYY.-"] + per_returned: DF.Percent + posting_date: DF.Date + posting_time: DF.Time + project: DF.Link | None + range: DF.Data | None + rejected_warehouse: DF.Link | None + remarks: DF.SmallText | None + represents_company: DF.Link | None + return_against: DF.Link | None + select_print_heading: DF.Link | None + set_posting_time: DF.Check + set_warehouse: DF.Link | None + shipping_address: DF.Link | None + shipping_address_display: DF.SmallText | None + status: DF.Literal["", "Draft", "Completed", "Return", "Return Issued", "Cancelled", "Closed"] + supplied_items: DF.Table[SubcontractingReceiptSuppliedItem] + supplier: DF.Link + supplier_address: DF.Link | None + supplier_delivery_note: DF.Data | None + supplier_name: DF.Data | None + supplier_warehouse: DF.Link | None + title: DF.Data | None + total: DF.Currency + total_additional_costs: DF.Currency + total_qty: DF.Float + transporter_name: DF.Data | None + # end: auto-generated types + def __init__(self, *args, **kwargs): super(SubcontractingReceipt, self).__init__(*args, **kwargs) self.status_updater = [ diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.py b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.py index 374f95baf3..d02160ece4 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.py @@ -6,4 +6,59 @@ from frappe.model.document import Document class SubcontractingReceiptItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + additional_cost_per_qty: DF.Currency + amount: DF.Currency + batch_no: DF.Link | None + bom: DF.Link | None + brand: DF.Link | None + conversion_factor: DF.Float + cost_center: DF.Link | None + description: DF.TextEditor | None + expense_account: DF.Link | None + image: DF.Attach | None + include_exploded_items: DF.Check + is_scrap_item: DF.Check + item_code: DF.Link + item_name: DF.Data | None + manufacturer: DF.Link | None + manufacturer_part_no: DF.Data | None + page_break: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + project: DF.Link | None + purchase_order: DF.Link | None + purchase_order_item: DF.Data | None + qty: DF.Float + quality_inspection: DF.Link | None + rate: DF.Currency + received_qty: DF.Float + reference_name: DF.Data | None + rejected_qty: DF.Float + rejected_serial_and_batch_bundle: DF.Link | None + rejected_serial_no: DF.SmallText | None + rejected_warehouse: DF.Link | None + returned_qty: DF.Float + rm_cost_per_qty: DF.Currency + rm_supp_cost: DF.Currency + schedule_date: DF.Date | None + scrap_cost_per_qty: DF.Float + serial_and_batch_bundle: DF.Link | None + serial_no: DF.SmallText | None + service_cost_per_qty: DF.Currency + stock_uom: DF.Link + subcontracting_order: DF.Link | None + subcontracting_order_item: DF.Data | None + subcontracting_receipt_item: DF.Data | None + warehouse: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.py b/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.py index f4d2805d4b..2ee55518d5 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.py @@ -6,4 +6,35 @@ from frappe.model.document import Document class SubcontractingReceiptSuppliedItem(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amount: DF.Currency + available_qty_for_consumption: DF.Float + batch_no: DF.Link | None + bom_detail_no: DF.Data | None + consumed_qty: DF.Float + conversion_factor: DF.Float + current_stock: DF.Float + description: DF.TextEditor | None + item_name: DF.Data | None + main_item_code: DF.Link | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + rate: DF.Currency + reference_name: DF.Data | None + required_qty: DF.Float + rm_item_code: DF.Link | None + serial_and_batch_bundle: DF.Link | None + serial_no: DF.Text | None + stock_uom: DF.Link | None + subcontracting_order: DF.Link | None + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index f23419e98e..c03fb3ea1f 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -18,6 +18,50 @@ from frappe.utils.user import is_website_user class Issue(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + agreement_status: DF.Literal["First Response Due", "Resolution Due", "Fulfilled", "Failed"] + attachment: DF.Attach | None + avg_response_time: DF.Duration | None + company: DF.Link | None + contact: DF.Link | None + content_type: DF.Data | None + customer: DF.Link | None + customer_name: DF.Data | None + description: DF.TextEditor | None + email_account: DF.Link | None + first_responded_on: DF.Datetime | None + first_response_time: DF.Duration | None + issue_split_from: DF.Link | None + issue_type: DF.Link | None + lead: DF.Link | None + naming_series: DF.Literal["ISS-.YYYY.-"] + on_hold_since: DF.Datetime | None + opening_date: DF.Date | None + opening_time: DF.Time | None + priority: DF.Link | None + project: DF.Link | None + raised_by: DF.Data | None + resolution_by: DF.Datetime | None + resolution_date: DF.Datetime | None + resolution_details: DF.TextEditor | None + resolution_time: DF.Duration | None + response_by: DF.Datetime | None + service_level_agreement: DF.Link | None + service_level_agreement_creation: DF.Datetime | None + status: DF.Literal["Open", "Replied", "On Hold", "Resolved", "Closed"] + subject: DF.Data + total_hold_time: DF.Duration | None + user_resolution_time: DF.Duration | None + via_customer_portal: DF.Check + # end: auto-generated types + def validate(self): if self.is_new() and self.via_customer_portal: self.flags.create_communication = True diff --git a/erpnext/support/doctype/issue_priority/issue_priority.py b/erpnext/support/doctype/issue_priority/issue_priority.py index f21a453d24..e2fbc70c54 100644 --- a/erpnext/support/doctype/issue_priority/issue_priority.py +++ b/erpnext/support/doctype/issue_priority/issue_priority.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class IssuePriority(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/issue_type/issue_type.py b/erpnext/support/doctype/issue_type/issue_type.py index c5adc8b903..b33033b0f0 100644 --- a/erpnext/support/doctype/issue_type/issue_type.py +++ b/erpnext/support/doctype/issue_type/issue_type.py @@ -6,4 +6,15 @@ from frappe.model.document import Document class IssueType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + description: DF.SmallText | None + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py b/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py index 41d4f7f501..59a541423d 100644 --- a/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py +++ b/erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.py @@ -7,4 +7,18 @@ from frappe.model.document import Document class PauseSLAOnStatus(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + status: DF.Literal + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/service_day/service_day.py b/erpnext/support/doctype/service_day/service_day.py index 4a3b1f00db..b90a0776be 100644 --- a/erpnext/support/doctype/service_day/service_day.py +++ b/erpnext/support/doctype/service_day/service_day.py @@ -7,4 +7,20 @@ from frappe.model.document import Document class ServiceDay(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + end_time: DF.Time + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + start_time: DF.Time + workday: DF.Literal["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 6c9bc54f7e..879381c3f2 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -29,6 +29,41 @@ from erpnext.support.doctype.issue.issue import get_holidays class ServiceLevelAgreement(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.support.doctype.pause_sla_on_status.pause_sla_on_status import PauseSLAOnStatus + from erpnext.support.doctype.service_day.service_day import ServiceDay + from erpnext.support.doctype.service_level_priority.service_level_priority import ( + ServiceLevelPriority, + ) + from erpnext.support.doctype.sla_fulfilled_on_status.sla_fulfilled_on_status import ( + SLAFulfilledOnStatus, + ) + + apply_sla_for_resolution: DF.Check + condition: DF.Code | None + default_priority: DF.Link | None + default_service_level_agreement: DF.Check + document_type: DF.Link + enabled: DF.Check + end_date: DF.Date | None + entity: DF.DynamicLink | None + entity_type: DF.Literal["", "Customer", "Customer Group", "Territory"] + holiday_list: DF.Link + pause_sla_on: DF.Table[PauseSLAOnStatus] + priorities: DF.Table[ServiceLevelPriority] + service_level: DF.Data + sla_fulfilled_on: DF.Table[SLAFulfilledOnStatus] + start_date: DF.Date | None + support_and_resolution: DF.Table[ServiceDay] + # end: auto-generated types + def validate(self): self.validate_selected_doctype() self.validate_doc() diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.py b/erpnext/support/doctype/service_level_priority/service_level_priority.py index adb153e256..6ee6fdfcf1 100644 --- a/erpnext/support/doctype/service_level_priority/service_level_priority.py +++ b/erpnext/support/doctype/service_level_priority/service_level_priority.py @@ -7,4 +7,21 @@ from frappe.model.document import Document class ServiceLevelPriority(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + default_priority: DF.Check + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + priority: DF.Link + resolution_time: DF.Duration | None + response_time: DF.Duration + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py b/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py index dbffcb8060..b348bf198b 100644 --- a/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py +++ b/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class SLAFulfilledOnStatus(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + status: DF.Literal + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/support_search_source/support_search_source.py b/erpnext/support/doctype/support_search_source/support_search_source.py index 2270015a19..b4aa952936 100644 --- a/erpnext/support/doctype/support_search_source/support_search_source.py +++ b/erpnext/support/doctype/support_search_source/support_search_source.py @@ -6,4 +6,31 @@ from frappe.model.document import Document class SupportSearchSource(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + base_url: DF.Data | None + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + post_description_key: DF.Data | None + post_route: DF.Data | None + post_route_key_list: DF.Data | None + post_title_key: DF.Data | None + query_route: DF.Data | None + response_result_key_path: DF.Data | None + result_preview_field: DF.Data | None + result_route_field: DF.Data | None + result_title_field: DF.Data | None + search_term_param_name: DF.Data | None + source_doctype: DF.Link | None + source_name: DF.Data | None + source_type: DF.Literal["API", "Link"] + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/support_settings/support_settings.py b/erpnext/support/doctype/support_settings/support_settings.py index ee8a3f5006..3bc1afed7a 100644 --- a/erpnext/support/doctype/support_settings/support_settings.py +++ b/erpnext/support/doctype/support_settings/support_settings.py @@ -6,4 +6,33 @@ from frappe.model.document import Document class SupportSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.support.doctype.support_search_source.support_search_source import ( + SupportSearchSource, + ) + + allow_resetting_service_level_agreement: DF.Check + close_issue_after_days: DF.Int + forum_url: DF.Data | None + get_latest_query: DF.Data | None + get_started_sections: DF.Code | None + greeting_subtitle: DF.Data | None + greeting_title: DF.Data | None + post_description_key: DF.Data | None + post_route_key: DF.Data | None + post_route_string: DF.Data | None + post_title_key: DF.Data | None + response_key_list: DF.Data | None + search_apis: DF.Table[SupportSearchSource] + show_latest_forum_posts: DF.Check + track_service_level_agreement: DF.Check + # end: auto-generated types + pass diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.py b/erpnext/support/doctype/warranty_claim/warranty_claim.py index ff63b77f9e..e0eb5a3ab8 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.py +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.py @@ -10,6 +10,47 @@ from erpnext.utilities.transaction_base import TransactionBase class WarrantyClaim(TransactionBase): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + address_display: DF.SmallText | None + amc_expiry_date: DF.Date | None + amended_from: DF.Link | None + company: DF.Link + complaint: DF.TextEditor + complaint_date: DF.Date + complaint_raised_by: DF.Data | None + contact_display: DF.SmallText | None + contact_email: DF.Data | None + contact_mobile: DF.Data | None + contact_person: DF.Link | None + customer: DF.Link + customer_address: DF.Link | None + customer_group: DF.Link | None + customer_name: DF.Data | None + description: DF.SmallText | None + from_company: DF.Data | None + item_code: DF.Link | None + item_name: DF.Data | None + naming_series: DF.Literal["SER-WRN-.YYYY.-"] + resolution_date: DF.Datetime | None + resolution_details: DF.Text | None + resolved_by: DF.Link | None + serial_no: DF.Link | None + service_address: DF.SmallText | None + status: DF.Literal["", "Open", "Closed", "Work In Progress", "Cancelled"] + territory: DF.Link | None + warranty_amc_status: DF.Literal[ + "", "Under Warranty", "Out of Warranty", "Under AMC", "Out of AMC" + ] + warranty_expiry_date: DF.Date | None + # end: auto-generated types + def validate(self): if session["user"] != "Guest" and not self.customer: frappe.throw(_("Customer is required")) diff --git a/erpnext/telephony/doctype/call_log/call_log.py b/erpnext/telephony/doctype/call_log/call_log.py index 1d6839c1e6..259f55b572 100644 --- a/erpnext/telephony/doctype/call_log/call_log.py +++ b/erpnext/telephony/doctype/call_log/call_log.py @@ -16,6 +16,34 @@ ONGOING_CALL_STATUSES = ["Ringing", "In Progress"] class CallLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.core.doctype.dynamic_link.dynamic_link import DynamicLink + from frappe.types import DF + + call_received_by: DF.Link | None + customer: DF.Link | None + duration: DF.Duration | None + employee_user_id: DF.Link | None + end_time: DF.Datetime | None + id: DF.Data | None + links: DF.Table[DynamicLink] + medium: DF.Data | None + recording_url: DF.Data | None + start_time: DF.Datetime | None + status: DF.Literal[ + "Ringing", "In Progress", "Completed", "Failed", "Busy", "No Answer", "Queued", "Canceled" + ] + summary: DF.SmallText | None + to: DF.Data | None + type: DF.Literal["Incoming", "Outgoing"] + type_of_call: DF.Link | None + # end: auto-generated types + def validate(self): deduplicate_dynamic_links(self) diff --git a/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py index b73f385cc3..ddc86c4096 100644 --- a/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py +++ b/erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.py @@ -7,4 +7,23 @@ from frappe.model.document import Document class IncomingCallHandlingSchedule(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + agent_group: DF.Link + day_of_week: DF.Literal[ + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + ] + from_time: DF.Time + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + to_time: DF.Time + # end: auto-generated types + pass diff --git a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py index 5edf81df73..f80c2d229c 100644 --- a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py +++ b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py @@ -11,6 +11,25 @@ from frappe.model.document import Document class IncomingCallSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.telephony.doctype.incoming_call_handling_schedule.incoming_call_handling_schedule import ( + IncomingCallHandlingSchedule, + ) + + agent_busy_message: DF.Data | None + agent_unavailable_message: DF.Data | None + call_handling_schedule: DF.Table[IncomingCallHandlingSchedule] + call_routing: DF.Literal["Sequential", "Simultaneous"] + greeting_message: DF.Data | None + # end: auto-generated types + def validate(self): """List of validations * Make sure that to time slot is ahead of from time slot in call schedule diff --git a/erpnext/telephony/doctype/telephony_call_type/telephony_call_type.py b/erpnext/telephony/doctype/telephony_call_type/telephony_call_type.py index 944ffef36f..ddb6f93f2e 100644 --- a/erpnext/telephony/doctype/telephony_call_type/telephony_call_type.py +++ b/erpnext/telephony/doctype/telephony_call_type/telephony_call_type.py @@ -6,4 +6,16 @@ from frappe.model.document import Document class TelephonyCallType(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + amended_from: DF.Link | None + call_type: DF.Data + # end: auto-generated types + pass diff --git a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py index 9f9486f580..da3a83a9ee 100644 --- a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py +++ b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py @@ -7,4 +7,19 @@ from frappe.model.document import Document class VoiceCallSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + agent_busy_message: DF.Data | None + agent_unavailable_message: DF.Data | None + call_receiving_device: DF.Literal["Computer", "Phone"] + greeting_message: DF.Data | None + user: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/utilities/doctype/portal_user/portal_user.py b/erpnext/utilities/doctype/portal_user/portal_user.py index 2e0064d198..176e32d6b5 100644 --- a/erpnext/utilities/doctype/portal_user/portal_user.py +++ b/erpnext/utilities/doctype/portal_user/portal_user.py @@ -6,4 +6,18 @@ from frappe.model.document import Document class PortalUser(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + user: DF.Link + # end: auto-generated types + pass diff --git a/erpnext/utilities/doctype/rename_tool/rename_tool.py b/erpnext/utilities/doctype/rename_tool/rename_tool.py index b31574cdc8..19b29f79aa 100644 --- a/erpnext/utilities/doctype/rename_tool/rename_tool.py +++ b/erpnext/utilities/doctype/rename_tool/rename_tool.py @@ -10,6 +10,18 @@ from frappe.model.rename_doc import bulk_rename class RenameTool(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + file_to_rename: DF.Attach | None + select_doctype: DF.Literal + # end: auto-generated types + pass diff --git a/erpnext/utilities/doctype/sms_log/sms_log.py b/erpnext/utilities/doctype/sms_log/sms_log.py index 85140f366f..8e4c248fd6 100644 --- a/erpnext/utilities/doctype/sms_log/sms_log.py +++ b/erpnext/utilities/doctype/sms_log/sms_log.py @@ -6,4 +6,21 @@ from frappe.model.document import Document class SMSLog(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + message: DF.SmallText | None + no_of_requested_sms: DF.Int + no_of_sent_sms: DF.Int + requested_numbers: DF.Code | None + sender_name: DF.Data | None + sent_on: DF.Date | None + sent_to: DF.Code | None + # end: auto-generated types + pass diff --git a/erpnext/utilities/doctype/video/video.py b/erpnext/utilities/doctype/video/video.py index 62033a5e18..1a9fe19732 100644 --- a/erpnext/utilities/doctype/video/video.py +++ b/erpnext/utilities/doctype/video/video.py @@ -15,6 +15,28 @@ from pyyoutube import Api class Video(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + comment_count: DF.Float + description: DF.TextEditor + dislike_count: DF.Float + duration: DF.Duration | None + image: DF.AttachImage | None + like_count: DF.Float + provider: DF.Literal["YouTube", "Vimeo"] + publish_date: DF.Date | None + title: DF.Data + url: DF.Data + view_count: DF.Float + youtube_video_id: DF.Data | None + # end: auto-generated types + def validate(self): if self.provider == "YouTube" and is_tracking_enabled(): self.set_video_id() diff --git a/erpnext/utilities/doctype/video_settings/video_settings.py b/erpnext/utilities/doctype/video_settings/video_settings.py index 9bc7972bb3..762a795a73 100644 --- a/erpnext/utilities/doctype/video_settings/video_settings.py +++ b/erpnext/utilities/doctype/video_settings/video_settings.py @@ -9,6 +9,19 @@ from frappe.model.document import Document class VideoSettings(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + api_key: DF.Data | None + enable_youtube_tracking: DF.Check + frequency: DF.Literal["30 mins", "1 hr", "6 hrs", "Daily"] + # end: auto-generated types + def validate(self): self.validate_youtube_api_key() From e4bdd3a28d7fa29b0460ad6661ff39a219c1fc5c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 30 Nov 2023 15:57:57 +0530 Subject: [PATCH 173/202] refactor: use flt on outstanding on AR/AP summary report --- .../accounts_receivable_summary.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index d50cf0708e..22b5c6ba76 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -8,7 +8,7 @@ from frappe.utils import cint, flt from erpnext.accounts.party import get_partywise_advanced_payment_amount from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport -from erpnext.accounts.utils import get_party_types_from_account_type +from erpnext.accounts.utils import get_currency_precision, get_party_types_from_account_type def execute(filters=None): @@ -34,6 +34,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): def get_data(self, args): self.data = [] self.receivables = ReceivablePayableReport(self.filters).run(args)[1] + self.currency_precision = get_currency_precision() or 2 self.get_party_total(args) @@ -57,7 +58,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): gl_balance_map = get_gl_balance(self.filters.report_date, self.filters.company) for party, party_dict in self.party_total.items(): - if party_dict.outstanding == 0: + if flt(party_dict.outstanding, self.currency_precision) == 0: continue row = frappe._dict() From ae294ee4702fa8e0367c07c881d632811beb67ae Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 30 Nov 2023 16:16:12 +0530 Subject: [PATCH 174/202] fix(ux): make PR `rate` field read-only having PO ref --- .../doctype/purchase_receipt_item/purchase_receipt_item.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index a86e63daf4..7344d2a599 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -359,6 +359,7 @@ "oldfieldtype": "Currency", "options": "currency", "print_width": "100px", + "read_only_depends_on": "eval: (!parent.is_return && doc.purchase_order && doc.purchase_order_item)", "width": "100px" }, { @@ -1103,7 +1104,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-28 13:37:29.245204", + "modified": "2023-11-30 16:12:02.364608", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From 3d4156cc7d90522f37f4c91e4ccf4145412109a9 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 30 Nov 2023 16:28:03 +0530 Subject: [PATCH 175/202] fix(ux): make PI `rate` field read-only having PR ref --- .../doctype/purchase_invoice_item/purchase_invoice_item.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 71796c9918..7cad3ae1c0 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -288,6 +288,7 @@ "oldfieldname": "import_rate", "oldfieldtype": "Currency", "options": "currency", + "read_only_depends_on": "eval: (!parent.is_return && doc.purchase_receipt && doc.pr_detail)", "reqd": 1 }, { @@ -918,7 +919,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:33:48.547297", + "modified": "2023-11-30 16:26:05.629780", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", From 691e3bb24fe62624cd2c39f88e7663ff690b0f1c Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 30 Nov 2023 10:25:22 +0530 Subject: [PATCH 176/202] fix: incorrect requested quantity for the subcontracting order --- .../doctype/purchase_order/purchase_order.py | 33 +++++------ .../controllers/subcontracting_controller.py | 17 ++++++ .../subcontracting_order.py | 23 ++++++++ .../test_subcontracting_order.py | 56 +++++++++++++++++++ .../subcontracting_order_item.json | 42 +++++++++++++- .../subcontracting_order_service_item.json | 33 ++++++++++- 6 files changed, 179 insertions(+), 25 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 5f19657a05..595722d1ee 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -221,6 +221,10 @@ class PurchaseOrder(BuyingController): self.reset_default_field_value("set_warehouse", "items", "warehouse") def validate_with_previous_doc(self): + mri_compare_fields = [["project", "="], ["item_code", "="]] + if self.is_subcontracted: + mri_compare_fields = [["project", "="]] + super(PurchaseOrder, self).validate_with_previous_doc( { "Supplier Quotation": { @@ -243,7 +247,7 @@ class PurchaseOrder(BuyingController): }, "Material Request Item": { "ref_dn_field": "material_request_item", - "compare_fields": [["project", "="], ["item_code", "="]], + "compare_fields": mri_compare_fields, "is_child_table": True, }, } @@ -417,23 +421,6 @@ class PurchaseOrder(BuyingController): check_list.append(d.material_request) check_on_hold_or_closed_status("Material Request", d.material_request) - def update_requested_qty(self): - material_request_map = {} - for d in self.get("items"): - if d.material_request_item: - material_request_map.setdefault(d.material_request, []).append(d.material_request_item) - - for mr, mr_item_rows in material_request_map.items(): - if mr and mr_item_rows: - mr_obj = frappe.get_doc("Material Request", mr) - - if mr_obj.status in ["Stopped", "Cancelled"]: - frappe.throw( - _("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError - ) - - mr_obj.update_requested_qty(mr_item_rows) - def update_ordered_qty(self, po_item_rows=None): """update requested qty (before ordered_qty is updated)""" item_wh_list = [] @@ -475,7 +462,9 @@ class PurchaseOrder(BuyingController): self.update_status_updater() self.update_prevdoc_status() - self.update_requested_qty() + if not self.is_subcontracted or self.is_old_subcontracting_flow: + self.update_requested_qty() + self.update_ordered_qty() self.validate_budget() self.update_reserved_qty_for_subcontract() @@ -509,7 +498,9 @@ class PurchaseOrder(BuyingController): # Must be called after updating ordered qty in Material Request # bin uses Material Request Items to recalculate & update - self.update_requested_qty() + if not self.is_subcontracted or self.is_old_subcontracting_flow: + self.update_requested_qty() + self.update_ordered_qty() self.update_blanket_order() @@ -875,6 +866,8 @@ def get_mapped_subcontracting_order(source_name, target_doc=None): "doctype": "Subcontracting Order Service Item", "field_map": { "name": "purchase_order_item", + "material_request": "material_request", + "material_request_item": "material_request_item", }, "field_no_map": [], }, diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index 3d55a087bd..b52fbad1f0 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -952,6 +952,23 @@ class SubcontractingController(StockController): return self._sub_contracted_items + def update_requested_qty(self): + material_request_map = {} + for d in self.get("items"): + if d.material_request_item: + material_request_map.setdefault(d.material_request, []).append(d.material_request_item) + + for mr, mr_item_rows in material_request_map.items(): + if mr and mr_item_rows: + mr_obj = frappe.get_doc("Material Request", mr) + + if mr_obj.status in ["Stopped", "Cancelled"]: + frappe.throw( + _("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError + ) + + mr_obj.update_requested_qty(mr_item_rows) + def get_item_details(items): item = frappe.qb.DocType("Item") diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 68d98fc734..6c187f8368 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -80,6 +80,23 @@ class SubcontractingOrder(SubcontractingController): transaction_date: DF.Date # end: auto-generated types + def __init__(self, *args, **kwargs): + super(SubcontractingOrder, self).__init__(*args, **kwargs) + + self.status_updater = [ + { + "source_dt": "Subcontracting Order Item", + "target_dt": "Material Request Item", + "join_field": "material_request_item", + "target_field": "ordered_qty", + "target_parent_dt": "Material Request", + "target_parent_field": "per_ordered", + "target_ref_field": "stock_qty", + "source_field": "qty", + "percent_join_field": "material_request", + } + ] + def before_validate(self): super(SubcontractingOrder, self).before_validate() @@ -93,11 +110,15 @@ class SubcontractingOrder(SubcontractingController): self.reset_default_field_value("set_warehouse", "items", "warehouse") def on_submit(self): + self.update_prevdoc_status() + self.update_requested_qty() self.update_ordered_qty_for_subcontracting() self.update_reserved_qty_for_subcontracting() self.update_status() def on_cancel(self): + self.update_prevdoc_status() + self.update_requested_qty() self.update_ordered_qty_for_subcontracting() self.update_reserved_qty_for_subcontracting() self.update_status() @@ -237,6 +258,8 @@ class SubcontractingOrder(SubcontractingController): "stock_uom": item.stock_uom, "bom": bom, "purchase_order_item": si.purchase_order_item, + "material_request": si.material_request, + "material_request_item": si.material_request_item, } ) else: diff --git a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py index 3557858935..37dabf1bfb 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py @@ -628,6 +628,62 @@ class TestSubcontractingOrder(FrappeTestCase): self.assertEqual(ordered_qty + 10, new_ordered_qty) + def test_requested_qty_for_subcontracting_order(self): + from erpnext.stock.doctype.material_request.material_request import make_purchase_order + from erpnext.stock.doctype.material_request.test_material_request import make_material_request + + requested_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="indented_qty", + ) + requested_qty = flt(requested_qty) + + mr = make_material_request( + item_code="Subcontracted Item SA8", + material_request_type="Purchase", + qty=10, + ) + + self.assertTrue(mr.docstatus == 1) + + new_requested_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="indented_qty", + ) + new_requested_qty = flt(new_requested_qty) + + self.assertEqual(requested_qty + 10, new_requested_qty) + + po = make_purchase_order(mr.name) + po.is_subcontracted = 1 + po.supplier = "_Test Supplier" + po.items[0].fg_item = "Subcontracted Item SA8" + po.items[0].fg_item_qty = 10 + po.items[0].item_code = "Subcontracted Service Item 8" + po.items[0].item_name = "Subcontracted Service Item 8" + po.items[0].qty = 10 + po.supplier_warehouse = "_Test Warehouse 1 - _TC" + po.save() + po.submit() + + self.assertTrue(po.items[0].material_request) + self.assertTrue(po.items[0].material_request_item) + + sco = create_subcontracting_order(po_name=po.name) + self.assertTrue(sco.items[0].material_request) + self.assertTrue(sco.items[0].material_request_item) + + new_requested_qty = frappe.db.get_value( + "Bin", + filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, + fieldname="indented_qty", + ) + new_requested_qty = flt(new_requested_qty) + + self.assertEqual(requested_qty, new_requested_qty) + def create_subcontracting_order(**args): args = frappe._dict(args) diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json index 911e903d23..1ca90c3165 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -40,13 +40,18 @@ "manufacture_section", "manufacturer", "manufacturer_part_no", + "column_break_impp", + "reference_section", + "material_request", + "column_break_fpyl", + "material_request_item", "accounting_dimensions_section", "cost_center", "dimension_col_break", "project", "section_break_34", - "page_break", - "purchase_order_item" + "purchase_order_item", + "page_break" ], "fields": [ { @@ -334,6 +339,37 @@ "label": "Project", "options": "Project" }, + { + "fieldname": "column_break_impp", + "fieldtype": "Column Break" + }, + { + "fieldname": "material_request", + "fieldtype": "Link", + "label": "Material Request", + "no_copy": 1, + "options": "Material Request", + "read_only": 1, + "search_index": 1 + }, + { + "fieldname": "material_request_item", + "fieldtype": "Data", + "label": "Material Request Item", + "no_copy": 1, + "read_only": 1, + "search_index": 1 + }, + { + "collapsible": 1, + "fieldname": "reference_section", + "fieldtype": "Section Break", + "label": "Reference" + }, + { + "fieldname": "column_break_fpyl", + "fieldtype": "Column Break" + }, { "fieldname": "purchase_order_item", "fieldtype": "Data", @@ -348,7 +384,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-23 16:56:22.182698", + "modified": "2023-11-30 15:29:43.744618", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Item", diff --git a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json index dc18543b04..f1e94e125a 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json @@ -19,7 +19,11 @@ "fg_item", "column_break_12", "fg_item_qty", - "purchase_order_item" + "purchase_order_item", + "section_break_kphn", + "material_request", + "column_break_piqi", + "material_request_item" ], "fields": [ { @@ -122,11 +126,36 @@ "no_copy": 1, "read_only": 1, "search_index": 1 + }, + { + "collapsible": 1, + "fieldname": "section_break_kphn", + "fieldtype": "Section Break", + "label": "Reference" + }, + { + "fieldname": "material_request", + "fieldtype": "Link", + "label": "Material Request", + "no_copy": 1, + "options": "Material Request", + "read_only": 1 + }, + { + "fieldname": "column_break_piqi", + "fieldtype": "Column Break" + }, + { + "fieldname": "material_request_item", + "fieldtype": "Data", + "label": "Material Request Item", + "no_copy": 1, + "read_only": 1 } ], "istable": 1, "links": [], - "modified": "2023-11-23 17:05:04.561948", + "modified": "2023-11-30 13:29:31.017440", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Service Item", From 54f7cf59fddd61a8e6ed1a21de21a540e8499793 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 Dec 2023 10:37:35 +0530 Subject: [PATCH 177/202] chore: version bump --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 3e418c48cf..5c58f84be2 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import inspect import frappe -__version__ = "15.0.0-dev" +__version__ = "16.0.0-dev" def get_default_company(user=None): From 3a66aefd2c6aedc1b7b6017c174261c1ed4c2907 Mon Sep 17 00:00:00 2001 From: Gughan Ravikumar Date: Fri, 1 Dec 2023 11:07:17 +0530 Subject: [PATCH 178/202] fix: show item name as title instead of item group in BOM (#38478) Item fields in BOM used to show Item Group when Items were set to show title as link fields. Now they show Item Name instead --- erpnext/manufacturing/doctype/bom/bom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index d48908edfb..71015a414d 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1395,7 +1395,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): order_by = "idx desc, name, item_name" - fields = ["name", "item_group", "item_name", "description"] + fields = ["name", "item_name", "item_group", "description"] fields.extend( [field for field in searchfields if not field in ["name", "item_group", "description"]] ) From 60a81a563ef99ae892a821d27ae298730a0e2563 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 1 Dec 2023 11:27:54 +0530 Subject: [PATCH 179/202] fix: `AttributeError` while saving Purchase Invoice --- erpnext/controllers/buying_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 68ad97d7ba..54c97b4208 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -440,7 +440,7 @@ class BuyingController(SubcontractingController): if allow_to_edit_stock_qty: d.stock_qty = flt(d.stock_qty, d.precision("stock_qty")) - if d.get("received_stock_qty"): + if d.get("received_stock_qty") and d.meta.get_field("received_stock_qty"): d.received_stock_qty = flt(d.received_stock_qty, d.precision("received_stock_qty")) def validate_purchase_return(self): From e2a519464b3214b0a6594498dc86bc3af15197c3 Mon Sep 17 00:00:00 2001 From: NandhiniDevi <95607404+Nandhinidevi123@users.noreply.github.com> Date: Fri, 1 Dec 2023 11:34:38 +0530 Subject: [PATCH 180/202] add supplier group filter in purchase register (#38421) * add supplier group field in purchase register * Update purchase_register.js --- .../doctype/purchase_invoice/purchase_invoice.json | 12 ++++++++++-- .../report/purchase_register/purchase_register.js | 6 ++++++ .../report/purchase_register/purchase_register.py | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 09bffff6da..f85fc878ab 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -189,6 +189,7 @@ "additional_info_section", "is_internal_supplier", "represents_company", + "supplier_group", "column_break_147", "inter_company_invoice_reference", "is_old_subcontracting_flow", @@ -1598,13 +1599,20 @@ "fieldtype": "Check", "label": "Use Transaction Date Exchange Rate", "read_only": 1 + }, + { + "fetch_from": "supplier.supplier_group", + "fieldname": "supplier_group", + "fieldtype": "Link", + "label": "Supplier Group", + "options": "Supplier Group" } ], "icon": "fa fa-file-text", "idx": 204, "is_submittable": 1, "links": [], - "modified": "2023-11-03 15:47:30.319200", + "modified": "2023-11-29 15:35:44.697496", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", @@ -1667,4 +1675,4 @@ "timeline_field": "supplier", "title_field": "title", "track_changes": 1 -} +} \ No newline at end of file diff --git a/erpnext/accounts/report/purchase_register/purchase_register.js b/erpnext/accounts/report/purchase_register/purchase_register.js index 57cb703bae..cf11ed0986 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.js +++ b/erpnext/accounts/report/purchase_register/purchase_register.js @@ -22,6 +22,12 @@ frappe.query_reports["Purchase Register"] = { "fieldtype": "Link", "options": "Supplier" }, + { + "fieldname":"supplier_group", + "label": __("Supplier Group"), + "fieldtype": "Link", + "options": "Supplier Group" + }, { "fieldname":"company", "label": __("Company"), diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 162e5b57c7..9721987f89 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -407,6 +407,8 @@ def get_invoices(filters, additional_query_columns): if filters.get("supplier"): query = query.where(pi.supplier == filters.supplier) + if filters.get("supplier_group"): + query = query.where(pi.supplier_group == filters.supplier_group) query = get_conditions(filters, query, "Purchase Invoice") From eecf9cd1d88987cfe6903c678216ba5af1e5d231 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 11:43:57 +0530 Subject: [PATCH 181/202] fix(test): use correct account type for testing --- erpnext/accounts/doctype/payment_entry/test_payment_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index e77f4632b2..5b8a46b2c2 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -1368,7 +1368,7 @@ class TestPaymentEntry(FrappeTestCase): parent_account="Current Assets - _TC", account_name="Advances Received", company=company, - account_type="Liability", + account_type="Receivable", ) frappe.db.set_value( From 080aa304077548a39678aabc3a33bcf3fb243a02 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 12:09:37 +0530 Subject: [PATCH 182/202] refactor(test): filter on document names --- erpnext/accounts/doctype/payment_entry/test_payment_entry.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 5b8a46b2c2..8a03dd7278 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -1419,6 +1419,8 @@ class TestPaymentEntry(FrappeTestCase): pr.party = "_Test Customer" pr.receivable_payable_account = si.debit_to pr.default_advance_account = advance_account + pr.payment_name = pe.name + pr.invoice_name = si.name pr.get_unreconciled_entries() self.assertEqual(len(pr.invoices), 1) From 961bdf0d247fc58f7d091459bb4d0059bd6ea791 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 12:13:00 +0530 Subject: [PATCH 183/202] refactor: handle forex payment advance entries --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index e2e655befb..f1064ad535 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1057,17 +1057,19 @@ class PaymentEntry(AccountsController): dr_or_cr = "credit" if self.payment_type == "Receive" else "debit" if self.book_advance_payments_in_separate_party_account: + gle = party_gl_dict.copy() + if self.payment_type == "Receive": amount = self.base_paid_amount else: amount = self.base_received_amount - gle = party_gl_dict.copy() + exchange_rate = self.get_exchange_rate() + amount_in_account_currency = amount * exchange_rate gle.update( { dr_or_cr: amount, - # TODO: handle multi currency payments - dr_or_cr + "_in_account_currency": amount, + dr_or_cr + "_in_account_currency": amount_in_account_currency, "against_voucher_type": "Payment Entry", "against_voucher": self.name, "cost_center": self.cost_center, From b24e28953b6e085705630e2d8474492777732a9e Mon Sep 17 00:00:00 2001 From: Ernesto Ruiz Date: Fri, 1 Dec 2023 01:11:14 -0600 Subject: [PATCH 184/202] chore: add translate function to email subject in digest frecuency (#38474) chore: add translate function to email subject in digest frecuency --- erpnext/setup/doctype/email_digest/email_digest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 53b353dd8a..22bdf50473 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -123,7 +123,7 @@ class EmailDigest(Document): if msg_for_this_recipient and row.recipient in valid_users: frappe.sendmail( recipients=row.recipient, - subject=_("{0} Digest").format(self.frequency), + subject=_("{0} Digest").format(_(self.frequency)), message=msg_for_this_recipient, reference_doctype=self.doctype, reference_name=self.name, From 68f5dd3e7b836c71f73cef210fcb4d72dc58e557 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 1 Dec 2023 14:45:01 +0530 Subject: [PATCH 185/202] fix: don't update previous doc on rate change --- erpnext/controllers/accounts_controller.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index f551133a28..4ab9e24a42 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -3248,7 +3248,10 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil if parent_doctype == "Purchase Order": update_last_purchase_rate(parent, is_submit=1) - parent.update_prevdoc_status() + + if any_qty_changed or items_added_or_removed or any_conversion_factor_changed: + parent.update_prevdoc_status() + parent.update_requested_qty() parent.update_ordered_qty() parent.update_ordered_and_reserved_qty() From 6bc40373f234af10ce4490529e96c5348d27b7df Mon Sep 17 00:00:00 2001 From: Sherin KR Date: Fri, 1 Dec 2023 19:07:28 +0530 Subject: [PATCH 186/202] chore: changed sort_order to DESC for customer (#38498) --- erpnext/selling/doctype/customer/customer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 3b97123113..31bbbcf51b 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -665,7 +665,7 @@ "search_fields": "customer_name,customer_group,territory, mobile_no,primary_address", "show_name_in_global_search": 1, "sort_field": "modified", - "sort_order": "ASC", + "sort_order": "DESC", "states": [], "title_field": "customer_name", "track_changes": 1 From 5e9016ffab34df9609a75a7cbbaabbb37e7159d6 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 1 Dec 2023 21:42:22 +0530 Subject: [PATCH 187/202] fix: validation error has not throw for the batch (#38494) * fix: validation error has not throw for the batch * chore: fix test cases --- .../sales_invoice/test_sales_invoice.py | 1 + erpnext/controllers/buying_controller.py | 2 ++ erpnext/controllers/selling_controller.py | 1 + .../controllers/subcontracting_controller.py | 1 + .../serial_and_batch_bundle.py | 1 + .../stock/doctype/stock_entry/stock_entry.py | 1 + .../doctype/stock_entry/test_stock_entry.py | 36 +++++++++++++++++++ .../test_stock_ledger_entry.py | 4 +-- erpnext/stock/serial_batch_bundle.py | 8 +++-- 9 files changed, 50 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 840a31942a..e9b71ddffd 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2629,6 +2629,7 @@ class TestSalesInvoice(FrappeTestCase): "voucher_type": "Sales Invoice", "voucher_no": si.name, "allow_zero_valuation": d.get("allow_zero_valuation"), + "voucher_detail_no": d.name, }, raise_error_if_no_rate=False, ) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 54c97b4208..3d863e9b87 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -118,6 +118,7 @@ class BuyingController(SubcontractingController): "company": self.company, "voucher_type": self.doctype, "voucher_no": self.name, + "voucher_detail_no": row.name, }, raise_error_if_no_rate=False, ) @@ -373,6 +374,7 @@ class BuyingController(SubcontractingController): "voucher_type": self.doctype, "voucher_no": self.name, "allow_zero_valuation": d.get("allow_zero_valuation"), + "voucher_detail_no": d.name, }, raise_error_if_no_rate=False, ) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 5575a24b35..fdadb30e93 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -444,6 +444,7 @@ class SellingController(StockController): "company": self.company, "voucher_type": self.doctype, "voucher_no": self.name, + "voucher_detail_no": d.name, "allow_zero_valuation": d.get("allow_zero_valuation"), }, raise_error_if_no_rate=False, diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index b52fbad1f0..9555902a74 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -880,6 +880,7 @@ class SubcontractingController(StockController): "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * item.consumed_qty, + "voucher_detail_no": item.name, "serial_and_batch_bundle": item.serial_and_batch_bundle, } ) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index f0cff21a42..88929eaaa0 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -252,6 +252,7 @@ class SerialandBatchBundle(Document): "serial_nos": [row.serial_no for row in self.entries if row.serial_no], "batch_nos": {row.batch_no: row for row in self.entries if row.batch_no}, "voucher_type": self.voucher_type, + "voucher_detail_no": self.voucher_detail_no, } ) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 8158b99f93..3baafd77ba 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -883,6 +883,7 @@ class StockEntry(StockController): "company": self.company, "allow_zero_valuation": item.allow_zero_valuation_rate, "serial_and_batch_bundle": item.serial_and_batch_bundle, + "voucher_detail_no": item.name, } ) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index b640983a09..eb1c7a85eb 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -936,6 +936,42 @@ class TestStockEntry(FrappeTestCase): stock_entry.insert() self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items]) + def test_nagative_stock_for_batch(self): + item = make_item( + "_Test Batch Negative Item", + { + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "B-BATCH-.##", + "is_stock_item": 1, + }, + ) + + make_stock_entry(item_code=item.name, target="_Test Warehouse - _TC", qty=50, basic_rate=100) + + ste = frappe.new_doc("Stock Entry") + ste.purpose = "Material Issue" + ste.company = "_Test Company" + for qty in [50, 20, 30]: + ste.append( + "items", + { + "item_code": item.name, + "s_warehouse": "_Test Warehouse - _TC", + "qty": qty, + "uom": item.stock_uom, + "stock_uom": item.stock_uom, + "conversion_factor": 1, + "transfer_qty": qty, + }, + ) + + ste.set_stock_entry_type() + ste.insert() + make_stock_entry(item_code=item.name, target="_Test Warehouse - _TC", qty=50, basic_rate=100) + + self.assertRaises(frappe.ValidationError, ste.submit) + def test_same_serial_nos_in_repack_or_manufacture_entries(self): s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC") serial_nos = get_serial_nos_from_bundle(s1.get("items")[0].serial_and_batch_bundle) diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py index f7c6ffece8..d8a3f2e33c 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py @@ -485,9 +485,9 @@ class TestStockLedgerEntry(FrappeTestCase, StockTestMixin): dns = create_delivery_note_entries_for_batchwise_item_valuation_test(dn_entry_list) sle_details = fetch_sle_details_for_doc_list(dns, ["stock_value_difference"]) svd_list = [-1 * d["stock_value_difference"] for d in sle_details] - expected_incoming_rates = expected_abs_svd = sorted([75.0, 125.0, 75.0, 125.0]) + expected_incoming_rates = expected_abs_svd = [75.0, 125.0, 75.0, 125.0] - self.assertEqual(expected_abs_svd, sorted(svd_list), "Incorrect 'Stock Value Difference' values") + self.assertEqual(expected_abs_svd, svd_list, "Incorrect 'Stock Value Difference' values") for dn, incoming_rate in zip(dns, expected_incoming_rates): self.assertTrue( dn.items[0].incoming_rate in expected_abs_svd, diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index de28be1c35..0c187923e3 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -406,7 +406,7 @@ class SerialNoValuation(DeprecatedSerialNoValuation): .orderby(bundle.posting_date, bundle.posting_time, bundle.creation) ) - # Important to exclude the current voucher + # Important to exclude the current voucher to calculate correct the stock value difference if self.sle.voucher_no: query = query.where(bundle.voucher_no != self.sle.voucher_no) @@ -539,8 +539,10 @@ class BatchNoValuation(DeprecatedBatchNoValuation): .groupby(child.batch_no) ) - # Important to exclude the current voucher - if self.sle.voucher_no: + # Important to exclude the current voucher detail no / voucher no to calculate the correct stock value difference + if self.sle.voucher_detail_no: + query = query.where(parent.voucher_detail_no != self.sle.voucher_detail_no) + elif self.sle.voucher_no: query = query.where(parent.voucher_no != self.sle.voucher_no) if timestamp_condition: From 023bc36592dc2ba4ae6eef21f48d70a6c4d98c0c Mon Sep 17 00:00:00 2001 From: Corin Wenger <119770691+strongjaw15@users.noreply.github.com> Date: Sat, 2 Dec 2023 08:54:46 -0500 Subject: [PATCH 188/202] fix: Move SMS Log module from ERPNext to Frappe (#38506) Move SMS Log module from ERPNext to Frappe SMS Log module moved to Frappe Core from ERPNext Utilities so that Frappe send_sms() works sans-ERPNext. --- erpnext/utilities/doctype/sms_log/README.md | 1 - erpnext/utilities/doctype/sms_log/__init__.py | 0 erpnext/utilities/doctype/sms_log/sms_log.js | 8 - .../utilities/doctype/sms_log/sms_log.json | 371 ------------------ erpnext/utilities/doctype/sms_log/sms_log.py | 26 -- .../utilities/doctype/sms_log/test_sms_log.py | 10 - 6 files changed, 416 deletions(-) delete mode 100644 erpnext/utilities/doctype/sms_log/README.md delete mode 100644 erpnext/utilities/doctype/sms_log/__init__.py delete mode 100644 erpnext/utilities/doctype/sms_log/sms_log.js delete mode 100644 erpnext/utilities/doctype/sms_log/sms_log.json delete mode 100644 erpnext/utilities/doctype/sms_log/sms_log.py delete mode 100644 erpnext/utilities/doctype/sms_log/test_sms_log.py diff --git a/erpnext/utilities/doctype/sms_log/README.md b/erpnext/utilities/doctype/sms_log/README.md deleted file mode 100644 index 9ee2b79ef0..0000000000 --- a/erpnext/utilities/doctype/sms_log/README.md +++ /dev/null @@ -1 +0,0 @@ -Log of SMS sent via SMS Center. \ No newline at end of file diff --git a/erpnext/utilities/doctype/sms_log/__init__.py b/erpnext/utilities/doctype/sms_log/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/utilities/doctype/sms_log/sms_log.js b/erpnext/utilities/doctype/sms_log/sms_log.js deleted file mode 100644 index f5358e8409..0000000000 --- a/erpnext/utilities/doctype/sms_log/sms_log.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('SMS Log', { - refresh: function(frm) { - - } -}); diff --git a/erpnext/utilities/doctype/sms_log/sms_log.json b/erpnext/utilities/doctype/sms_log/sms_log.json deleted file mode 100644 index 269094b8f1..0000000000 --- a/erpnext/utilities/doctype/sms_log/sms_log.json +++ /dev/null @@ -1,371 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "SYS-SMS-.#####", - "beta": 0, - "creation": "2012-03-27 14:36:47", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "editable_grid": 0, - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sender_name", - "fieldtype": "Data", - "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": "Sender Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sent_on", - "fieldtype": "Date", - "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": "Sent On", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break0", - "fieldtype": "Column Break", - "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, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, - "width": "50%" - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "message", - "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": "Message", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sec_break1", - "fieldtype": "Section Break", - "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, - "length": 0, - "no_copy": 0, - "options": "Simple", - "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 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "no_of_requested_sms", - "fieldtype": "Int", - "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": "No of Requested SMS", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "requested_numbers", - "fieldtype": "Code", - "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": "Requested Numbers", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "fieldtype": "Column Break", - "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, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, - "width": "50%" - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "no_of_sent_sms", - "fieldtype": "Int", - "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": "No of Sent SMS", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sent_to", - "fieldtype": "Code", - "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": "Sent To", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-mobile-phone", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-08-21 16:15:40.898889", - "modified_by": "Administrator", - "module": "Utilities", - "name": "SMS Log", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} \ No newline at end of file diff --git a/erpnext/utilities/doctype/sms_log/sms_log.py b/erpnext/utilities/doctype/sms_log/sms_log.py deleted file mode 100644 index 8e4c248fd6..0000000000 --- a/erpnext/utilities/doctype/sms_log/sms_log.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - - -from frappe.model.document import Document - - -class SMSLog(Document): - # begin: auto-generated types - # This code is auto-generated. Do not modify anything in this block. - - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from frappe.types import DF - - message: DF.SmallText | None - no_of_requested_sms: DF.Int - no_of_sent_sms: DF.Int - requested_numbers: DF.Code | None - sender_name: DF.Data | None - sent_on: DF.Date | None - sent_to: DF.Code | None - # end: auto-generated types - - pass diff --git a/erpnext/utilities/doctype/sms_log/test_sms_log.py b/erpnext/utilities/doctype/sms_log/test_sms_log.py deleted file mode 100644 index 3ff0202388..0000000000 --- a/erpnext/utilities/doctype/sms_log/test_sms_log.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - -# test_records = frappe.get_test_records('SMS Log') - - -class TestSMSLog(unittest.TestCase): - pass From a1e0197a8bc569a334503b6c3ba024feb3572d0f Mon Sep 17 00:00:00 2001 From: noec764 <58433943+noec764@users.noreply.github.com> Date: Sat, 2 Dec 2023 15:19:13 +0100 Subject: [PATCH 189/202] fix: Add missing french translations (#38368) fix: Add missing french translation Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com> --- erpnext/translations/fr.csv | 79 ++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index 5c34759a70..a7111234af 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -134,7 +134,7 @@ Advance amount cannot be greater than {0} {1},Montant de l'avance ne peut être Advertising,Publicité, Aerospace,Aérospatial, Against,Contre, -Against Account,Pour le Compte, +Against Account,Contrepartie, Against Journal Entry {0} does not have any unmatched {1} entry,L'Écriture de Journal {0} n'a pas d'entrée non associée {1}, Against Journal Entry {0} is already adjusted against some other voucher,L'Écriture de Journal {0} est déjà ajustée par un autre bon, Against Supplier Invoice {0} dated {1},Pour la Facture Fournisseur {0} datée {1}, @@ -2969,7 +2969,7 @@ Import Successful,Importation réussie, Please save first,S'il vous plaît enregistrer en premier, Price not found for item {0} in price list {1},Prix non trouvé pour l'article {0} dans la liste de prix {1}, Warehouse Type,Type d'entrepôt, -'Date' is required,'Date' est requis, +'Date' is required,La 'date' est obligatoire, Budgets,Budgets, Bundle Qty,Quantité de paquet, Company GSTIN,GSTIN de la Société, @@ -3002,7 +3002,7 @@ Account: {0} is capital Work in progress and can not be updated by Journa Account: {0} is not permitted under Payment Entry,Compte: {0} n'est pas autorisé sous Saisie du paiement., Accounting Dimension {0} is required for 'Balance Sheet' account {1}.,La dimension de comptabilité {0} est requise pour le compte "Bilan" {1}., Accounting Dimension {0} is required for 'Profit and Loss' account {1}.,La dimension de comptabilité {0} est requise pour le compte 'Bénéfices et pertes' {1}., -Accounting Masters,Maîtres Comptables, +Accounting Masters,Données de base, Accounting Period overlaps with {0},La période comptable chevauche avec {0}, Add to Featured Item,Ajouter à l'article en vedette, Add your review,Ajouter votre avis, @@ -3701,7 +3701,7 @@ Mandatory For Profit and Loss Account,Compte de résultat obligatoire, Accounting Period,Période comptable, Period Name,Nom de période, Closed Documents,Documents fermés, -Accounts Settings,Paramètres des Comptes, +Accounts Settings,Paramètres de comptabilité, Settings for Accounts,Paramètres des Comptes, Make Accounting Entry For Every Stock Movement,Faites une Écriture Comptable Pour Chaque Mouvement du Stock, Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts,Les utilisateurs ayant ce rôle sont autorisés à définir les comptes gelés et à créer / modifier des écritures comptables sur des comptes gelés, @@ -3718,7 +3718,7 @@ Show Payment Schedule in Print,Afficher le calendrier de paiement dans Imprimer, Currency Exchange Settings,Paramètres d'échange de devises, Allow Stale Exchange Rates,Autoriser les Taux de Change Existants, Stale Days,Journées Passées, -Report Settings,Paramètres de rapport, +Report Settings,Paramètres des rapports, Use Custom Cash Flow Format,Utiliser le format de flux de trésorerie personnalisé, Allowed To Transact With,Autorisé à faire affaire avec, SWIFT number,Numéro rapide, @@ -4321,7 +4321,7 @@ Redemption Account,Compte pour l'échange, Redemption Cost Center,Centre de coûts pour l'échange, In Words will be visible once you save the Sales Invoice.,En Toutes Lettres. Sera visible une fois que vous enregistrerez la Facture., Allocate Advances Automatically (FIFO),Allouer automatiquement les avances (FIFO), -Get Advances Received,Obtenir Acomptes Reçus, +Get Advances Received,Obtenir les paiements des avances, Base Change Amount (Company Currency),Montant de Base à Rendre (Devise de la Société), Write Off Outstanding Amount,Encours de Reprise, Terms and Conditions Details,Détails des Termes et Conditions, @@ -4329,7 +4329,7 @@ Is Internal Customer,Est un client interne, Is Discounted,Est réduit, Unpaid and Discounted,Non payé et à prix réduit, Overdue and Discounted,En retard et à prix réduit, -Accounting Details,Détails Comptabilité, +Accounting Details,Détails Comptable, Debit To,Débit Pour, Is Opening Entry,Est Écriture Ouverte, C-Form Applicable,Formulaire-C Applicable, @@ -8028,7 +8028,7 @@ Import Chart of Accounts from CSV / Excel files,Importer un plan comptable à pa Completed Qty cannot be greater than 'Qty to Manufacture',La quantité terminée ne peut pas être supérieure à la `` quantité à fabriquer '', "Row {0}: For Supplier {1}, Email Address is Required to send an email","Ligne {0}: pour le fournisseur {1}, l'adresse e-mail est obligatoire pour envoyer un e-mail", "If enabled, the system will post accounting entries for inventory automatically","Si activé, le système enregistrera automatiquement les écritures comptables pour l'inventaire", -Accounts Frozen Till Date,Comptes gelés jusqu'à la date, +Accounts Frozen Till Date,Comptes gelés jusqu'au, Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below,Les écritures comptables sont gelées jusqu'à cette date. Personne ne peut créer ou modifier des entrées sauf les utilisateurs avec le rôle spécifié ci-dessous, Role Allowed to Set Frozen Accounts and Edit Frozen Entries,Rôle autorisé à définir des comptes gelés et à modifier les entrées gelées, Address used to determine Tax Category in transactions,Adresse utilisée pour déterminer la catégorie de taxe dans les transactions, @@ -8339,7 +8339,7 @@ Unit of Measure (UOM),Unité de mesure (UdM), Unit Of Measure (UOM),Unité de mesure (UdM), CRM Settings,Paramètres CRM, Do Not Explode,Ne pas décomposer, -Quick Access, Accés rapides, +Quick Access, Accès rapides, {} Available,{} Disponible.s, {} Pending,{} En attente.s, {} To Bill,{} à facturer, @@ -8449,3 +8449,64 @@ Closing,Clôture Allow Sales,Autoriser à la vente Approve,Approuver, Reject,Rejeter, +'Account' in the Accounting section of Customer {0},'Compte' dans la section comptabilité du client {0}, +Accounting Entry Number,Numéro d'écriture comptable, +Accounting Ledger,Grand livre, +Accounts Closing,Clôture, +Accounts Frozen Upto,Comptes gelés jusqu'au, +Accounts Manager,Responsable comptable, +Active Customers,Clients actifs, +Against Account,Contrepartie, +All the Comments and Emails will be copied from one document to another newly created document(Lead -> Opportunity -> Quotation) throughout the CRM documents.,Tous les commentaires et les courriels seront copiés d'un document à un autre document nouvellement créé (Lead -> Opportunité -> Devis) dans l'ensemble des documents CRM., +Allow multi-currency invoices against single party account ,Autoriser les factures multi-devises en contrepartie d'un seul compte de tiers, +Allow Sales Order Creation For Expired Quotation,Autoriser la création de commandes client pour les devis expirés, +Allow Continuous Material Consumption,Autoriser la consommation continue de matériel, +Allow Lead Duplication based on Emails,Autoriser la duplication des pistes sur la base des courriels, +Asset Settings,Paramètres des actifs, +Auto close Opportunity Replied after the no. of days mentioned above,Fermeture automatique de l'opportunité de réponse après le nombre de jours mentionné ci-dessus., +Auto Creation of Contact,Création automatique d'un contact, +Automatically Fetch Payment Terms from Order,Récupération automatique des conditions de paiement de la commande, +Bill for Rejected Quantity in Purchase Invoice,Facturation de la quantité rejetée dans la facture d'achat, +Credit Limit Settings,Paramètres de la limite de crédit, +Create Ledger Entries for Change Amount,Créer des écritures de grand livre pour modifier le montant, +Customer Defaults,Valeurs par défaut des clients, +Calculate Product Bundle Price based on Child Items' Rates,Calculer le prix des ensembles de produits en fonction des tarifs des articles enfants, +Configure the action to stop the transaction or just warn if the same rate is not maintained.,Configurez une action pour stopper la transaction ou alertez simplement su le prix unitaie n'est pas maintenu., +Close Replied Opportunity After Days,Fermer l'opportunité répliquée après des jours, +Carry Forward Communication and Comments,Reprendre les communications et commentaires, +Default Down Payment Payable Account,Compte d'acompte fournisseur par défaut, +Default Down Payment Receivable Account,Compte d'acompte client par défaut, +Disable Last Purchase Rate,Désactiver le dernier prix d'achat, +'Default {0} Account' in Company {1},'Compte {0} par défaut' dans la société {1}, +Enable Custom Cash Flow Format,Activation du format de flux de trésorerie personnalisé, +Enabling ensure each Purchase Invoice has a unique value in Supplier Invoice No. field,Garanti que chaque facture d'achat est associée à un numéro de facture fournisseur unique, +Enable Common Party Accounting,Activer la comptabilité des tiers communs, +Enabling this will allow creation of multi-currency invoices against single party account in company currency,L'activation de cette option va permettre la création de factures multi-devises en contrepartie d'un seul compte de tiers en devise de la société, +Enable Discount Accounting for Selling,Activation de la comptabilité d'escompte pour la vente, +'Expected Start Date' can not be greater than 'Expected End Date','Date de Début Prévue' ne peut pas être postérieure à 'Date de Fin Prévue', +Get Advances Received, Obtenir les paiements des avances, +"If enabled, ledger entries will be posted for change amount in POS transactions","Si cette option est activée, des écritures de grand livre seront enregistrées pour le montant de la modification dans les transactions POS.", +"If enabled, additional ledger entries will be made for discounts in a separate Discount Account","Si cette option est activée, des écritures de grand livre supplémentaires seront effectuées pour les remises dans un compte de remise séparé.", +Item Price Settings,Paramètres du prix de l'article, +Invoice and Billing,Facturation, +Invoice Cancellation,Annulation de facture, +Invoicing Features,Caractéristiques de la facturation, +Journals,Journaux, +"Learn about Common Party","En savoir plus Tiers communs", +Naming Series and Price Defaults,Nom de série et Tarifs, +Over Order Allowance (%),Tolérance de sur-commande (%), +Payment Terms from orders will be fetched into the invoices as is,Les termes de paiement des commandes seront récupérées dans les factures telles quelles, +Percentage you are allowed to order more against the Blanket Order Quantity. For example: If you have a Blanket Order of Quantity 100 units. and your Allowance is 10% then you are allowed to order 110 units.,"Percentage de commande autorisée en plus de la quantité prévue dans la commande ouverte. Par exemple: Si vous avez une commande avec une quantité de 100 unités et une tolérance de 10%, alors vous pourrez commander jusqu'à 110 unités.", +Period Closing Settings,Paramètres de clôture de la période, +Quick Access,Accès rapide, +Report Setting,Réglage des rapports, +Record all transactions against an accounting journal,Comptabiliser toutes les transactions dans un journal comptable, +Rows with Same Account heads will be merged on Ledger,Les lignes associées aux mêmes comptes comptables seront fusionnées dans le grand livre, +Role Allowed to Over Bill ,Rôle autorisé à sur-facturer, +Role allowed to bypass Credit Limit,Rôle autorisé à contourner la limite de crédit, +Role Allowed to Override Stop Action,Rôle autorisé à outrepasser l'action Stop, +Show Balances in Chart Of Accounts,Afficher les soldes dans le plan comptable, +Sales Update Frequency in Company and Project,Fréquence de mise à jour des ventes dans la société et le projet, +Transaction Settings,Paramètres des transactions, +Subcontracting Settings,Paramètres de sous-traitance, +Users with this role are allowed to over bill above the allowance percentage,Les utilisateurs avec ce rôle sont autorisés à sur-facturer au delà du pourcentage de tolérance, From 5952cfa673837e09167591e593e5691f1f121b6e Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Sat, 2 Dec 2023 15:22:11 +0100 Subject: [PATCH 190/202] fix: german translations for Lost Quotations (#38435) --- erpnext/translations/de.csv | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 73755be653..2745d4da12 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -8856,3 +8856,7 @@ Book Tax Loss on Early Payment Discount,Umsatzsteueranteil bei Skonto berücksic Split Early Payment Discount Loss into Income and Tax Loss,"Skontobetrag in Aufwand und Umsatzsteuerkorrektur aufteilen", Approve,Genehmigen, Reject,Ablehnen, +Lost Quotations,Verlorene Angebote, +Lost Quotations %,Verlorene Angebote %, +Lost Value,Verlorener Wert, +Lost Value %,Verlorener Wert %, From 9087e1443e4719ef07888ba43b167fe24bd352e1 Mon Sep 17 00:00:00 2001 From: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com> Date: Sat, 2 Dec 2023 19:53:00 +0530 Subject: [PATCH 191/202] fix: SO ordered qty on PO item removal (#38378) * fix: update ordered_qty for SO when PO items removed * refactor: use cached value --------- Co-authored-by: Deepesh Garg --- .../doctype/purchase_order/purchase_order.py | 14 ++++++++++++++ erpnext/controllers/accounts_controller.py | 3 +++ 2 files changed, 17 insertions(+) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 595722d1ee..b446512003 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -608,6 +608,20 @@ class PurchaseOrder(BuyingController): return result + def update_ordered_qty_in_so_for_removed_items(self, removed_items): + """ + Updates ordered_qty in linked SO when item rows are removed using Update Items + """ + if not self.is_against_so(): + return + for item in removed_items: + prev_ordered_qty = frappe.get_cached_value( + "Sales Order Item", item.get("sales_order_item"), "ordered_qty" + ) + frappe.db.set_value( + "Sales Order Item", item.get("sales_order_item"), "ordered_qty", prev_ordered_qty - item.qty + ) + def auto_create_subcontracting_order(self): if self.is_subcontracted and not self.is_old_subcontracting_flow: if frappe.db.get_single_value("Buying Settings", "auto_create_subcontracting_order"): diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index f551133a28..414f98c961 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -2958,6 +2958,9 @@ def validate_and_delete_children(parent, data) -> bool: d.cancel() d.delete() + if parent.doctype == "Purchase Order": + parent.update_ordered_qty_in_so_for_removed_items(deleted_children) + # need to update ordered qty in Material Request first # bin uses Material Request Items to recalculate & update parent.update_prevdoc_status() From b6a7549407bc04225f0bb7c144284078a314f430 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Sat, 2 Dec 2023 20:06:19 +0530 Subject: [PATCH 192/202] fix: use predefined onload property `load_after_mapping` (#38209) --- .../doctype/purchase_invoice/purchase_invoice.py | 2 -- .../doctype/sales_invoice/sales_invoice.py | 1 - .../doctype/purchase_order/purchase_order.py | 3 --- .../supplier_quotation/supplier_quotation.py | 1 - erpnext/controllers/sales_and_purchase_return.py | 2 -- erpnext/public/js/controllers/transaction.js | 14 +++++++------- erpnext/selling/doctype/quotation/quotation.py | 5 ----- erpnext/selling/doctype/sales_order/sales_order.py | 3 --- .../stock/doctype/delivery_note/delivery_note.py | 2 -- .../doctype/purchase_receipt/purchase_receipt.py | 1 - 10 files changed, 7 insertions(+), 27 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index f9c9fb5ac5..262732c976 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1859,6 +1859,4 @@ def make_purchase_receipt(source_name, target_doc=None): target_doc, ) - doc.set_onload("ignore_price_list", True) - return doc diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 0ebf33564f..96a557b7e8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -2095,7 +2095,6 @@ def make_delivery_note(source_name, target_doc=None): set_missing_values, ) - doclist.set_onload("ignore_price_list", True) return doclist diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index b446512003..2efb46e9d3 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -713,8 +713,6 @@ def make_purchase_receipt(source_name, target_doc=None): set_missing_values, ) - doc.set_onload("ignore_price_list", True) - return doc @@ -794,7 +792,6 @@ def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions postprocess, ignore_permissions=ignore_permissions, ) - doc.set_onload("ignore_price_list", True) return doc diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index bb0c2691dc..e2b737ba6f 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -257,7 +257,6 @@ def make_purchase_order(source_name, target_doc=None): set_missing_values, ) - doclist.set_onload("ignore_price_list", True) return doclist diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 8e3a15a0ad..81e71e3aa2 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -586,8 +586,6 @@ def make_return_doc( set_missing_values, ) - doclist.set_onload("ignore_price_list", True) - return doclist diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 6dc24faa96..8c0d84b415 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -357,7 +357,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe onload_post_render() { if(this.frm.doc.__islocal && !(this.frm.doc.taxes || []).length - && !(this.frm.doc.__onload ? this.frm.doc.__onload.load_after_mapping : false)) { + && !this.frm.doc.__onload?.load_after_mapping) { frappe.after_ajax(() => this.apply_default_taxes()); } else if(this.frm.doc.__islocal && this.frm.doc.company && this.frm.doc["items"] && !this.frm.doc.is_pos) { @@ -964,9 +964,9 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe let me = this; this.set_dynamic_labels(); let company_currency = this.get_company_currency(); - // Added `ignore_price_list` to determine if document is loading after mapping from another doc + // Added `load_after_mapping` to determine if document is loading after mapping from another doc if(this.frm.doc.currency && this.frm.doc.currency !== company_currency - && !(this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list)) { + && !this.frm.doc.__onload?.load_after_mapping) { this.get_exchange_rate(transaction_date, this.frm.doc.currency, company_currency, function(exchange_rate) { @@ -998,7 +998,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } if(flt(this.frm.doc.conversion_rate)>0.0) { - if(this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list) { + if(this.frm.doc.__onload?.load_after_mapping) { this.calculate_taxes_and_totals(); } else if (!this.in_apply_price_list){ this.apply_price_list(); @@ -1085,9 +1085,9 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe this.set_dynamic_labels(); var company_currency = this.get_company_currency(); - // Added `ignore_price_list` to determine if document is loading after mapping from another doc + // Added `load_after_mapping` to determine if document is loading after mapping from another doc if(this.frm.doc.price_list_currency !== company_currency && - !(this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list)) { + !this.frm.doc.__onload?.load_after_mapping) { this.get_exchange_rate(this.frm.doc.posting_date, this.frm.doc.price_list_currency, company_currency, function(exchange_rate) { me.frm.set_value("plc_conversion_rate", exchange_rate); @@ -1476,7 +1476,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } // Target doc created from a mapped doc - if (this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list) { + if (this.frm.doc.__onload?.load_after_mapping) { // Calculate totals even though pricing rule is not applied. // `apply_pricing_rule` is triggered due to change in data which most likely contributes to Total. if (calculate_taxes_and_totals) me.calculate_taxes_and_totals(); diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 8d3bb78740..00b79e3aad 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -434,9 +434,6 @@ def _make_sales_order(source_name, target_doc=None, customer_group=None, ignore_ ignore_permissions=ignore_permissions, ) - # postprocess: fetch shipping address, set missing values - doclist.set_onload("ignore_price_list", True) - return doclist @@ -505,8 +502,6 @@ def _make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): ignore_permissions=ignore_permissions, ) - doclist.set_onload("ignore_price_list", True) - return doclist diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index fd6c0273ef..09941eaa82 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -995,7 +995,6 @@ def make_delivery_note(source_name, target_doc=None, kwargs=None): # Should be called after mapping items. set_missing_values(so, target_doc) - target_doc.set_onload("ignore_price_list", True) return target_doc @@ -1085,8 +1084,6 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): if automatically_fetch_payment_terms: doclist.set_payment_schedule() - doclist.set_onload("ignore_price_list", True) - return doclist diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index e44736b56e..a101bdf244 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -964,8 +964,6 @@ def make_sales_invoice(source_name, target_doc=None): if automatically_fetch_payment_terms: doc.set_payment_schedule() - doc.set_onload("ignore_price_list", True) - return doc diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 907bc6712f..ab0727163e 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -1208,7 +1208,6 @@ def make_purchase_invoice(source_name, target_doc=None): set_missing_values, ) - doclist.set_onload("ignore_price_list", True) return doclist From 74eab910427ca4af94119b0c099e7743be770006 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sat, 2 Dec 2023 23:12:12 +0530 Subject: [PATCH 193/202] fix: better overlap logic for job card (#38432) --- .../doctype/job_card/job_card.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 4b1015de68..d696cc4082 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -261,8 +261,7 @@ class JobCard(Document): # override capacity for employee production_capacity = 1 - overlap_count = self.get_overlap_count(time_logs) - if time_logs and production_capacity > overlap_count: + if not self.has_overlap(production_capacity, time_logs): return {} if self.workstation_type and time_logs: @@ -272,16 +271,15 @@ class JobCard(Document): return time_logs[-1] - @staticmethod - def get_overlap_count(time_logs): - count = 1 + def has_overlap(self, production_capacity, time_logs): + overlap = False + if production_capacity == 1 and len(time_logs) > 0: + return True # Check overlap exists or not between the overlapping time logs with the current Job Card - for idx, row in enumerate(time_logs): - next_idx = idx - if idx + 1 < len(time_logs): - next_idx = idx + 1 - next_row = time_logs[next_idx] + for row in time_logs: + count = 1 + for next_row in time_logs: if row.name == next_row.name: continue @@ -301,7 +299,10 @@ class JobCard(Document): ): count += 1 - return count + if count > production_capacity: + return True + + return overlap def get_time_logs(self, args, doctype, check_next_available_slot=False): jc = frappe.qb.DocType("Job Card") From f4d418ea6d28f64d6d1c15c5eea2a75722384c0c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 3 Dec 2023 10:33:31 +0530 Subject: [PATCH 194/202] fix: item group filter in sales person wise report --- .../sales_person_wise_transaction_summary.py | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py index cb6e8a1102..9f3ba0da8b 100644 --- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py +++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py @@ -3,7 +3,8 @@ import frappe -from frappe import _, msgprint +from frappe import _, msgprint, qb +from frappe.query_builder import Criterion from erpnext import get_company_currency @@ -214,24 +215,33 @@ def get_conditions(filters, date_field): if items: conditions.append("dt_item.item_code in (%s)" % ", ".join(["%s"] * len(items))) values += items + else: + # return empty result, if no items are fetched after filtering on 'item group' and 'brand' + conditions.append("dt_item.item_code = Null") return " and ".join(conditions), values def get_items(filters): + item = qb.DocType("Item") + + item_query_conditions = [] if filters.get("item_group"): - key = "item_group" - elif filters.get("brand"): - key = "brand" - else: - key = "" - - items = [] - if key: - items = frappe.db.sql_list( - """select name from tabItem where %s = %s""" % (key, "%s"), (filters[key]) + # Handle 'Parent' nodes as well. + item_group = qb.DocType("Item Group") + lft, rgt = frappe.db.get_all( + "Item Group", filters={"name": filters.get("item_group")}, fields=["lft", "rgt"], as_list=True + )[0] + item_group_query = ( + qb.from_(item_group) + .select(item_group.name) + .where((item_group.lft >= lft) & (item_group.rgt <= rgt)) ) + item_query_conditions.append(item.item_group.isin(item_group_query)) + if filters.get("brand"): + item_query_conditions.append(item.brand == filters.get("brand")) + items = qb.from_(item).select(item.name).where(Criterion.all(item_query_conditions)).run() return items From 64266c4d3826e19b293f522bfb4cbbb305f817b7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 3 Dec 2023 10:50:18 +0530 Subject: [PATCH 195/202] fix: remove hardcoded, implicit rounding loss allowance --- .../exchange_rate_revaluation/exchange_rate_revaluation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index 4f7eeba2d1..e9cbb337d5 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -214,7 +214,7 @@ class ExchangeRateRevaluation(Document): # round off balance based on currency precision # and consider debit-credit difference allowance currency_precision = get_currency_precision() - rounding_loss_allowance = float(rounding_loss_allowance) or 0.05 + rounding_loss_allowance = float(rounding_loss_allowance) for acc in account_details: acc.balance_in_account_currency = flt(acc.balance_in_account_currency, currency_precision) if abs(acc.balance_in_account_currency) <= rounding_loss_allowance: From d659d407a060e3f2ec7f41ce62a00fe5238f429c Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Sun, 3 Dec 2023 23:22:04 +0530 Subject: [PATCH 196/202] fix: Group By in Item-wise Purchase Register (#38503) --- .../item_wise_purchase_register/item_wise_purchase_register.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index ad196a9032..9c6e2d0dc3 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -319,7 +319,7 @@ def get_items(filters, additional_query_columns): `tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company, `tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total, `tabPurchase Invoice`.unrealized_profit_loss_account, - `tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description, + `tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description, `tabPurchase Invoice Item`.`item_group`, `tabPurchase Invoice Item`.`item_name` as pi_item_name, `tabPurchase Invoice Item`.`item_group` as pi_item_group, `tabItem`.`item_name` as i_item_name, `tabItem`.`item_group` as i_item_group, `tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`, From dd39da0b77f73dc9006c036b960b63404cc2c2f5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 4 Dec 2023 10:08:37 +0530 Subject: [PATCH 197/202] fix: incorrectly treating normal payment as advance (#38437) fix: treating normal payment as advance --- .../doctype/payment_entry/payment_entry.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index dfb5caf2d3..1282ab6039 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -106,9 +106,17 @@ class PaymentEntry(AccountsController): self.set_status() def set_liability_account(self): - if not self.book_advance_payments_in_separate_party_account: + # Auto setting liability account should only be done during 'draft' status + if self.docstatus > 0: return + if not frappe.db.get_value( + "Company", self.company, "book_advance_payments_in_separate_party_account" + ): + return + + # Important to set this flag for the gl building logic to work properly + self.book_advance_payments_in_separate_party_account = True account_type = frappe.get_value( "Account", {"name": self.party_account, "company": self.company}, "account_type" ) @@ -118,11 +126,13 @@ class PaymentEntry(AccountsController): ): return - if self.unallocated_amount == 0: - for d in self.references: - if d.reference_doctype in ["Sales Order", "Purchase Order"]: - break - else: + if self.references: + allowed_types = frozenset(["Sales Order", "Purchase Order"]) + reference_types = set([x.reference_doctype for x in self.references]) + + # If there are referencers other than `allowed_types`, treat this as a normal payment entry + if reference_types - allowed_types: + self.book_advance_payments_in_separate_party_account = False return liability_account = get_party_account( From ccdcb7dfcc29eb68d1cad38f3426e6fb575528eb Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 4 Dec 2023 11:58:44 +0530 Subject: [PATCH 198/202] fix(ux): stock-item filter for Item Code field --- erpnext/stock/report/stock_analytics/stock_analytics.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.js b/erpnext/stock/report/stock_analytics/stock_analytics.js index ea7bf5688e..e033fd9a9d 100644 --- a/erpnext/stock/report/stock_analytics/stock_analytics.js +++ b/erpnext/stock/report/stock_analytics/stock_analytics.js @@ -17,6 +17,7 @@ frappe.query_reports["Stock Analytics"] = { fieldtype: "Link", options:"Item", default: "", + get_query: () => ({filters: { 'is_stock_item': 1 }}), }, { fieldname: "value_quantity", From 01aadbef85e2570399f054027e57d6bb01af9433 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 4 Dec 2023 12:00:36 +0530 Subject: [PATCH 199/202] fix: don't show non-stock items in Stock Analytics report --- erpnext/stock/report/stock_analytics/stock_analytics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.py b/erpnext/stock/report/stock_analytics/stock_analytics.py index 6c5b58c6e4..ab48181c48 100644 --- a/erpnext/stock/report/stock_analytics/stock_analytics.py +++ b/erpnext/stock/report/stock_analytics/stock_analytics.py @@ -270,7 +270,7 @@ def get_items(filters): if item_code := filters.get("item_code"): return [item_code] else: - item_filters = {} + item_filters = {"is_stock_item": 1} if item_group := filters.get("item_group"): children = get_descendants_of("Item Group", item_group, ignore_permissions=True) item_filters["item_group"] = ("in", children + [item_group]) From 15fff84bb5cc78507aa24771fde3e9a9fbb926bc Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 4 Dec 2023 12:05:27 +0530 Subject: [PATCH 200/202] fix: `linter` --- .../accounts/report/accounts_receivable/accounts_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 7948e5f465..eaf9f421e1 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -1087,7 +1087,7 @@ class ReceivablePayableReport(object): ) if self.filters.show_remarks: - self.add_column(label=_("Remarks"), fieldname="remarks", fieldtype="Text", width=200), + 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: From 3df1d75bdd7a34c9fef4c4fe9af9341bc2e6e094 Mon Sep 17 00:00:00 2001 From: NIYAZ RAZAK <76736615+niyazrazak@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:09:49 +0300 Subject: [PATCH 201/202] fix: incorrect customer outstanding amount (#38475) * fix: incorrect customer outstanding amount * chore: resolve linting error Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --------- Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- erpnext/selling/doctype/customer/customer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 96df0ed733..efb9820016 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -587,7 +587,8 @@ def get_customer_outstanding( """ select sum(debit) - sum(credit) from `tabGL Entry` where party_type = 'Customer' - and party = %s and company=%s {0}""".format( + and is_cancelled = 0 and party = %s + and company=%s {0}""".format( cond ), (customer, company), From c8693cdf37ba9e91bf47d89de69aafc2fde5e6ed Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 4 Dec 2023 15:02:47 +0530 Subject: [PATCH 202/202] fix: scan for serial or batch in bundle (#38534) --- .../js/utils/serial_no_batch_selector.js | 82 ++++++++++++++++--- .../serial_and_batch_bundle.py | 5 ++ 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 9267801839..0de6774393 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -31,8 +31,19 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { secondary_action: () => this.edit_full_form(), }); - this.dialog.set_value("qty", this.item.qty); + this.dialog.set_value("qty", this.item.qty).then(() => { + if (this.item.serial_no) { + this.dialog.set_value("scan_serial_no", this.item.serial_no); + frappe.model.set_value(this.item.doctype, this.item.name, 'serial_no', ''); + } else if (this.item.batch_no) { + this.dialog.set_value("scan_batch_no", this.item.batch_no); + frappe.model.set_value(this.item.doctype, this.item.name, 'batch_no', ''); + } + }); + this.dialog.show(); + this.$scan_btn = this.dialog.$wrapper.find(".link-btn"); + this.$scan_btn.css("display", "inline"); } get_serial_no_filters() { @@ -95,6 +106,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { if (this.item.has_serial_no) { fields.push({ fieldtype: 'Data', + options: 'Barcode', fieldname: 'scan_serial_no', label: __('Scan Serial No'), get_query: () => { @@ -106,15 +118,10 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { }); } - if (this.item.has_batch_no && this.item.has_serial_no) { - fields.push({ - fieldtype: 'Column Break', - }); - } - - if (this.item.has_batch_no) { + if (this.item.has_batch_no && !this.item.has_serial_no) { fields.push({ fieldtype: 'Data', + options: 'Barcode', fieldname: 'scan_batch_no', label: __('Scan Batch No'), onchange: () => this.update_serial_batch_no() @@ -309,6 +316,14 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } get_auto_data() { + if (this.item.serial_and_batch_bundle || this.item.rejected_serial_and_batch_bundle) { + return; + } + + if (this.item.serial_no || this.item.batch_no) { + return; + } + let { qty, based_on } = this.dialog.get_values(); if (!based_on) { @@ -340,16 +355,57 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { const { scan_serial_no, scan_batch_no } = this.dialog.get_values(); if (scan_serial_no) { - this.dialog.fields_dict.entries.df.data.push({ - serial_no: scan_serial_no + let existing_row = this.dialog.fields_dict.entries.df.data.filter(d => { + if (d.serial_no === scan_serial_no) { + return d + } }); - this.dialog.fields_dict.scan_serial_no.set_value(''); + if (existing_row?.length) { + frappe.throw(__('Serial No {0} already exists', [scan_serial_no])); + } + + if (!this.item.has_batch_no) { + this.dialog.fields_dict.entries.df.data.push({ + serial_no: scan_serial_no + }); + + this.dialog.fields_dict.scan_serial_no.set_value(''); + } else { + frappe.call({ + method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_batch_no_from_serial_no', + args: { + serial_no: scan_serial_no, + }, + callback: (r) => { + if (r.message) { + this.dialog.fields_dict.entries.df.data.push({ + serial_no: scan_serial_no, + batch_no: r.message + }); + + this.dialog.fields_dict.scan_serial_no.set_value(''); + } + } + + }) + } } else if (scan_batch_no) { - this.dialog.fields_dict.entries.df.data.push({ - batch_no: scan_batch_no + let existing_row = this.dialog.fields_dict.entries.df.data.filter(d => { + if (d.batch_no === scan_batch_no) { + return d + } }); + if (existing_row?.length) { + existing_row[0].qty += 1; + } else { + this.dialog.fields_dict.entries.df.data.push({ + batch_no: scan_batch_no, + qty: 1 + }); + } + this.dialog.fields_dict.scan_batch_no.set_value(''); } diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 88929eaaa0..108a2e008d 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1745,3 +1745,8 @@ def get_stock_ledgers_batches(kwargs): batches[key].qty += d.qty return batches + + +@frappe.whitelist() +def get_batch_no_from_serial_no(serial_no): + return frappe.get_cached_value("Serial No", serial_no, "batch_no")