From 2834d25ce31801808781a9fc203e942c89636cc3 Mon Sep 17 00:00:00 2001 From: Wolfram Schmidt Date: Sun, 24 Mar 2024 07:43:40 +0100 Subject: [PATCH 01/72] refactor: better pop message for Internal Customer validation -added more meaningful description to message when using "internal Customer" scenario (cherry picked from commit b132892b257dcad80cb85092b3b19cfc5532ece6) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 2a86d0daf45e..6a1a5f3a7c99 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1817,9 +1817,9 @@ def validate_inter_company_party(doctype, party, company, inter_company_referenc companies = [d.company for d in companies] if not company in companies: frappe.throw( - _("{0} not allowed to transact with {1}. Please change the Company.").format( - partytype, company - ) + _( + "{0} not allowed to transact with {1}. Please change the Company or add the Company in the 'Allowed To Transact With'-Section in the Customer record." + ).format(_(partytype), company) ) From 4f4470b9d209dc5b2c04a2c61029d69dd4f976c8 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 27 Mar 2024 15:07:44 +0530 Subject: [PATCH 02/72] fix: Priority not copied from project template (cherry picked from commit 33fd7b8a1f125e0387a7a7851a149f91297b9958) --- erpnext/projects/doctype/project/project.py | 1 + erpnext/projects/doctype/project/test_project.py | 9 +++++++-- erpnext/projects/doctype/task/test_task.py | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 748c755d3777..8704147cd22f 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -87,6 +87,7 @@ def create_task_from_template(self, task_details): is_group=task_details.is_group, color=task_details.color, template_task=task_details.name, + priority=task_details.priority, ) ).insert() diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py index e49fecd1f470..b8340ffe1936 100644 --- a/erpnext/projects/doctype/project/test_project.py +++ b/erpnext/projects/doctype/project/test_project.py @@ -23,7 +23,11 @@ def test_project_with_template_having_no_parent_and_depend_tasks(self): task1 = task_exists("Test Template Task with No Parent and Dependency") if not task1: task1 = create_task( - subject="Test Template Task with No Parent and Dependency", is_template=1, begin=5, duration=3 + subject="Test Template Task with No Parent and Dependency", + is_template=1, + begin=5, + duration=3, + priority="High", ) template = make_project_template( @@ -32,11 +36,12 @@ def test_project_with_template_having_no_parent_and_depend_tasks(self): project = get_project(project_name, template) tasks = frappe.get_all( "Task", - ["subject", "exp_end_date", "depends_on_tasks"], + ["subject", "exp_end_date", "depends_on_tasks", "priority"], dict(project=project.name), order_by="creation asc", ) + self.assertEqual(tasks[0].priority, "High") self.assertEqual(tasks[0].subject, "Test Template Task with No Parent and Dependency") self.assertEqual(getdate(tasks[0].exp_end_date), calculate_end_date(project, 5, 3)) self.assertEqual(len(tasks), 1) diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index c0333f8f590d..ea7d6edcdf91 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -122,6 +122,7 @@ def create_task( begin=0, duration=0, save=True, + priority=None, ): if not frappe.db.exists("Task", subject): task = frappe.new_doc("Task") @@ -139,6 +140,7 @@ def create_task( task.duration = duration task.is_group = is_group task.parent_task = parent_task + task.priority = priority if save: task.save() else: From e778d7e69041f2f4cd63c6ecaa23a8146c86fe4f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 27 Mar 2024 20:05:27 +0530 Subject: [PATCH 03/72] fix: do not fetch received items in purchase receipt (cherry picked from commit 5bff4349020f3c54fdd7e30a294f1042b714a6fc) --- erpnext/controllers/stock_controller.py | 2 +- erpnext/stock/doctype/delivery_note/delivery_note.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index bc3ec7f93c25..8d7d888c2c9c 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -669,7 +669,7 @@ def validate_internal_transfer(self): self.validate_multi_currency() self.validate_packed_items() - if self.get("is_internal_supplier"): + if self.get("is_internal_supplier") and self.docstatus == 1: self.validate_internal_transfer_qty() else: self.validate_internal_transfer_warehouse() diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index a402bb5aed28..0a389b602a51 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -965,6 +965,9 @@ def set_missing_values(source, target): for tax in get_taxes_and_charges(master_doctype, target.get("taxes_and_charges")): target.append("taxes", tax) + if not target.get("items"): + frappe.throw(_("All items have already been received")) + def update_details(source_doc, target_doc, source_parent): target_doc.inter_company_invoice_reference = source_doc.name if target_doc.doctype == "Purchase Receipt": @@ -1020,6 +1023,10 @@ def update_details(source_doc, target_doc, source_parent): shipping_address_name=target_doc.shipping_address_name, ) + def update_item(source, target, source_parent): + if source_parent.doctype == "Delivery Note" and source.received_qty: + target.qty = flt(source.qty) + flt(source.returned_qty) - flt(source.received_qty) + doclist = get_mapped_doc( doctype, source_name, @@ -1043,6 +1050,8 @@ def update_details(source_doc, target_doc, source_parent): "Material_request_item": "material_request_item", }, "field_no_map": ["warehouse"], + "condition": lambda item: item.received_qty < item.qty + item.returned_qty, + "postprocess": update_item, }, }, target_doc, From b5629d2d4e93adffda39f027a2de861167b709b6 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 28 Mar 2024 10:30:13 +0530 Subject: [PATCH 04/72] fix: markdown to text editor set for supplier quotation (cherry picked from commit 9828d34b19e575697b4d5bbc624689535160aa69) # Conflicts: # erpnext/buying/doctype/supplier_quotation/supplier_quotation.json # erpnext/buying/doctype/supplier_quotation/supplier_quotation.py --- .../supplier_quotation.json | 6 +- .../supplier_quotation/supplier_quotation.py | 92 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index f13ceb04a50e..a35719f81ad2 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -461,7 +461,7 @@ }, { "fieldname": "other_charges_calculation", - "fieldtype": "Markdown Editor", + "fieldtype": "Text Editor", "label": "Taxes and Charges Calculation", "no_copy": 1, "oldfieldtype": "HTML", @@ -927,7 +927,11 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2024-03-20 16:03:59.069145", +======= + "modified": "2024-03-28 10:20:30.231915", +>>>>>>> 9828d34b19 (fix: markdown to text editor set for supplier quotation) "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index e27fbe8aaa23..7570063aef12 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -14,6 +14,98 @@ class SupplierQuotation(BuyingController): +<<<<<<< HEAD +======= + # begin: auto-generated types + # This 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.TextEditor | 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.TextEditor | 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.TextEditor | 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.TextEditor | 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 + +>>>>>>> 9828d34b19 (fix: markdown to text editor set for supplier quotation) def validate(self): super(SupplierQuotation, self).validate() From 4d6fad26f3fee7f54c7b64e4f8720f1759a82e8f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 28 Mar 2024 13:28:59 +0530 Subject: [PATCH 05/72] refactor: use sql to clear comments (cherry picked from commit 1f46c1530e68263ca2b5f9f86f59bb06063cd05e) --- .../transaction_deletion_record.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 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 db5024bbc199..c32df4ec9d03 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py @@ -388,17 +388,11 @@ def delete_communications(self, doctype, reference_doc_names): 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) + if reference_doc_names: + comment = qb.DocType("Comment") + qb.from_(comment).delete().where( + (comment.reference_doctype == doctype) & (comment.reference_name.isin(reference_doc_names)) + ).run() def unlink_attachments(self, doctype, reference_doc_names): files = frappe.get_all( From f66b53b2c1f2855ad72500731c350bc37ccf8218 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 29 Mar 2024 11:21:27 +0530 Subject: [PATCH 06/72] fix: cost center shouldn't update debit/credit in Exc gain/loss JV (cherry picked from commit 398d3022eff1df4d7179bf795570eab02fc0816b) --- erpnext/accounts/doctype/journal_entry/journal_entry.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index a2f5455f2f74..cda0adc7257e 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -428,7 +428,10 @@ frappe.ui.form.on("Journal Entry Account", { } }, cost_center: function (frm, dt, dn) { - erpnext.journal_entry.set_account_details(frm, dt, dn); + // Don't reset for Gain/Loss type journals, as it will make Debit and Credit values '0' + if (frm.doc.voucher_type != "Exchange Gain Or Loss") { + erpnext.journal_entry.set_account_details(frm, dt, dn); + } }, account: function (frm, dt, dn) { From 8dff18eab478a3a17d485dc500dbcdeda84eaf0f Mon Sep 17 00:00:00 2001 From: Ashish Shah Date: Fri, 29 Mar 2024 10:52:52 +0530 Subject: [PATCH 07/72] fix: payment_order_status should be no_copy payment_order_status should be no_copy (cherry picked from commit adee2ba5413f5f8c73cbc30204b9ba507866f4ec) --- erpnext/accounts/doctype/payment_entry/payment_entry.json | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index bd43fb77c233..d3db789c3362 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -576,6 +576,7 @@ "fieldtype": "Select", "hidden": 1, "label": "Payment Order Status", + "no_copy": 1, "options": "Initiated\nPayment Ordered", "read_only": 1 }, From ceac42dfaa691d169603a529545c6fd70facf247 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 30 Mar 2024 10:18:16 +0530 Subject: [PATCH 08/72] fix: Warehouse linked company name in multicompany setup (backport #40779) (#40780) fix: Warehouse linked company name in multicompany setup (#40779) (cherry picked from commit 679aea607b1bf7c9303a2cbe1a7b5629a03f3f4f) Co-authored-by: jeshani <56191568+jeshani@users.noreply.github.com> --- erpnext/stock/doctype/warehouse/warehouse.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js index 4f44db023dd3..9457c25b22dc 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.js +++ b/erpnext/stock/doctype/warehouse/warehouse.js @@ -49,6 +49,7 @@ frappe.ui.form.on("Warehouse", { frm.add_custom_button(__("Stock Balance"), function () { frappe.set_route("query-report", "Stock Balance", { warehouse: frm.doc.name, + company: frm.doc.company, }); }); From 9b8bb4d6a2c88b133208d488ca0d275edf7798d7 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sun, 31 Mar 2024 11:41:44 +0530 Subject: [PATCH 09/72] chore: fix conflicts --- .../supplier_quotation/supplier_quotation.py | 92 ------------------- 1 file changed, 92 deletions(-) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index 7570063aef12..e27fbe8aaa23 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -14,98 +14,6 @@ class SupplierQuotation(BuyingController): -<<<<<<< HEAD -======= - # begin: auto-generated types - # This 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.TextEditor | 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.TextEditor | 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.TextEditor | 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.TextEditor | 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 - ->>>>>>> 9828d34b19 (fix: markdown to text editor set for supplier quotation) def validate(self): super(SupplierQuotation, self).validate() From 31017774f63d0a9a8c46b748c6b2942207fbe09a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sun, 31 Mar 2024 11:42:05 +0530 Subject: [PATCH 10/72] chore: fix conflicts --- .../doctype/supplier_quotation/supplier_quotation.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index a35719f81ad2..d87db06a4a97 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -927,11 +927,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], -<<<<<<< HEAD - "modified": "2024-03-20 16:03:59.069145", -======= "modified": "2024-03-28 10:20:30.231915", ->>>>>>> 9828d34b19 (fix: markdown to text editor set for supplier quotation) "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", @@ -999,4 +995,4 @@ "states": [], "timeline_field": "supplier", "title_field": "title" -} \ No newline at end of file +} From 72db656054e90a02bb7f2fee86fdb5f6488a852e Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Wed, 28 Feb 2024 20:33:16 -0500 Subject: [PATCH 11/72] test: show future payments allocated sales returns is considered as payment (cherry picked from commit daaa00bd4aa7414fde65bfc0e23538678f38aa12) --- .../test_accounts_receivable.py | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index de49139adc1c..01129824bca6 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -469,11 +469,30 @@ def test_group_by_party(self): ) def test_future_payments(self): + sr = self.create_sales_invoice(do_not_submit=True) + sr.is_return = 1 + sr.items[0].qty = -1 + sr.items[0].rate = 10 + sr.calculate_taxes_and_totals() + sr.submit() + si = self.create_sales_invoice() pe = get_payment_entry(si.doctype, si.name) + pe.append( + "references", + { + "reference_doctype": sr.doctype, + "reference_name": sr.name, + "due_date": sr.due_date, + "total_amount": sr.grand_total, + "outstanding_amount": sr.outstanding_amount, + "allocated_amount": sr.outstanding_amount, + }, + ) + pe.posting_date = add_days(today(), 1) - pe.paid_amount = 90.0 - pe.references[0].allocated_amount = 90.0 + pe.paid_amount = 80 + pe.references[0].allocated_amount = 90.0 # pe.paid_amount + sr.grand_total pe.save().submit() filters = { "company": self.company, @@ -485,16 +504,21 @@ def test_future_payments(self): "show_future_payments": True, } report = execute(filters)[1] - self.assertEqual(len(report), 1) + self.assertEqual(len(report), 2) - expected_data = [100.0, 100.0, 10.0, 90.0] + expected_data = {sr.name: [10.0, -10.0, 0.0, -10], si.name: [100.0, 100.0, 10.0, 90.0]} - row = report[0] - self.assertEqual( - expected_data, [row.invoiced, row.outstanding, row.remaining_balance, row.future_amount] - ) + rows = report[:2] + for row in rows: + self.assertEqual( + expected_data[row.voucher_no], + [row.invoiced or row.paid, row.outstanding, row.remaining_balance, row.future_amount], + ) pe.cancel() + sr.load_from_db() # Outstanding amount is updated so a updated timestamp is needed. + sr.cancel() + # full payment in future date pe = get_payment_entry(si.doctype, si.name) pe.posting_date = add_days(today(), 1) From 803ed904a9aa1201af0b7a701861ad03a8306fcd Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Wed, 28 Feb 2024 20:33:25 -0500 Subject: [PATCH 12/72] fix: show future payments allocated sales returns is considered as payment (cherry picked from commit 3381d0d94525cc2900ba23a69be644b6dae7a483) --- .../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 c3ebb018ae9c..609a4abe66f6 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -673,7 +673,7 @@ def allocate_future_payments(self, row): else: future_amount_field = "future_amount_in_base_currency" - if row.remaining_balance > 0 and future.get(future_amount_field): + if row.remaining_balance != 0 and future.get(future_amount_field): if future.get(future_amount_field) > row.outstanding: row.future_amount = row.outstanding future[future_amount_field] = future.get(future_amount_field) - row.outstanding From cfe5f009f6eef125d836601ab72d1913b50d90e9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 21 Mar 2024 12:43:08 +0530 Subject: [PATCH 13/72] fix: show currency symbol in base currency in fixed asset register report (cherry picked from commit 8b6220efd8e6a29a3e972c5d0e3af9cd2d26b631) --- .../report/pos_register/pos_register.py | 13 ++++++-- .../fixed_asset_register.py | 31 ++++++++++++++----- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py index 488bb9957c96..36e49250ee42 100644 --- a/erpnext/accounts/report/pos_register/pos_register.py +++ b/erpnext/accounts/report/pos_register/pos_register.py @@ -62,7 +62,7 @@ def get_pos_entries(filters, group_by_field): return frappe.db.sql( """ SELECT - p.posting_date, p.name as pos_invoice, p.pos_profile, + p.posting_date, p.name as pos_invoice, p.pos_profile, p.company, p.owner, p.customer, p.is_return, p.base_grand_total as grand_total {select_mop_field} FROM `tabPOS Invoice` p {from_sales_invoice_payment} @@ -207,14 +207,14 @@ def get_columns(filters): "label": _("Grand Total"), "fieldname": "grand_total", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 120, }, { "label": _("Paid Amount"), "fieldname": "paid_amount", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 120, }, { @@ -224,6 +224,13 @@ def get_columns(filters): "width": 150, }, {"label": _("Is Return"), "fieldname": "is_return", "fieldtype": "Data", "width": 80}, + { + "label": _("Company"), + "fieldname": "company", + "fieldtype": "Link", + "options": "Company", + "width": 120, + }, ] return columns diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index 45811a934444..4150494e22fc 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -149,6 +149,7 @@ def get_data(filters): "asset_category": asset.asset_category, "purchase_date": asset.purchase_date, "asset_value": asset_value, + "company": asset.company, } data.append(row) @@ -379,30 +380,37 @@ def get_columns(filters): "label": _("Gross Purchase Amount"), "fieldname": "gross_purchase_amount", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 250, }, { "label": _("Opening Accumulated Depreciation"), "fieldname": "opening_accumulated_depreciation", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 250, }, { "label": _("Depreciated Amount"), "fieldname": "depreciated_amount", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 250, }, { "label": _("Asset Value"), "fieldname": "asset_value", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 250, }, + { + "label": _("Company"), + "fieldname": "company", + "fieldtype": "Link", + "options": "Company", + "width": 120, + }, ] return [ @@ -433,28 +441,28 @@ def get_columns(filters): "label": _("Gross Purchase Amount"), "fieldname": "gross_purchase_amount", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 100, }, { "label": _("Asset Value"), "fieldname": "asset_value", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 100, }, { "label": _("Opening Accumulated Depreciation"), "fieldname": "opening_accumulated_depreciation", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 90, }, { "label": _("Depreciated Amount"), "fieldname": "depreciated_amount", "fieldtype": "Currency", - "options": "company:currency", + "options": "Company:company:default_currency", "width": 100, }, { @@ -479,4 +487,11 @@ def get_columns(filters): "options": "Location", "width": 100, }, + { + "label": _("Company"), + "fieldname": "company", + "fieldtype": "Link", + "options": "Company", + "width": 120, + }, ] From 515f93336263b4a865b66bd79fe8e884c88b79aa Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 2 Apr 2024 15:35:06 +0530 Subject: [PATCH 14/72] fix: linter issues (cherry picked from commit 21a40a22361c9bad92947e3ea4329f6c6815ee0f) --- erpnext/accounts/report/pos_register/pos_register.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py index 36e49250ee42..3c687d0b48e3 100644 --- a/erpnext/accounts/report/pos_register/pos_register.py +++ b/erpnext/accounts/report/pos_register/pos_register.py @@ -59,6 +59,7 @@ def get_pos_entries(filters, group_by_field): order_by += ", p.{}".format(group_by_field) select_mop_field = ", p.base_paid_amount - p.change_amount as paid_amount " + # nosemgrep return frappe.db.sql( """ SELECT From abc0294cbf472f1b4f3563d2e34a2a2776c50df4 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 2 Apr 2024 15:35:21 +0530 Subject: [PATCH 15/72] chore: remove enqueue submit and cancel from stock entry --- .../stock/doctype/stock_entry/stock_entry.py | 47 +------------------ .../doctype/stock_entry/test_stock_entry.py | 30 ------------ 2 files changed, 1 insertion(+), 76 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index ca31a9a3d31c..81658c42e91c 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -9,17 +9,7 @@ from frappe import _ from frappe.model.mapper import get_mapped_doc from frappe.query_builder.functions import Sum -from frappe.utils import ( - cint, - comma_or, - cstr, - flt, - format_time, - formatdate, - getdate, - month_diff, - nowdate, -) +from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate import erpnext from erpnext.accounts.general_ledger import process_gl_map @@ -168,41 +158,6 @@ def validate(self): self.reset_default_field_value("from_warehouse", "items", "s_warehouse") self.reset_default_field_value("to_warehouse", "items", "t_warehouse") - def submit(self): - if self.is_enqueue_action(): - frappe.msgprint( - _( - "The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Entry and revert to the Draft stage" - ) - ) - self.queue_action("submit", timeout=2000) - else: - self._submit() - - def cancel(self): - if self.is_enqueue_action(): - frappe.msgprint( - _( - "The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Entry and revert to the Submitted stage" - ) - ) - self.queue_action("cancel", timeout=2000) - else: - self._cancel() - - def is_enqueue_action(self, force=False) -> bool: - if force: - return True - - if frappe.flags.in_test: - return False - - # If line items are more than 100 or record is older than 6 months - if len(self.items) > 50 or month_diff(nowdate(), self.posting_date) > 6: - return True - - return False - def on_submit(self): self.update_stock_ledger() diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 771dae538645..c6814558ce17 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -1702,36 +1702,6 @@ def test_negative_stock_reco(self): self.assertRaises(frappe.ValidationError, sr_doc.submit) - def test_enqueue_action(self): - frappe.flags.in_test = False - item_code = "Test Enqueue Item - 001" - create_item(item_code=item_code, is_stock_item=1, valuation_rate=10) - - doc = make_stock_entry( - item_code=item_code, - posting_date=add_to_date(today(), months=-7), - posting_time="00:00:00", - purpose="Material Receipt", - qty=10, - to_warehouse="_Test Warehouse - _TC", - do_not_submit=True, - ) - - self.assertTrue(doc.is_enqueue_action()) - - doc = make_stock_entry( - item_code=item_code, - posting_date=today(), - posting_time="00:00:00", - purpose="Material Receipt", - qty=10, - to_warehouse="_Test Warehouse - _TC", - do_not_submit=True, - ) - - self.assertFalse(doc.is_enqueue_action()) - frappe.flags.in_test = True - def test_auto_reorder_level(self): from erpnext.stock.reorder_item import reorder_item From b55d8597e8dffee0412c3806f76b99ac1920e35c Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:14:38 +0200 Subject: [PATCH 16/72] fix: translatable web footer (#40834) (cherry picked from commit f3bcdbe5bd1a5b1da0b02a6c8fe0b213f59a62f8) --- erpnext/templates/includes/footer/footer_powered.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/templates/includes/footer/footer_powered.html b/erpnext/templates/includes/footer/footer_powered.html index faf5e9278c7f..8310063e5756 100644 --- a/erpnext/templates/includes/footer/footer_powered.html +++ b/erpnext/templates/includes/footer/footer_powered.html @@ -1 +1 @@ -Powered by ERPNext +{{ _("Powered by {0}").format('ERPNext') }} From fb076d34b1e446fea95dbc7555ea999fb61e02ce Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 3 Apr 2024 10:32:43 +0000 Subject: [PATCH 17/72] chore(release): Bumped to Version 14.66.3 ## [14.66.3](https://github.com/frappe/erpnext/compare/v14.66.2...v14.66.3) (2024-04-03) ### Bug Fixes * cost center shouldn't update debit/credit in Exc gain/loss JV ([f66b53b](https://github.com/frappe/erpnext/commit/f66b53b2c1f2855ad72500731c350bc37ccf8218)) * do not fetch received items in purchase receipt ([e778d7e](https://github.com/frappe/erpnext/commit/e778d7e69041f2f4cd63c6ecaa23a8146c86fe4f)) * linter issues ([515f933](https://github.com/frappe/erpnext/commit/515f93336263b4a865b66bd79fe8e884c88b79aa)) * markdown to text editor set for supplier quotation ([b5629d2](https://github.com/frappe/erpnext/commit/b5629d2d4e93adffda39f027a2de861167b709b6)) * payment_order_status should be no_copy ([8dff18e](https://github.com/frappe/erpnext/commit/8dff18eab478a3a17d485dc500dbcdeda84eaf0f)) * Priority not copied from project template ([4f4470b](https://github.com/frappe/erpnext/commit/4f4470b9d209dc5b2c04a2c61029d69dd4f976c8)) * show currency symbol in base currency in fixed asset register report ([cfe5f00](https://github.com/frappe/erpnext/commit/cfe5f009f6eef125d836601ab72d1913b50d90e9)) * show future payments allocated sales returns is considered as payment ([803ed90](https://github.com/frappe/erpnext/commit/803ed904a9aa1201af0b7a701861ad03a8306fcd)) * Warehouse linked company name in multicompany setup (backport [#40779](https://github.com/frappe/erpnext/issues/40779)) ([#40780](https://github.com/frappe/erpnext/issues/40780)) ([ceac42d](https://github.com/frappe/erpnext/commit/ceac42dfaa691d169603a529545c6fd70facf247)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 7e2270131e09..b82a818ad05d 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import frappe -__version__ = "14.66.2" +__version__ = "14.66.3" def get_default_company(user=None): From 9dea6d3393c6f02feed666e05d3ae792bee2afc1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 4 Apr 2024 12:06:46 +0530 Subject: [PATCH 18/72] fix: group warehouse added in the stock reconciliation (cherry picked from commit 8f53bc00969e8be6a8e40d1e9254b348917f31ed) --- .../stock_reconciliation.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 878af0e22ca2..c7608cc2dd91 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -744,7 +744,9 @@ def get_items( warehouse, posting_date, posting_time, company, item_code=None, ignore_empty_stock=False ): ignore_empty_stock = cint(ignore_empty_stock) - items = [frappe._dict({"item_code": item_code, "warehouse": warehouse})] + items = [] + if item_code and warehouse: + items = get_item_and_warehouses(item_code, warehouse) if not item_code: items = get_items_for_stock_reco(warehouse, company) @@ -789,6 +791,20 @@ def get_items( return res +def get_item_and_warehouses(item_code, warehouse): + from frappe.utils.nestedset import get_descendants_of + + items = [] + if frappe.get_cached_value("Warehouse", warehouse, "is_group"): + childrens = get_descendants_of("Warehouse", warehouse, ignore_permissions=True, order_by="lft") + for ch_warehouse in childrens: + items.append(frappe._dict({"item_code": item_code, "warehouse": ch_warehouse})) + else: + items = [frappe._dict({"item_code": item_code, "warehouse": warehouse})] + + return items + + def get_items_for_stock_reco(warehouse, company): lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) items = frappe.db.sql( @@ -803,7 +819,7 @@ def get_items_for_stock_reco(warehouse, company): and i.is_stock_item = 1 and i.has_variants = 0 and exists( - select name from `tabWarehouse` where lft >= {lft} and rgt <= {rgt} and name = bin.warehouse + select name from `tabWarehouse` where lft >= {lft} and rgt <= {rgt} and name = bin.warehouse and is_group = 0 ) """, as_dict=1, @@ -818,7 +834,7 @@ def get_items_for_stock_reco(warehouse, company): where i.name = id.parent and exists( - select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=id.default_warehouse + select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=id.default_warehouse and is_group = 0 ) and i.is_stock_item = 1 and i.has_variants = 0 @@ -880,7 +896,7 @@ def get_itemwise_batch(warehouse, posting_date, company, item_code=None): frappe._dict( { "item_code": row[0], - "warehouse": warehouse, + "warehouse": row[3], "qty": row[8], "item_name": row[1], "batch_no": row[4], From 09cda60bdf11444bb05d6ec8968deffee59559f7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 4 Apr 2024 11:58:05 +0530 Subject: [PATCH 19/72] fix: use reference type name to update exc rate (cherry picked from commit c15690e475f5f1f19d635bb78e6f1261ad9bcb1f) --- .../doctype/payment_entry/payment_entry.py | 10 +++++++--- erpnext/accounts/utils.py | 14 +++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index e0e8e2154a68..fefb331ff272 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -338,7 +338,7 @@ def set_missing_ref_details( self, force: bool = False, update_ref_details_only_for: list | None = None, - ref_exchange_rate: float | None = None, + reference_exchange_details: dict | None = None, ) -> None: for d in self.get("references"): if d.allocated_amount: @@ -352,8 +352,12 @@ def set_missing_ref_details( ) # Only update exchange rate when the reference is Journal Entry - if ref_exchange_rate and d.reference_doctype == "Journal Entry": - ref_details.update({"exchange_rate": ref_exchange_rate}) + if ( + reference_exchange_details + and d.reference_doctype == reference_exchange_details.reference_doctype + and d.reference_name == reference_exchange_details.reference_name + ): + ref_details.update({"exchange_rate": reference_exchange_details.exchange_rate}) for field, value in ref_details.items(): if d.exchange_gain_loss: diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 6ca4aa2ada6b..a8338e26a2c4 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -682,7 +682,19 @@ def update_reference_in_payment_entry( payment_entry.setup_party_account_field() payment_entry.set_missing_values() if not skip_ref_details_update_for_pe: - payment_entry.set_missing_ref_details(ref_exchange_rate=d.exchange_rate or None) + reference_exchange_details = frappe._dict() + if d.against_voucher_type == "Journal Entry" and d.exchange_rate: + reference_exchange_details.update( + { + "reference_doctype": d.against_voucher_type, + "reference_name": d.against_voucher, + "exchange_rate": d.exchange_rate, + } + ) + payment_entry.set_missing_ref_details( + update_ref_details_only_for=[(d.against_voucher_type, d.against_voucher)], + reference_exchange_details=reference_exchange_details, + ) payment_entry.set_amounts() payment_entry.make_exchange_gain_loss_journal( From 8f2fd5dec93205e816bb976da14220aa2e5ccb7b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 4 Apr 2024 14:42:06 +0530 Subject: [PATCH 20/72] test: payment against JE reconciliation with different rates (cherry picked from commit fe84558b772a345845e67f1423c6955620153fbb) --- .../tests/test_accounts_controller.py | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index e39d03dccb91..e348d296cd71 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -56,7 +56,8 @@ class TestAccountsController(FrappeTestCase): 20 series - Sales Invoice against Journals 30 series - Sales Invoice against Credit Notes 40 series - Company default Cost center is unset - 50 series = Journals against Journals + 50 series - Journals against Journals + 60 series - Journals against Payment Entries 90 series - Dimension inheritence """ @@ -1574,3 +1575,70 @@ def test_50_journal_against_journal(self): exc_je_for_je = self.get_journals_for(journal_as_payment.doctype, journal_as_payment.name) self.assertEqual(exc_je_for_si, []) self.assertEqual(exc_je_for_je, []) + + def test_60_payment_entry_against_journal(self): + # Invoices + exc_rate1 = 75 + exc_rate2 = 77 + amount = 1 + je1 = self.create_journal_entry( + acc1=self.debit_usd, + acc1_exc_rate=exc_rate1, + acc2=self.cash, + acc1_amount=amount, + acc2_amount=(amount * 75), + acc2_exc_rate=1, + ) + je1.accounts[0].party_type = "Customer" + je1.accounts[0].party = self.customer + je1 = je1.save().submit() + + je2 = self.create_journal_entry( + acc1=self.debit_usd, + acc1_exc_rate=exc_rate2, + acc2=self.cash, + acc1_amount=amount, + acc2_amount=(amount * exc_rate2), + acc2_exc_rate=1, + ) + je2.accounts[0].party_type = "Customer" + je2.accounts[0].party = self.customer + je2 = je2.save().submit() + + # Payment + pe = self.create_payment_entry(amount=2, source_exc_rate=exc_rate1).save().submit() + + pr = self.create_payment_reconciliation() + pr.receivable_payable_account = self.debit_usd + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 2) + self.assertEqual(len(pr.payments), 1) + invoices = [x.as_dict() for x in pr.invoices] + payments = [x.as_dict() for x in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + self.assertEqual(len(pr.invoices), 0) + self.assertEqual(len(pr.payments), 0) + + # There should be no outstanding in both currencies + self.assert_ledger_outstanding(je1.doctype, je1.name, 0.0, 0.0) + self.assert_ledger_outstanding(je2.doctype, je2.name, 0.0, 0.0) + + # Exchange Gain/Loss Journal should've been created only for JE2 + exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name) + exc_je_for_je2 = self.get_journals_for(je2.doctype, je2.name) + self.assertEqual(exc_je_for_je1, []) + self.assertEqual(len(exc_je_for_je2), 1) + + # Cancel Payment + pe.reload() + pe.cancel() + + self.assert_ledger_outstanding(je1.doctype, je1.name, (amount * exc_rate1), amount) + self.assert_ledger_outstanding(je2.doctype, je2.name, (amount * exc_rate2), amount) + + # Exchange Gain/Loss Journal should've been cancelled + exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name) + exc_je_for_je2 = self.get_journals_for(je2.doctype, je2.name) + self.assertEqual(exc_je_for_je1, []) + self.assertEqual(exc_je_for_je2, []) From a6145fa13c7dc6d5334cef7aeb9d712c2c9f4c27 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 7 Apr 2024 11:48:07 +0530 Subject: [PATCH 21/72] fix: query_report.trigger_refresh is not a function (cherry picked from commit 30bbb58ca146604da9b2dd362717ded1470adaa5) --- erpnext/stock/report/item_prices/item_prices.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/erpnext/stock/report/item_prices/item_prices.js b/erpnext/stock/report/item_prices/item_prices.js index 868b503eb73d..6724c1a29097 100644 --- a/erpnext/stock/report/item_prices/item_prices.js +++ b/erpnext/stock/report/item_prices/item_prices.js @@ -9,9 +9,6 @@ frappe.query_reports["Item Prices"] = { fieldtype: "Select", options: "Enabled Items only\nDisabled Items only\nAll Items", default: "Enabled Items only", - on_change: function (query_report) { - query_report.trigger_refresh(); - }, }, ], }; From 7e1ab75b382d18d8453d59c496f20641567851de Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 6 Apr 2024 15:29:00 +0530 Subject: [PATCH 22/72] fix: incorrect operator causing incorrect validation (cherry picked from commit 6b317b0c0d94f8c65743bedb444ef0a3d10beaa6) --- .../doctype/closing_stock_balance/closing_stock_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e905f6733657..c762ad68adc9 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py @@ -44,7 +44,7 @@ def validate_duplicate(self): & ( (table.from_date.between(self.from_date, self.to_date)) | (table.to_date.between(self.from_date, self.to_date)) - | (table.from_date >= self.from_date and table.to_date >= self.to_date) + | ((table.from_date >= self.from_date) & (table.to_date >= self.to_date)) ) ) ) From 10d760089e3ad44859c89dac2250c296c68dc764 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Sun, 7 Apr 2024 14:08:45 +0530 Subject: [PATCH 23/72] fix: Get pro-rata depr amount based on correct days --- erpnext/assets/doctype/asset/asset.py | 84 +++++++++++++--------- erpnext/assets/doctype/asset/test_asset.py | 42 ++++++----- 2 files changed, 75 insertions(+), 51 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 7755f3e0b646..95c627735d63 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -437,6 +437,7 @@ def _make_depreciation_schedule( depreciation_amount, from_date, date_of_disposal, + original_schedule_date=schedule_date, ) if depreciation_amount > 0: @@ -1118,14 +1119,20 @@ def get_depreciation_rate(self, args, on_validate=False): return flt((100 * (1 - depreciation_rate)), float_precision) def get_pro_rata_amt( - self, row, depreciation_amount, from_date, to_date, has_wdv_or_dd_non_yearly_pro_rata=False + self, + row, + depreciation_amount, + from_date, + to_date, + has_wdv_or_dd_non_yearly_pro_rata=False, + original_schedule_date=None, ): days = date_diff(to_date, from_date) months = month_diff(to_date, from_date) if has_wdv_or_dd_non_yearly_pro_rata: - total_days = get_total_days(to_date, 12) + total_days = get_total_days(original_schedule_date or to_date, 12) else: - total_days = get_total_days(to_date, row.frequency_of_depreciation) + total_days = get_total_days(original_schedule_date or to_date, row.frequency_of_depreciation) return (depreciation_amount * flt(days)) / flt(total_days), days, months @@ -1445,32 +1452,35 @@ def get_straight_line_or_manual_depr_amount( # if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value elif asset.flags.decrease_in_asset_value_due_to_value_adjustment: if row.daily_prorata_based: - daily_depr_amount = ( - flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life) - ) / date_diff( - get_last_day( - add_months( - row.depreciation_start_date, - flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked - 1) - * row.frequency_of_depreciation, - ) - ), - add_days( + amount = flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life) + total_days = ( + date_diff( get_last_day( add_months( row.depreciation_start_date, - flt( - row.total_number_of_depreciations - - asset.number_of_depreciations_booked - - number_of_pending_depreciations - - 1 - ) + flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked - 1) * row.frequency_of_depreciation, ) ), - 1, - ), + add_days( + get_last_day( + add_months( + row.depreciation_start_date, + flt( + row.total_number_of_depreciations + - asset.number_of_depreciations_booked + - number_of_pending_depreciations + - 1 + ) + * row.frequency_of_depreciation, + ) + ), + 1, + ), + ) + + 1 ) + daily_depr_amount = amount / total_days to_date = get_last_day( add_months(row.depreciation_start_date, schedule_idx * row.frequency_of_depreciation) @@ -1490,22 +1500,28 @@ def get_straight_line_or_manual_depr_amount( # if the Depreciation Schedule is being prepared for the first time else: if row.daily_prorata_based: - daily_depr_amount = ( + + amount = ( flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation) - flt(row.expected_value_after_useful_life) - ) / date_diff( - get_last_day( - add_months( - row.depreciation_start_date, - flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked - 1) - * row.frequency_of_depreciation, - ) - ), - add_days( - get_last_day(add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation)), 1 - ), ) + total_days = ( + date_diff( + get_last_day( + add_months( + row.depreciation_start_date, + flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked - 1) + * row.frequency_of_depreciation, + ) + ), + add_days( + get_last_day(add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation)), 1 + ), + ) + + 1 + ) + daily_depr_amount = amount / total_days to_date = get_last_day( add_months(row.depreciation_start_date, schedule_idx * row.frequency_of_depreciation) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 708172b29803..ea5b95aaf02e 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -219,7 +219,11 @@ def test_scrap_asset(self): asset.precision("gross_purchase_amount"), ) pro_rata_amount, _, _ = asset.get_pro_rata_amt( - asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date + asset.finance_books[0], + 9000, + get_last_day(add_months(purchase_date, 1)), + date, + original_schedule_date=get_last_day(nowdate()), ) pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) self.assertEquals( @@ -287,7 +291,11 @@ def test_gle_made_by_asset_sale(self): self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") pro_rata_amount, _, _ = asset.get_pro_rata_amt( - asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date + asset.finance_books[0], + 9000, + get_last_day(add_months(purchase_date, 1)), + date, + original_schedule_date=get_last_day(nowdate()), ) pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) @@ -349,7 +357,7 @@ def test_gle_made_by_asset_sale_for_existing_asset(self): self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") - expected_values = [["2023-03-31", 12000, 36000], ["2023-05-23", 1742.47, 37742.47]] + expected_values = [["2023-03-31", 12000, 36000], ["2023-05-23", 1737.7, 37737.7]] for i, schedule in enumerate(asset.schedules): self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) @@ -360,7 +368,7 @@ def test_gle_made_by_asset_sale_for_existing_asset(self): expected_gle = ( ( "_Test Accumulated Depreciations - _TC", - 37742.47, + 37737.7, 0.0, ), ( @@ -371,7 +379,7 @@ def test_gle_made_by_asset_sale_for_existing_asset(self): ( "_Test Gain/Loss on Asset Disposal - _TC", 0.0, - 17742.47, + 17737.7, ), ("Debtors - _TC", 40000.0, 0.0), ) @@ -691,18 +699,18 @@ def test_schedule_for_straight_line_method_with_daily_prorata_based( ) expected_schedules = [ - ["2023-01-31", 1021.98, 1021.98], - ["2023-02-28", 923.08, 1945.06], - ["2023-03-31", 1021.98, 2967.04], - ["2023-04-30", 989.01, 3956.05], - ["2023-05-31", 1021.98, 4978.03], - ["2023-06-30", 989.01, 5967.04], - ["2023-07-31", 1021.98, 6989.02], - ["2023-08-31", 1021.98, 8011.0], - ["2023-09-30", 989.01, 9000.01], - ["2023-10-31", 1021.98, 10021.99], - ["2023-11-30", 989.01, 11011.0], - ["2023-12-31", 989.0, 12000.0], + ["2023-01-31", 1019.18, 1019.18], + ["2023-02-28", 920.55, 1939.73], + ["2023-03-31", 1019.18, 2958.91], + ["2023-04-30", 986.3, 3945.21], + ["2023-05-31", 1019.18, 4964.39], + ["2023-06-30", 986.3, 5950.69], + ["2023-07-31", 1019.18, 6969.87], + ["2023-08-31", 1019.18, 7989.05], + ["2023-09-30", 986.3, 8975.35], + ["2023-10-31", 1019.18, 9994.53], + ["2023-11-30", 986.3, 10980.83], + ["2023-12-31", 1019.17, 12000.0], ] schedules = [ From 60ba62e882f71895256e763d830fb06de2e6ed8b Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 6 Apr 2024 15:29:00 +0530 Subject: [PATCH 24/72] fix: incorrect operator causing incorrect validation (cherry picked from commit 6b317b0c0d94f8c65743bedb444ef0a3d10beaa6) (cherry picked from commit 7e1ab75b382d18d8453d59c496f20641567851de) --- .../doctype/closing_stock_balance/closing_stock_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e905f6733657..c762ad68adc9 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py @@ -44,7 +44,7 @@ def validate_duplicate(self): & ( (table.from_date.between(self.from_date, self.to_date)) | (table.to_date.between(self.from_date, self.to_date)) - | (table.from_date >= self.from_date and table.to_date >= self.to_date) + | ((table.from_date >= self.from_date) & (table.to_date >= self.to_date)) ) ) ) From 8d8feadeae1b52b82783f2bdbd32ef4cd8067688 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Sun, 7 Apr 2024 12:34:56 +0000 Subject: [PATCH 25/72] chore(release): Bumped to Version 14.66.4 ## [14.66.4](https://github.com/frappe/erpnext/compare/v14.66.3...v14.66.4) (2024-04-07) ### Bug Fixes * incorrect operator causing incorrect validation ([60ba62e](https://github.com/frappe/erpnext/commit/60ba62e882f71895256e763d830fb06de2e6ed8b)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index b82a818ad05d..09803b970198 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import frappe -__version__ = "14.66.3" +__version__ = "14.66.4" def get_default_company(user=None): From 22b16a6b0e98ea92cc8c5822d633f1b18e8013cd Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 1 Apr 2024 16:25:35 +0530 Subject: [PATCH 26/72] refactor: merge taxes from delivery note to Sales Invoice (cherry picked from commit 550cbbd91c2b3addc493b86744b8a2e3407c4b6e) --- erpnext/controllers/accounts_controller.py | 31 ++++++++++++++++++ erpnext/public/js/utils.js | 7 ++-- .../doctype/delivery_note/delivery_note.py | 13 ++++++-- .../purchase_receipt/purchase_receipt.py | 32 +------------------ 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 61bdc4f52a9d..52f95ee63235 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -3313,6 +3313,37 @@ def check_if_child_table_updated( return False +def merge_taxes(source_taxes, target_doc): + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + update_item_wise_tax_detail, + ) + + existing_taxes = target_doc.get("taxes") or [] + idx = 1 + for tax in source_taxes: + found = False + for t in existing_taxes: + if t.account_head == tax.account_head and t.cost_center == tax.cost_center: + t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount_after_discount_amount) + t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount_after_discount_amount) + update_item_wise_tax_detail(t, tax) + found = True + + if not found: + tax.charge_type = "Actual" + tax.idx = idx + idx += 1 + tax.included_in_print_rate = 0 + tax.dont_recompute_tax = 1 + tax.row_id = "" + tax.tax_amount = tax.tax_amount_after_discount_amount + tax.base_tax_amount = tax.base_tax_amount_after_discount_amount + tax.item_wise_tax_detail = tax.item_wise_tax_detail + existing_taxes.append(tax) + + target_doc.set("taxes", existing_taxes) + + @erpnext.allow_regional def validate_regional(doc): pass diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 429363f1e5c2..716b655d7395 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -819,7 +819,7 @@ erpnext.utils.map_current_doc = function (opts) { if (opts.source_doctype) { let data_fields = []; - if (opts.source_doctype == "Purchase Receipt") { + if (["Purchase Receipt", "Delivery Note"].includes(opts.source_doctype)) { data_fields.push({ fieldname: "merge_taxes", fieldtype: "Check", @@ -845,7 +845,10 @@ erpnext.utils.map_current_doc = function (opts) { return; } opts.source_name = values; - if (opts.allow_child_item_selection || opts.source_doctype == "Purchase Receipt") { + if ( + opts.allow_child_item_selection || + ["Purchase Receipt", "Delivery Note"].includes(opts.source_doctype) + ) { // args contains filtered child docnames opts.args = args; } diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 0a389b602a51..88552d8de083 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -10,7 +10,7 @@ from frappe.model.utils import get_fetch_values from frappe.utils import cint, flt -from erpnext.controllers.accounts_controller import get_taxes_and_charges +from erpnext.controllers.accounts_controller import get_taxes_and_charges, merge_taxes from erpnext.controllers.selling_controller import SellingController from erpnext.stock.doctype.batch.batch import set_batch_nos from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no @@ -623,7 +623,7 @@ def get_returned_qty_map(delivery_note): @frappe.whitelist() -def make_sales_invoice(source_name, target_doc=None): +def make_sales_invoice(source_name, target_doc=None, args=None): doc = frappe.get_doc("Delivery Note", source_name) to_make_invoice_qty_map = {} @@ -637,6 +637,9 @@ def set_missing_values(source, target): if len(target.get("items")) == 0: frappe.throw(_("All these items have already been Invoiced/Returned")) + if args and args.get("merge_taxes"): + merge_taxes(source.get("taxes") or [], target) + target.run_method("calculate_taxes_and_totals") # set company address @@ -701,7 +704,11 @@ def get_pending_qty(item_row): if not doc.get("is_return") else get_pending_qty(d) > 0, }, - "Sales Taxes and Charges": {"doctype": "Sales Taxes and Charges", "add_if_empty": True}, + "Sales Taxes and Charges": { + "doctype": "Sales Taxes and Charges", + "add_if_empty": True, + "ignore": args.get("merge_taxes") if args else 0, + }, "Sales Team": { "doctype": "Sales Team", "field_map": {"incentives": "incentives"}, diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 79e6ab84d950..064c717c3205 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -14,6 +14,7 @@ from erpnext.accounts.utils import get_account_currency from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled from erpnext.buying.utils import check_on_hold_or_closed_status +from erpnext.controllers.accounts_controller import merge_taxes from erpnext.controllers.buying_controller import BuyingController from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_transaction @@ -974,37 +975,6 @@ def get_item_wise_returned_qty(pr_doc): ) -def merge_taxes(source_taxes, target_doc): - from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( - update_item_wise_tax_detail, - ) - - existing_taxes = target_doc.get("taxes") or [] - idx = 1 - for tax in source_taxes: - found = False - for t in existing_taxes: - if t.account_head == tax.account_head and t.cost_center == tax.cost_center: - t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount_after_discount_amount) - t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount_after_discount_amount) - update_item_wise_tax_detail(t, tax) - found = True - - if not found: - tax.charge_type = "Actual" - tax.idx = idx - idx += 1 - tax.included_in_print_rate = 0 - tax.dont_recompute_tax = 1 - tax.row_id = "" - tax.tax_amount = tax.tax_amount_after_discount_amount - tax.base_tax_amount = tax.base_tax_amount_after_discount_amount - tax.item_wise_tax_detail = tax.item_wise_tax_detail - existing_taxes.append(tax) - - target_doc.set("taxes", existing_taxes) - - @frappe.whitelist() def make_purchase_invoice(source_name, target_doc=None, args=None): from erpnext.accounts.party import get_payment_terms_template From ae1858f4653590d0cbd44eaec00d933e908fbae9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 8 Apr 2024 14:20:45 +0530 Subject: [PATCH 27/72] test: tax merging from 2 Delivery Note to Sales Invoice (cherry picked from commit 39a48a2e2a711312dc8b5d2d10d171ed46bcf74f) # Conflicts: # erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py --- .../sales_invoice/test_sales_invoice.py | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4d0f6446da4d..730f1fd23fe5 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3439,12 +3439,230 @@ def test_sales_return_negative_rate(self): si.save() +<<<<<<< HEAD def get_sales_invoice_for_e_invoice(): si = make_sales_invoice_for_ewaybill() si.naming_series = "INV-2020-.#####" si.items = [] si.append( "items", +======= + 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 test_pulling_advance_based_on_debit_to(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry + + debtors2 = create_account( + parent_account="Accounts Receivable - _TC", + account_name="Debtors 2", + company="_Test Company", + account_type="Receivable", + ) + si = create_sales_invoice(do_not_submit=True) + si.debit_to = debtors2 + si.save() + + pe = create_payment_entry( + company=si.company, + payment_type="Receive", + party_type="Customer", + party=si.customer, + paid_from=debtors2, + paid_to="Cash - _TC", + paid_amount=1000, + ) + pe.submit() + advances = si.get_advance_entries() + self.assertEqual(1, len(advances)) + self.assertEqual(advances[0].reference_name, pe.name) + + def test_taxes_merging_from_delivery_note(self): + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + + dn1 = create_delivery_note(do_not_submit=1) + dn1.items[0].qty = 10 + dn1.items[0].rate = 100 + dn1.append( + "taxes", + { + "charge_type": "Actual", + "account_head": "Freight and Forwarding Charges - _TC", + "description": "movement charges", + "tax_amount": 100, + }, + ) + dn1.append( + "taxes", + { + "charge_type": "Actual", + "account_head": "Marketing Expenses - _TC", + "description": "marketing", + "tax_amount": 150, + }, + ) + dn1.save().submit() + + dn2 = create_delivery_note(do_not_submit=1) + dn2.items[0].qty = 5 + dn2.items[0].rate = 100 + dn2.append( + "taxes", + { + "charge_type": "Actual", + "account_head": "Freight and Forwarding Charges - _TC", + "description": "movement charges", + "tax_amount": 20, + }, + ) + dn2.append( + "taxes", + { + "charge_type": "Actual", + "account_head": "Miscellaneous Expenses - _TC", + "description": "marketing", + "tax_amount": 60, + }, + ) + dn2.save().submit() + + # si = make_sales_invoice(dn1.name) + si = create_sales_invoice(do_not_submit=True) + si.customer = dn1.customer + si.items.clear() + + from frappe.model.mapper import map_docs + + map_docs( + method="erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice", + source_names=frappe.json.dumps([dn1.name, dn2.name]), + target_doc=si, + args=frappe.json.dumps({"customer": dn1.customer, "merge_taxes": 1, "filtered_children": []}), + ) + si.save().submit() + + expected = [ + { + "charge_type": "Actual", + "account_head": "Freight and Forwarding Charges - _TC", + "tax_amount": 120.0, + "total": 1520.0, + "base_total": 1520.0, + }, + { + "charge_type": "Actual", + "account_head": "Marketing Expenses - _TC", + "tax_amount": 150.0, + "total": 1670.0, + "base_total": 1670.0, + }, + { + "charge_type": "Actual", + "account_head": "Miscellaneous Expenses - _TC", + "tax_amount": 60.0, + "total": 1610.0, + "base_total": 1610.0, + }, + ] + actual = [ + dict( + charge_type=x.charge_type, + account_head=x.account_head, + tax_amount=x.tax_amount, + total=x.total, + base_total=x.base_total, + ) + for x in si.taxes + ] + self.assertEqual(expected, actual) + + +def set_advance_flag(company, flag, default_account): + frappe.db.set_value( + "Company", + company, +>>>>>>> 39a48a2e2a (test: tax merging from 2 Delivery Note to Sales Invoice) { "item_code": "_Test Item", "uom": "Nos", From b76c00de68f33889378c4a4e8cb129c92b9e73f8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 8 Apr 2024 15:44:13 +0530 Subject: [PATCH 28/72] chore: resolve conflict --- .../sales_invoice/test_sales_invoice.py | 131 +----------------- 1 file changed, 6 insertions(+), 125 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 730f1fd23fe5..5993c81a1748 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3438,126 +3438,6 @@ def test_sales_return_negative_rate(self): si.items[0].rate = 10 si.save() - -<<<<<<< HEAD -def get_sales_invoice_for_e_invoice(): - si = make_sales_invoice_for_ewaybill() - si.naming_series = "INV-2020-.#####" - si.items = [] - si.append( - "items", -======= - 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 test_pulling_advance_based_on_debit_to(self): - from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry - - debtors2 = create_account( - parent_account="Accounts Receivable - _TC", - account_name="Debtors 2", - company="_Test Company", - account_type="Receivable", - ) - si = create_sales_invoice(do_not_submit=True) - si.debit_to = debtors2 - si.save() - - pe = create_payment_entry( - company=si.company, - payment_type="Receive", - party_type="Customer", - party=si.customer, - paid_from=debtors2, - paid_to="Cash - _TC", - paid_amount=1000, - ) - pe.submit() - advances = si.get_advance_entries() - self.assertEqual(1, len(advances)) - self.assertEqual(advances[0].reference_name, pe.name) - def test_taxes_merging_from_delivery_note(self): from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note @@ -3658,11 +3538,12 @@ def test_taxes_merging_from_delivery_note(self): self.assertEqual(expected, actual) -def set_advance_flag(company, flag, default_account): - frappe.db.set_value( - "Company", - company, ->>>>>>> 39a48a2e2a (test: tax merging from 2 Delivery Note to Sales Invoice) +def get_sales_invoice_for_e_invoice(): + si = make_sales_invoice_for_ewaybill() + si.naming_series = "INV-2020-.#####" + si.items = [] + si.append( + "items", { "item_code": "_Test Item", "uom": "Nos", From 0172880fd3a20a4a6a07685c208bbb5d1df7afd9 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Mon, 8 Apr 2024 15:47:18 +0530 Subject: [PATCH 29/72] feat: new hook `fields_for_group_similar_items` to group additional fields for print formats (#40831) (cherry picked from commit f7c9e1538b0814c06ec1dd8abe971113e0662132) # Conflicts: # erpnext/hooks.py --- erpnext/controllers/accounts_controller.py | 22 ++++++++++++++-------- erpnext/hooks.py | 12 ++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 61bdc4f52a9d..4f2856d98c86 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -3,6 +3,7 @@ import json +from collections import defaultdict import frappe from frappe import _, bold, qb, throw @@ -1947,21 +1948,26 @@ def delink_advance_entries(self, linked_doc_name): ) def group_similar_items(self): - group_item_qty = {} - group_item_amount = {} + grouped_items = {} # to update serial number in print count = 0 + fields_to_group = frappe.get_hooks("fields_for_group_similar_items") + fields_to_group = set(fields_to_group) + for item in self.items: - group_item_qty[item.item_code] = group_item_qty.get(item.item_code, 0) + item.qty - group_item_amount[item.item_code] = group_item_amount.get(item.item_code, 0) + item.amount + item_values = grouped_items.setdefault(item.item_code, defaultdict(int)) + + for field in fields_to_group: + item_values[field] += item.get(field, 0) duplicate_list = [] for item in self.items: - if item.item_code in group_item_qty: + if item.item_code in grouped_items: count += 1 - item.qty = group_item_qty[item.item_code] - item.amount = group_item_amount[item.item_code] + + for field in fields_to_group: + item.set(field, grouped_items[item.item_code][field]) if item.qty: item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate")) @@ -1969,7 +1975,7 @@ def group_similar_items(self): item.rate = 0 item.idx = count - del group_item_qty[item.item_code] + del grouped_items[item.item_code] else: duplicate_list.append(item) for item in duplicate_list: diff --git a/erpnext/hooks.py b/erpnext/hooks.py index e328c686f5dc..68340f9f68a4 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -643,3 +643,15 @@ "erpnext.support.doctype.service_level_agreement.service_level_agreement.add_sla_doctypes", "erpnext.startup.boot.bootinfo", ] +<<<<<<< HEAD +======= + + +default_log_clearing_doctypes = { + "Repost Item Valuation": 60, +} + +export_python_type_annotations = True + +fields_for_group_similar_items = ["qty", "amount"] +>>>>>>> f7c9e1538b (feat: new hook `fields_for_group_similar_items` to group additional fields for print formats (#40831)) From 24709ab4007c1f2d29abe350386e483842a1eea3 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 8 Apr 2024 15:50:58 +0530 Subject: [PATCH 30/72] chore: fix conflict --- erpnext/hooks.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 68340f9f68a4..fdaae5cc7e49 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -643,15 +643,5 @@ "erpnext.support.doctype.service_level_agreement.service_level_agreement.add_sla_doctypes", "erpnext.startup.boot.bootinfo", ] -<<<<<<< HEAD -======= - - -default_log_clearing_doctypes = { - "Repost Item Valuation": 60, -} - -export_python_type_annotations = True fields_for_group_similar_items = ["qty", "amount"] ->>>>>>> f7c9e1538b (feat: new hook `fields_for_group_similar_items` to group additional fields for print formats (#40831)) From 3165682d7a6efb73b1123998417ef0356c276bd2 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 8 Apr 2024 19:03:36 +0530 Subject: [PATCH 31/72] perf: memory consumption for the Batch-Wise Balance History report --- .../batch_wise_balance_history.py | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py index 31ea576ec1d9..e6490f1717aa 100644 --- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py +++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py @@ -117,34 +117,37 @@ def get_stock_ledger_entries(filters): if filters.get(field): query = query.where(sle[field] == filters.get(field)) - return query.run(as_dict=True) + return query def get_item_warehouse_batch_map(filters, float_precision): - sle = get_stock_ledger_entries(filters) - iwb_map = {} + with frappe.db.unbuffered_cursor(): + sle = get_stock_ledger_entries(filters) + sle = sle.run(as_dict=True, as_iterator=True) - from_date = getdate(filters["from_date"]) - to_date = getdate(filters["to_date"]) + iwb_map = {} - for d in sle: - iwb_map.setdefault(d.item_code, {}).setdefault(d.warehouse, {}).setdefault( - d.batch_no, frappe._dict({"opening_qty": 0.0, "in_qty": 0.0, "out_qty": 0.0, "bal_qty": 0.0}) - ) - qty_dict = iwb_map[d.item_code][d.warehouse][d.batch_no] - if d.posting_date < from_date: - qty_dict.opening_qty = flt(qty_dict.opening_qty, float_precision) + flt( - d.actual_qty, float_precision + from_date = getdate(filters["from_date"]) + to_date = getdate(filters["to_date"]) + + for d in sle: + iwb_map.setdefault(d.item_code, {}).setdefault(d.warehouse, {}).setdefault( + d.batch_no, frappe._dict({"opening_qty": 0.0, "in_qty": 0.0, "out_qty": 0.0, "bal_qty": 0.0}) ) - elif d.posting_date >= from_date and d.posting_date <= to_date: - if flt(d.actual_qty) > 0: - qty_dict.in_qty = flt(qty_dict.in_qty, float_precision) + flt(d.actual_qty, float_precision) - else: - qty_dict.out_qty = flt(qty_dict.out_qty, float_precision) + abs( - flt(d.actual_qty, float_precision) + qty_dict = iwb_map[d.item_code][d.warehouse][d.batch_no] + if d.posting_date < from_date: + qty_dict.opening_qty = flt(qty_dict.opening_qty, float_precision) + flt( + d.actual_qty, float_precision ) - - qty_dict.bal_qty = flt(qty_dict.bal_qty, float_precision) + flt(d.actual_qty, float_precision) + elif d.posting_date >= from_date and d.posting_date <= to_date: + if flt(d.actual_qty) > 0: + qty_dict.in_qty = flt(qty_dict.in_qty, float_precision) + flt(d.actual_qty, float_precision) + else: + qty_dict.out_qty = flt(qty_dict.out_qty, float_precision) + abs( + flt(d.actual_qty, float_precision) + ) + + qty_dict.bal_qty = flt(qty_dict.bal_qty, float_precision) + flt(d.actual_qty, float_precision) return iwb_map From 5896e755bf3cf9e5b4385699b6ddfc7cef852b4f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Apr 2024 17:39:32 +0530 Subject: [PATCH 32/72] fix: incorrect currency symbol in General Ledger print (cherry picked from commit 429e036e8c3c9f27d1abe2e1820f110072639191) --- erpnext/accounts/report/general_ledger/general_ledger.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html index 2d5ca497654f..3c4e1a05c97a 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.html +++ b/erpnext/accounts/report/general_ledger/general_ledger.html @@ -55,10 +55,10 @@
- {%= format_currency(data[i].debit, filters.presentation_currency) %} + {%= format_currency(data[i].debit, filters.presentation_currency || data[i].account_currency) %} - {%= format_currency(data[i].credit, filters.presentation_currency) %} + {%= format_currency(data[i].credit, filters.presentation_currency || data[i].account_currency) %} {% } else { %} From b667a024709ce70851eaf308ff48e6550e9c07af Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Mar 2024 17:04:48 +0530 Subject: [PATCH 33/72] feat: ledger health doctype (cherry picked from commit 9ed74dd8cc8911f25af31a21dfec1b5185b4b49a) --- .../doctype/ledger_health/__init__.py | 0 .../doctype/ledger_health/ledger_health.js | 8 +++ .../doctype/ledger_health/ledger_health.json | 55 +++++++++++++++++++ .../doctype/ledger_health/ledger_health.py | 23 ++++++++ .../ledger_health/test_ledger_health.py | 9 +++ 5 files changed, 95 insertions(+) create mode 100644 erpnext/accounts/doctype/ledger_health/__init__.py create mode 100644 erpnext/accounts/doctype/ledger_health/ledger_health.js create mode 100644 erpnext/accounts/doctype/ledger_health/ledger_health.json create mode 100644 erpnext/accounts/doctype/ledger_health/ledger_health.py create mode 100644 erpnext/accounts/doctype/ledger_health/test_ledger_health.py diff --git a/erpnext/accounts/doctype/ledger_health/__init__.py b/erpnext/accounts/doctype/ledger_health/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.js b/erpnext/accounts/doctype/ledger_health/ledger_health.js new file mode 100644 index 000000000000..e207daef5115 --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.js @@ -0,0 +1,8 @@ +// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Ledger Health", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.json b/erpnext/accounts/doctype/ledger_health/ledger_health.json new file mode 100644 index 000000000000..b7dfdec937ea --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.json @@ -0,0 +1,55 @@ +{ + "actions": [], + "autoname": "autoincrement", + "creation": "2024-03-26 17:01:47.443986", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "voucher_type", + "voucher_no", + "debit_credit_mismatch" + ], + "fields": [ + { + "fieldname": "voucher_type", + "fieldtype": "Data", + "label": "Voucher Type" + }, + { + "fieldname": "voucher_no", + "fieldtype": "Data", + "label": "Voucher No" + }, + { + "default": "0", + "fieldname": "debit_credit_mismatch", + "fieldtype": "Check", + "label": "Debit-Credit mismatch" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2024-03-26 17:53:04.985881", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Ledger Health", + "naming_rule": "Autoincrement", + "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/accounts/doctype/ledger_health/ledger_health.py b/erpnext/accounts/doctype/ledger_health/ledger_health.py new file mode 100644 index 000000000000..f2fe23560fe8 --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.py @@ -0,0 +1,23 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class LedgerHealth(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + debit_credit_mismatch: DF.Check + name: DF.Int | None + voucher_no: DF.Data | None + voucher_type: DF.Data | None + # end: auto-generated types + + pass diff --git a/erpnext/accounts/doctype/ledger_health/test_ledger_health.py b/erpnext/accounts/doctype/ledger_health/test_ledger_health.py new file mode 100644 index 000000000000..ca647c99be92 --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health/test_ledger_health.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestLedgerHealth(FrappeTestCase): + pass From 153fc914786df908c2a9392b5cdf3dd9380e5697 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Mar 2024 17:57:04 +0530 Subject: [PATCH 34/72] refactor: date on which vouchers was reported (cherry picked from commit 402ffc6d27374b413af6b95d9b715acc82d34a20) --- .../accounts/doctype/ledger_health/ledger_health.json | 10 ++++++++-- .../accounts/doctype/ledger_health/ledger_health.py | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.json b/erpnext/accounts/doctype/ledger_health/ledger_health.json index b7dfdec937ea..2bb1ccb48a87 100644 --- a/erpnext/accounts/doctype/ledger_health/ledger_health.json +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.json @@ -7,7 +7,8 @@ "field_order": [ "voucher_type", "voucher_no", - "debit_credit_mismatch" + "debit_credit_mismatch", + "checked_on" ], "fields": [ { @@ -25,11 +26,16 @@ "fieldname": "debit_credit_mismatch", "fieldtype": "Check", "label": "Debit-Credit mismatch" + }, + { + "fieldname": "checked_on", + "fieldtype": "Datetime", + "label": "Checked On" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-03-26 17:53:04.985881", + "modified": "2024-03-26 17:54:47.662290", "modified_by": "Administrator", "module": "Accounts", "name": "Ledger Health", diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.py b/erpnext/accounts/doctype/ledger_health/ledger_health.py index f2fe23560fe8..f4a3af10f586 100644 --- a/erpnext/accounts/doctype/ledger_health/ledger_health.py +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.py @@ -14,6 +14,7 @@ class LedgerHealth(Document): if TYPE_CHECKING: from frappe.types import DF + checked_on: DF.Datetime | None debit_credit_mismatch: DF.Check name: DF.Int | None voucher_no: DF.Data | None From bbe4ca7d7459719d56ebc427063c007082274286 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Mar 2024 20:00:48 +0530 Subject: [PATCH 35/72] refactor: flag for general and payment ledger mismatch (cherry picked from commit d620b9eae8899c62302531e671f5d8c47d06672b) --- .../accounts/doctype/ledger_health/ledger_health.json | 11 +++++++++-- .../accounts/doctype/ledger_health/ledger_health.py | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.json b/erpnext/accounts/doctype/ledger_health/ledger_health.json index 2bb1ccb48a87..e17f4e8f2d74 100644 --- a/erpnext/accounts/doctype/ledger_health/ledger_health.json +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.json @@ -7,8 +7,9 @@ "field_order": [ "voucher_type", "voucher_no", + "checked_on", "debit_credit_mismatch", - "checked_on" + "general_and_payment_ledger_mismatch" ], "fields": [ { @@ -31,11 +32,17 @@ "fieldname": "checked_on", "fieldtype": "Datetime", "label": "Checked On" + }, + { + "default": "0", + "fieldname": "general_and_payment_ledger_mismatch", + "fieldtype": "Check", + "label": "General and Payment Ledger mismatch" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-03-26 17:54:47.662290", + "modified": "2024-03-26 19:59:41.180161", "modified_by": "Administrator", "module": "Accounts", "name": "Ledger Health", diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.py b/erpnext/accounts/doctype/ledger_health/ledger_health.py index f4a3af10f586..590ff80cc110 100644 --- a/erpnext/accounts/doctype/ledger_health/ledger_health.py +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.py @@ -16,6 +16,7 @@ class LedgerHealth(Document): checked_on: DF.Datetime | None debit_credit_mismatch: DF.Check + general_and_payment_ledger_mismatch: DF.Check name: DF.Int | None voucher_no: DF.Data | None voucher_type: DF.Data | None From 58698c9aa4b04f80a6090bc9950e4ab68f4cd1f7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Mar 2024 17:57:43 +0530 Subject: [PATCH 36/72] refactor: barebones method to run checks (cherry picked from commit 8c8d9be8105918b86b80c0488557f94bc82ecebd) # Conflicts: # erpnext/accounts/utils.py --- erpnext/accounts/utils.py | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index a8338e26a2c4..29c08538c945 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -13,11 +13,13 @@ from frappe.query_builder.functions import Round, Sum from frappe.query_builder.utils import DocType from frappe.utils import ( + add_days, cint, create_batch, cstr, flt, formatdate, + get_datetime, get_number_format_info, getdate, now, @@ -2084,3 +2086,47 @@ def create_gain_loss_journal( journal_entry.save() journal_entry.submit() return journal_entry.name +<<<<<<< HEAD +======= + + +def get_party_types_from_account_type(account_type): + return frappe.db.get_all("Party Type", {"account_type": account_type}, pluck="name") + + +def run_ledger_health_checks(): + # run for last 1 month + period_end = getdate() + period_start = add_days(period_end, -100) + + run_date = get_datetime() + + # Debit-Credit mismatch report + voucher_wise = frappe.get_doc("Report", "Voucher-wise Balance") + + # todo: company and dates should be configurable + filters = {"company": "நுண்ணறி", "from_date": period_start, "to_date": period_end} + + res = voucher_wise.execute_script_report(filters=filters) + for x in res[1]: + doc = frappe.new_doc("Ledger Health") + doc.voucher_type = x.voucher_type + doc.voucher_no = x.voucher_no + doc.debit_credit_mismatch = True + doc.checked_on = run_date + doc.save() + + # General Ledger and Payment Ledger discrepancy + gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") + # todo: company and dates should be configurable + filters = {"company": "நுண்ணறி", "period_start_date": period_start, "period_end_date": period_end} + res = gl_pl_comparison.execute_script_report(filters=filters) + + for x in res[1]: + doc = frappe.new_doc("Ledger Health") + doc.voucher_type = x.voucher_type + doc.voucher_no = x.voucher_no + doc.general_and_payment_ledger_mismatch = True + doc.checked_on = run_date + doc.save() +>>>>>>> 8c8d9be810 (refactor: barebones method to run checks) From 7a6ffccecc5955b5a18fcf4c3b425dd31926e6ee Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Mar 2024 09:41:43 +0530 Subject: [PATCH 37/72] chore: settings page for health monitor (cherry picked from commit b2fb7843d1b441ccfad7e84e5828e581f8967930) --- .../doctype/ledger_health_monitor/__init__.py | 0 .../ledger_health_monitor.js | 8 +++ .../ledger_health_monitor.json | 70 +++++++++++++++++++ .../ledger_health_monitor.py | 23 ++++++ .../test_ledger_health_monitor.py | 9 +++ 5 files changed, 110 insertions(+) create mode 100644 erpnext/accounts/doctype/ledger_health_monitor/__init__.py create mode 100644 erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.js create mode 100644 erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json create mode 100644 erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py create mode 100644 erpnext/accounts/doctype/ledger_health_monitor/test_ledger_health_monitor.py diff --git a/erpnext/accounts/doctype/ledger_health_monitor/__init__.py b/erpnext/accounts/doctype/ledger_health_monitor/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.js b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.js new file mode 100644 index 000000000000..cf112760f8ce --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.js @@ -0,0 +1,8 @@ +// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Ledger Health Monitor", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json new file mode 100644 index 000000000000..9a916484925f --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json @@ -0,0 +1,70 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2024-03-27 09:38:07.427997", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "enable_health_monitor", + "monitor_section", + "monitor_for_last_x_days", + "debit_credit_mismatch", + "general_and_payment_ledger_mismatch" + ], + "fields": [ + { + "default": "0", + "fieldname": "enable_health_monitor", + "fieldtype": "Check", + "label": "Enable Health Monitor" + }, + { + "fieldname": "monitor_section", + "fieldtype": "Section Break", + "label": "Monitor" + }, + { + "default": "0", + "fieldname": "debit_credit_mismatch", + "fieldtype": "Check", + "label": "Debit-Credit Mismatch" + }, + { + "default": "0", + "fieldname": "general_and_payment_ledger_mismatch", + "fieldtype": "Check", + "label": "Discrepancy between General and Payment Ledger" + }, + { + "default": "60", + "fieldname": "monitor_for_last_x_days", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Monitor for Last 'X' days", + "reqd": 1 + } + ], + "index_web_pages_for_search": 1, + "issingle": 1, + "links": [], + "modified": "2024-03-27 09:53:00.674708", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Ledger Health Monitor", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 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/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py new file mode 100644 index 000000000000..c6a33790ee95 --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py @@ -0,0 +1,23 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class LedgerHealthMonitor(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + debit_credit_mismatch: DF.Check + enable_health_monitor: DF.Check + general_and_payment_ledger_mismatch: DF.Check + monitor_for_last_x_days: DF.Int + # end: auto-generated types + + pass diff --git a/erpnext/accounts/doctype/ledger_health_monitor/test_ledger_health_monitor.py b/erpnext/accounts/doctype/ledger_health_monitor/test_ledger_health_monitor.py new file mode 100644 index 000000000000..e0ba4435b825 --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health_monitor/test_ledger_health_monitor.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestLedgerHealthMonitor(FrappeTestCase): + pass From 9981a900b2d66452eb29333dac4941d352313fc2 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Mar 2024 10:01:03 +0530 Subject: [PATCH 38/72] refactor: control monitoring through settings page (cherry picked from commit a42482ce352432a56425434181b738145eb736f4) # Conflicts: # erpnext/accounts/utils.py --- erpnext/accounts/utils.py | 60 ++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 29c08538c945..e617d12b9e68 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -2095,27 +2095,38 @@ def get_party_types_from_account_type(account_type): def run_ledger_health_checks(): - # run for last 1 month - period_end = getdate() - period_start = add_days(period_end, -100) - - run_date = get_datetime() - - # Debit-Credit mismatch report - voucher_wise = frappe.get_doc("Report", "Voucher-wise Balance") - - # todo: company and dates should be configurable - filters = {"company": "நுண்ணறி", "from_date": period_start, "to_date": period_end} - - res = voucher_wise.execute_script_report(filters=filters) - for x in res[1]: - doc = frappe.new_doc("Ledger Health") - doc.voucher_type = x.voucher_type - doc.voucher_no = x.voucher_no - doc.debit_credit_mismatch = True - doc.checked_on = run_date - doc.save() + health_monitor_settings = frappe.get_doc("Ledger Health Monitor") + if health_monitor_settings.enable_health_monitor: + period_end = getdate() + period_start = add_days(period_end, -abs(health_monitor_settings.monitor_for_last_x_days)) + + run_date = get_datetime() + + # Debit-Credit mismatch report + if health_monitor_settings.debit_credit_mismatch: + voucher_wise = frappe.get_doc("Report", "Voucher-wise Balance") + filters = {"company": "நுண்ணறி", "from_date": period_start, "to_date": period_end} + + res = voucher_wise.execute_script_report(filters=filters) + for x in res[1]: + doc = frappe.new_doc("Ledger Health") + doc.voucher_type = x.voucher_type + doc.voucher_no = x.voucher_no + doc.debit_credit_mismatch = True + doc.checked_on = run_date + doc.save() + + # General Ledger and Payment Ledger discrepancy + if health_monitor_settings.general_and_payment_ledger_mismatch: + gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") + filters = { + "company": "நுண்ணறி", + "period_start_date": period_start, + "period_end_date": period_end, + } + res = gl_pl_comparison.execute_script_report(filters=filters) +<<<<<<< HEAD # General Ledger and Payment Ledger discrepancy gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") # todo: company and dates should be configurable @@ -2130,3 +2141,12 @@ def run_ledger_health_checks(): doc.checked_on = run_date doc.save() >>>>>>> 8c8d9be810 (refactor: barebones method to run checks) +======= + for x in res[1]: + doc = frappe.new_doc("Ledger Health") + doc.voucher_type = x.voucher_type + doc.voucher_no = x.voucher_no + doc.general_and_payment_ledger_mismatch = True + doc.checked_on = run_date + doc.save() +>>>>>>> a42482ce35 (refactor: control monitoring through settings page) From f86c035f888bc091dacb7dcad0d3addf42258aa3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Mar 2024 10:07:48 +0530 Subject: [PATCH 39/72] refactor: make health check configurable for companies (cherry picked from commit 704925549b4e044ee8b55f8322e4216e25c3764b) --- .../ledger_health_monitor.json | 18 +++++++++-- .../ledger_health_monitor.py | 5 +++ .../ledger_health_monitor_company/__init__.py | 0 .../ledger_health_monitor_company.json | 32 +++++++++++++++++++ .../ledger_health_monitor_company.py | 23 +++++++++++++ 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 erpnext/accounts/doctype/ledger_health_monitor_company/__init__.py create mode 100644 erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.json create mode 100644 erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.py diff --git a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json index 9a916484925f..4c1c8f80ac91 100644 --- a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json +++ b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json @@ -9,7 +9,9 @@ "monitor_section", "monitor_for_last_x_days", "debit_credit_mismatch", - "general_and_payment_ledger_mismatch" + "general_and_payment_ledger_mismatch", + "section_break_xdsp", + "companies" ], "fields": [ { @@ -21,7 +23,7 @@ { "fieldname": "monitor_section", "fieldtype": "Section Break", - "label": "Monitor" + "label": "Configuration" }, { "default": "0", @@ -42,12 +44,22 @@ "in_list_view": 1, "label": "Monitor for Last 'X' days", "reqd": 1 + }, + { + "fieldname": "section_break_xdsp", + "fieldtype": "Section Break", + "label": "Companies" + }, + { + "fieldname": "companies", + "fieldtype": "Table", + "options": "Ledger Health Monitor Company" } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2024-03-27 09:53:00.674708", + "modified": "2024-03-27 10:07:28.601546", "modified_by": "Administrator", "module": "Accounts", "name": "Ledger Health Monitor", diff --git a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py index c6a33790ee95..9f7c569d6d1d 100644 --- a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py +++ b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.py @@ -14,6 +14,11 @@ class LedgerHealthMonitor(Document): if TYPE_CHECKING: from frappe.types import DF + from erpnext.accounts.doctype.ledger_health_monitor_company.ledger_health_monitor_company import ( + LedgerHealthMonitorCompany, + ) + + companies: DF.Table[LedgerHealthMonitorCompany] debit_credit_mismatch: DF.Check enable_health_monitor: DF.Check general_and_payment_ledger_mismatch: DF.Check diff --git a/erpnext/accounts/doctype/ledger_health_monitor_company/__init__.py b/erpnext/accounts/doctype/ledger_health_monitor_company/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.json b/erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.json new file mode 100644 index 000000000000..87fa3e328015 --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.json @@ -0,0 +1,32 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2024-03-27 10:04:45.727054", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company" + ], + "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2024-03-27 10:06:22.806155", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Ledger Health Monitor Company", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.py b/erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.py new file mode 100644 index 000000000000..5890410090dc --- /dev/null +++ b/erpnext/accounts/doctype/ledger_health_monitor_company/ledger_health_monitor_company.py @@ -0,0 +1,23 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class LedgerHealthMonitorCompany(Document): + # begin: auto-generated types + # This 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 From 6273a31b8c73426e37a23dd7f69e4df313dce1b0 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Mar 2024 10:10:55 +0530 Subject: [PATCH 40/72] refactor: only run checks on specified companies (cherry picked from commit 00eeacd06af69a5c65b90c629d7497d8b1357751) # Conflicts: # erpnext/accounts/utils.py --- erpnext/accounts/utils.py | 40 ++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index e617d12b9e68..c7fd17c33df3 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -2104,20 +2104,21 @@ def run_ledger_health_checks(): # Debit-Credit mismatch report if health_monitor_settings.debit_credit_mismatch: - voucher_wise = frappe.get_doc("Report", "Voucher-wise Balance") - filters = {"company": "நுண்ணறி", "from_date": period_start, "to_date": period_end} - - res = voucher_wise.execute_script_report(filters=filters) - for x in res[1]: - doc = frappe.new_doc("Ledger Health") - doc.voucher_type = x.voucher_type - doc.voucher_no = x.voucher_no - doc.debit_credit_mismatch = True - doc.checked_on = run_date - doc.save() + for x in health_monitor_settings.companies: + filters = {"company": x.company, "from_date": period_start, "to_date": period_end} + voucher_wise = frappe.get_doc("Report", "Voucher-wise Balance") + res = voucher_wise.execute_script_report(filters=filters) + for x in res[1]: + doc = frappe.new_doc("Ledger Health") + doc.voucher_type = x.voucher_type + doc.voucher_no = x.voucher_no + doc.debit_credit_mismatch = True + doc.checked_on = run_date + doc.save() # General Ledger and Payment Ledger discrepancy if health_monitor_settings.general_and_payment_ledger_mismatch: +<<<<<<< HEAD gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") filters = { "company": "நுண்ணறி", @@ -2150,3 +2151,20 @@ def run_ledger_health_checks(): doc.checked_on = run_date doc.save() >>>>>>> a42482ce35 (refactor: control monitoring through settings page) +======= + for x in health_monitor_settings.companies: + filters = { + "company": x.company, + "period_start_date": period_start, + "period_end_date": period_end, + } + gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") + res = gl_pl_comparison.execute_script_report(filters=filters) + for x in res[1]: + doc = frappe.new_doc("Ledger Health") + doc.voucher_type = x.voucher_type + doc.voucher_no = x.voucher_no + doc.general_and_payment_ledger_mismatch = True + doc.checked_on = run_date + doc.save() +>>>>>>> 00eeacd06a (refactor: only run checks on specified companies) From 1af6b4256fd7e03581856813553c9d730553a4d4 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Mar 2024 10:14:29 +0530 Subject: [PATCH 41/72] chore: permission and UI changes (cherry picked from commit 1a43ed763b85ffbe500d53eac600737457e7fa17) --- .../ledger_health_monitor.json | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json index 4c1c8f80ac91..6e688333e3f5 100644 --- a/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json +++ b/erpnext/accounts/doctype/ledger_health_monitor/ledger_health_monitor.json @@ -56,10 +56,11 @@ "options": "Ledger Health Monitor Company" } ], + "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2024-03-27 10:07:28.601546", + "modified": "2024-03-27 10:14:16.511681", "modified_by": "Administrator", "module": "Accounts", "name": "Ledger Health Monitor", @@ -74,9 +75,30 @@ "role": "System Manager", "share": 1, "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "Accounts Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "Accounts User", + "share": 1, + "write": 1 } ], "sort_field": "modified", "sort_order": "DESC", - "states": [] + "states": [], + "track_changes": 1 } \ No newline at end of file From 0591f72e0143d86a474ddf5ee9356d50a928a8e9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Mar 2024 10:33:54 +0530 Subject: [PATCH 42/72] chore: schedule job to run daily (cherry picked from commit f96cf111ed0681254a1b9f4fe11d80e84368079d) --- erpnext/hooks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index fdaae5cc7e49..da4c1974247e 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -449,6 +449,7 @@ "erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status", "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email", "erpnext.accounts.utils.auto_create_exchange_rate_revaluation_daily", + "erpnext.accounts.utils.run_ledger_health_checks", ], "weekly": [ "erpnext.accounts.utils.auto_create_exchange_rate_revaluation_weekly", From 277717a2e0a75a85d6a70373938fd6ac748e749a Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Apr 2024 09:35:53 +0530 Subject: [PATCH 43/72] test: ledger monitoring function (cherry picked from commit 4776d660b535a19940b71b5d646d36792261fcb7) --- .../ledger_health/test_ledger_health.py | 106 +++++++++++++++++- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/ledger_health/test_ledger_health.py b/erpnext/accounts/doctype/ledger_health/test_ledger_health.py index ca647c99be92..daad855abf0b 100644 --- a/erpnext/accounts/doctype/ledger_health/test_ledger_health.py +++ b/erpnext/accounts/doctype/ledger_health/test_ledger_health.py @@ -1,9 +1,109 @@ # Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -# import frappe +import frappe +from frappe import qb from frappe.tests.utils import FrappeTestCase +from frappe.utils import nowdate +from erpnext.accounts.test.accounts_mixin import AccountsTestMixin +from erpnext.accounts.utils import run_ledger_health_checks -class TestLedgerHealth(FrappeTestCase): - pass + +class TestLedgerHealth(AccountsTestMixin, FrappeTestCase): + def setUp(self): + self.create_company() + self.create_customer() + self.configure_monitoring_tool() + self.clear_old_entries() + + def tearDown(self): + frappe.db.rollback() + + def configure_monitoring_tool(self): + monitor_settings = frappe.get_doc("Ledger Health Monitor") + monitor_settings.enable_health_monitor = True + monitor_settings.enable_for_last_x_days = 60 + monitor_settings.debit_credit_mismatch = True + monitor_settings.general_and_payment_ledger_mismatch = True + exists = [x for x in monitor_settings.companies if x.company == self.company] + if not exists: + monitor_settings.append("companies", {"company": self.company}) + monitor_settings.save() + + def clear_old_entries(self): + super(TestLedgerHealth, self).clear_old_entries() + lh = qb.DocType("Ledger Health") + qb.from_(lh).delete().run() + + def create_journal(self): + je = frappe.new_doc("Journal Entry") + je.company = self.company + je.voucher_type = "Journal Entry" + je.posting_date = nowdate() + je.append( + "accounts", + { + "account": self.debit_to, + "party_type": "Customer", + "party": self.customer, + "debit_in_account_currency": 10000, + }, + ) + je.append("accounts", {"account": self.income_account, "credit_in_account_currency": 10000}) + je.save().submit() + self.je = je + + def test_debit_credit_mismatch(self): + self.create_journal() + + # manually cause debit-credit mismatch + gle = frappe.db.get_all( + "GL Entry", filters={"voucher_no": self.je.name, "account": self.income_account} + )[0] + frappe.db.set_value("GL Entry", gle.name, "credit", 8000) + + run_ledger_health_checks() + expected = { + "voucher_type": self.je.doctype, + "voucher_no": self.je.name, + "debit_credit_mismatch": True, + "general_and_payment_ledger_mismatch": False, + } + actual = frappe.db.get_all( + "Ledger Health", + fields=[ + "voucher_type", + "voucher_no", + "debit_credit_mismatch", + "general_and_payment_ledger_mismatch", + ], + ) + self.assertEqual(len(actual), 1) + self.assertEqual(expected, actual[0]) + + def test_gl_and_pl_mismatch(self): + self.create_journal() + + # manually cause GL and PL discrepancy + ple = frappe.db.get_all("Payment Ledger Entry", filters={"voucher_no": self.je.name})[0] + frappe.db.set_value("Payment Ledger Entry", ple.name, "amount", 11000) + + run_ledger_health_checks() + expected = { + "voucher_type": self.je.doctype, + "voucher_no": self.je.name, + "debit_credit_mismatch": False, + "general_and_payment_ledger_mismatch": True, + } + actual = frappe.db.get_all( + "Ledger Health", + fields=[ + "voucher_type", + "voucher_no", + "debit_credit_mismatch", + "general_and_payment_ledger_mismatch", + ], + ) + self.assertEqual(len(actual), 1) + self.assertEqual(expected, actual[0]) From 98ad034b2130b538bdc44c606b989ecdaf3ae7f2 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Apr 2024 11:18:53 +0530 Subject: [PATCH 44/72] chore: make ledger health doctype read_only (cherry picked from commit dc79213bb372c0171f6f4d9bab92b91eb5d7314a) --- erpnext/accounts/doctype/ledger_health/ledger_health.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/ledger_health/ledger_health.json b/erpnext/accounts/doctype/ledger_health/ledger_health.json index e17f4e8f2d74..fb2da3d25648 100644 --- a/erpnext/accounts/doctype/ledger_health/ledger_health.json +++ b/erpnext/accounts/doctype/ledger_health/ledger_health.json @@ -40,9 +40,10 @@ "label": "General and Payment Ledger mismatch" } ], + "in_create": 1, "index_web_pages_for_search": 1, "links": [], - "modified": "2024-03-26 19:59:41.180161", + "modified": "2024-04-09 11:16:07.044484", "modified_by": "Administrator", "module": "Accounts", "name": "Ledger Health", @@ -62,6 +63,7 @@ "write": 1 } ], + "read_only": 1, "sort_field": "modified", "sort_order": "DESC", "states": [] From 5808feaccf606f4ddae69be98fff58371c55f975 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Apr 2024 17:35:15 +0530 Subject: [PATCH 45/72] chore: use super() instead of super(__class__, self) (cherry picked from commit 24d37d22a3d5bb52a5b7ee2e0157bc400c50b323) --- erpnext/accounts/doctype/ledger_health/test_ledger_health.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/ledger_health/test_ledger_health.py b/erpnext/accounts/doctype/ledger_health/test_ledger_health.py index daad855abf0b..d35b39d9ea12 100644 --- a/erpnext/accounts/doctype/ledger_health/test_ledger_health.py +++ b/erpnext/accounts/doctype/ledger_health/test_ledger_health.py @@ -32,7 +32,7 @@ def configure_monitoring_tool(self): monitor_settings.save() def clear_old_entries(self): - super(TestLedgerHealth, self).clear_old_entries() + super().clear_old_entries() lh = qb.DocType("Ledger Health") qb.from_(lh).delete().run() From 46c76b166d66c61a4265c99e70d35ec753d1dd23 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Apr 2024 19:59:09 +0530 Subject: [PATCH 46/72] chore: resolve conflicts --- erpnext/accounts/utils.py | 41 --------------------------------------- 1 file changed, 41 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index c7fd17c33df3..a32c25fbb709 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -2086,12 +2086,6 @@ def create_gain_loss_journal( journal_entry.save() journal_entry.submit() return journal_entry.name -<<<<<<< HEAD -======= - - -def get_party_types_from_account_type(account_type): - return frappe.db.get_all("Party Type", {"account_type": account_type}, pluck="name") def run_ledger_health_checks(): @@ -2118,40 +2112,6 @@ def run_ledger_health_checks(): # General Ledger and Payment Ledger discrepancy if health_monitor_settings.general_and_payment_ledger_mismatch: -<<<<<<< HEAD - gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") - filters = { - "company": "நுண்ணறி", - "period_start_date": period_start, - "period_end_date": period_end, - } - res = gl_pl_comparison.execute_script_report(filters=filters) - -<<<<<<< HEAD - # General Ledger and Payment Ledger discrepancy - gl_pl_comparison = frappe.get_doc("Report", "General and Payment Ledger Comparison") - # todo: company and dates should be configurable - filters = {"company": "நுண்ணறி", "period_start_date": period_start, "period_end_date": period_end} - res = gl_pl_comparison.execute_script_report(filters=filters) - - for x in res[1]: - doc = frappe.new_doc("Ledger Health") - doc.voucher_type = x.voucher_type - doc.voucher_no = x.voucher_no - doc.general_and_payment_ledger_mismatch = True - doc.checked_on = run_date - doc.save() ->>>>>>> 8c8d9be810 (refactor: barebones method to run checks) -======= - for x in res[1]: - doc = frappe.new_doc("Ledger Health") - doc.voucher_type = x.voucher_type - doc.voucher_no = x.voucher_no - doc.general_and_payment_ledger_mismatch = True - doc.checked_on = run_date - doc.save() ->>>>>>> a42482ce35 (refactor: control monitoring through settings page) -======= for x in health_monitor_settings.companies: filters = { "company": x.company, @@ -2167,4 +2127,3 @@ def run_ledger_health_checks(): doc.general_and_payment_ledger_mismatch = True doc.checked_on = run_date doc.save() ->>>>>>> 00eeacd06a (refactor: only run checks on specified companies) From 9745724d413d65ff533654a4a2a66d8ddae892a9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 10 Apr 2024 13:21:24 +0530 Subject: [PATCH 47/72] fix: ignore dimension validation for cancelled entries (cherry picked from commit 971c867f292802f14a7635d5ebbae45a60ec868d) --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 939d84109008..346fee81812a 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -135,6 +135,7 @@ def validate_dimensions_for_pl_and_bs(self): and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled + and not self.is_cancelled ): if not self.get(dimension.fieldname): frappe.throw( @@ -148,6 +149,7 @@ def validate_dimensions_for_pl_and_bs(self): and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled + and not self.is_cancelled ): if not self.get(dimension.fieldname): frappe.throw( From c28d19cf7fcd43eb503a65dfedaf8723f69bdabe Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:22:19 +0100 Subject: [PATCH 48/72] chore: switch to ruff for python formatting/linting (cherry picked from commit 8afb7790de8885182e6181b7ce21d25b6120dad8) (cherry picked from commit 9eeedd8515af05a64fdac0910cacdd7b5077b7c8) Signed-off-by: Akhil Narang --- .pre-commit-config.yaml | 26 ++++++---------------- pyproject.toml | 48 ++++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b95b32d7ddb9..1f670f2bec33 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -65,27 +65,15 @@ repos: .*/loan_write_off.js )$ - - repo: https://github.com/PyCQA/flake8 - rev: 5.0.4 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.0 hooks: - - id: flake8 - additional_dependencies: [ - 'flake8-bugbear', - ] - args: ['--config', '.github/helper/.flake8_strict'] - exclude: ".*setup.py$" + - id: ruff + name: "Run ruff linter and apply fixes" + args: ["--fix"] - - repo: https://github.com/adityahase/black - rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119 - hooks: - - id: black - additional_dependencies: ['click==8.0.4'] - - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - exclude: ".*setup.py$" + - id: ruff-format + name: "Format Python code" ci: diff --git a/pyproject.toml b/pyproject.toml index 7f28903f120b..af0fbffd9fff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,17 +32,41 @@ build-backend = "flit_core.buildapi" [tool.bench.dev-dependencies] hypothesis = "~=6.31.0" -[tool.black] -line-length = 99 - -[tool.isort] -line_length = 99 -multi_line_output = 3 -include_trailing_comma = true -force_grid_wrap = 0 -use_parentheses = true -ensure_newline_before_comments = true -indent = "\t" - [tool.bench.frappe-dependencies] frappe = ">=14.0.0,<15.0.0" + +[tool.ruff] +line-length = 110 +target-version = "py310" + +[tool.ruff.lint] +select = [ + "F", + "E", + "W", + "I", + "UP", + "B", + "RUF", +] +ignore = [ + "B017", # assertRaises(Exception) - should be more specific + "B018", # useless expression, not assigned to anything + "B023", # function doesn't bind loop variable - will have last iteration's value + "B904", # raise inside except without from + "E101", # indentation contains mixed spaces and tabs + "E402", # module level import not at top of file + "E501", # line too long + "E741", # ambiguous variable name + "F401", # "unused" imports + "F403", # can't detect undefined names from * import + "F405", # can't detect undefined names from * import + "F722", # syntax error in forward type annotation + "W191", # indentation contains tabs + "RUF001", # string contains ambiguous unicode character +] + +[tool.ruff.format] +quote-style = "double" +indent-style = "tab" +docstring-code-format = true From 4d34b1ead73baf4c5430a2ecbe44b9e8468d7626 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 27 Mar 2024 11:37:26 +0530 Subject: [PATCH 49/72] refactor(treewide): formatting and ruff fixes, + manually enabled F401 Signed-off-by: Akhil Narang --- erpnext/__init__.py | 14 +- erpnext/accounts/custom/address.py | 12 +- .../account_balance_timeline.py | 7 +- erpnext/accounts/deferred_revenue.py | 76 ++---- erpnext/accounts/doctype/account/account.py | 25 +- .../chart_of_accounts/chart_of_accounts.py | 17 +- .../chart_of_accounts/import_from_openerp.py | 30 ++- .../accounts/doctype/account/test_account.py | 24 +- .../account_closing_balance.py | 10 +- .../accounting_dimension.py | 31 +-- .../test_accounting_dimension_filter.py | 4 +- .../accounting_period/accounting_period.py | 5 +- .../test_accounting_period.py | 4 +- .../doctype/bank_account/test_bank_account.py | 4 +- .../doctype/bank_clearance/bank_clearance.py | 18 +- .../bank_reconciliation_tool.py | 20 +- .../bank_statement_import.py | 10 +- .../bank_transaction/auto_match_party.py | 14 +- .../bank_transaction/bank_transaction.py | 13 +- .../bank_transaction_upload.py | 4 +- .../bank_transaction/test_bank_transaction.py | 4 +- erpnext/accounts/doctype/budget/budget.py | 94 +++---- .../accounts/doctype/budget/test_budget.py | 60 ++--- .../chart_of_accounts_importer.py | 22 +- .../cheque_print_template.py | 92 +++---- .../doctype/cost_center/cost_center.py | 8 +- .../doctype/cost_center/test_cost_center.py | 1 - .../cost_center_allocation.py | 6 +- .../currency_exchange_settings.py | 9 +- .../exchange_rate_revaluation.py | 23 +- .../test_exchange_rate_revaluation.py | 23 +- .../doctype/fiscal_year/fiscal_year.py | 12 +- erpnext/accounts/doctype/gl_entry/gl_entry.py | 51 ++-- .../doctype/gl_entry/test_gl_entry.py | 8 +- .../invoice_discounting.py | 8 +- .../test_invoice_discounting.py | 22 +- .../item_tax_template/item_tax_template.py | 2 +- .../doctype/journal_entry/journal_entry.py | 132 +++++----- .../journal_entry/test_journal_entry.py | 19 +- .../doctype/ledger_merge/test_ledger_merge.py | 5 +- .../loyalty_program/loyalty_program.py | 10 +- .../loyalty_program/test_loyalty_program.py | 22 +- .../monthly_distribution.py | 4 +- .../test_opening_invoice_creation_tool.py | 12 +- .../accounts/doctype/party_link/party_link.py | 5 +- .../doctype/payment_entry/payment_entry.py | 150 ++++++------ .../payment_entry/test_payment_entry.py | 26 +- .../payment_ledger_entry.py | 12 +- .../test_payment_ledger_entry.py | 18 +- .../doctype/payment_order/payment_order.py | 4 +- .../payment_order/test_payment_order.py | 5 +- .../payment_reconciliation.py | 21 +- .../test_payment_reconciliation.py | 19 +- .../payment_request/payment_request.py | 27 +-- .../payment_request/test_payment_request.py | 4 +- .../payment_terms_template.py | 4 +- .../period_closing_voucher.py | 15 +- .../pos_closing_entry/pos_closing_entry.py | 12 +- .../doctype/pos_invoice/pos_invoice.py | 14 +- .../doctype/pos_invoice/test_pos_invoice.py | 32 +-- .../pos_invoice_merge_log.py | 40 ++- .../test_pos_invoice_merge_log.py | 18 +- .../doctype/pos_profile/pos_profile.py | 12 +- .../doctype/pos_profile/test_pos_profile.py | 14 +- .../doctype/pricing_rule/pricing_rule.py | 25 +- .../doctype/pricing_rule/test_pricing_rule.py | 7 +- .../accounts/doctype/pricing_rule/utils.py | 61 ++--- .../test_process_deferred_accounting.py | 2 +- .../process_payment_reconciliation.py | 33 ++- .../process_statement_of_accounts.py | 4 +- .../test_process_statement_of_accounts.py | 1 - .../promotional_scheme/promotional_scheme.py | 17 +- .../purchase_invoice/purchase_invoice.py | 91 ++++--- .../purchase_invoice/test_purchase_invoice.py | 64 ++--- .../purchase_taxes_and_charges_template.py | 2 +- .../repost_accounting_ledger.py | 10 +- .../test_repost_accounting_ledger.py | 1 - .../repost_payment_ledger.py | 4 +- .../doctype/sales_invoice/sales_invoice.py | 99 ++++---- .../sales_invoice/test_sales_invoice.py | 45 ++-- .../sales_taxes_and_charges_template.py | 8 +- .../doctype/share_transfer/share_transfer.py | 18 +- .../doctype/shipping_rule/shipping_rule.py | 17 +- .../shipping_rule/test_shipping_rule.py | 1 - .../doctype/subscription/subscription.py | 18 +- .../doctype/subscription/test_subscription.py | 13 +- .../subscription_plan/subscription_plan.py | 4 +- erpnext/accounts/doctype/tax_rule/tax_rule.py | 41 ++-- .../tax_withholding_category.py | 34 +-- .../test_tax_withholding_category.py | 10 +- .../test_unreconcile_payment.py | 10 +- .../unreconcile_payment.py | 6 +- erpnext/accounts/general_ledger.py | 26 +- erpnext/accounts/party.py | 54 ++--- .../report/account_balance/account_balance.py | 1 - .../accounts_payable/test_accounts_payable.py | 10 +- .../accounts_receivable.py | 46 ++-- .../test_accounts_receivable.py | 29 +-- .../accounts_receivable_summary.py | 8 +- .../test_accounts_receivable_summary.py | 2 - .../asset_depreciations_and_balances.py | 12 +- .../report/balance_sheet/balance_sheet.py | 1 - .../balance_sheet/test_balance_sheet.py | 6 +- .../bank_clearance_summary.py | 16 +- .../bank_reconciliation_statement.py | 9 +- .../billed_items_to_be_received.py | 8 +- .../budget_variance_report.py | 49 ++-- .../accounts/report/cash_flow/cash_flow.py | 24 +- .../report/cash_flow/custom_cash_flow.py | 31 +-- .../consolidated_financial_statement.py | 55 ++--- .../customer_ledger_summary.py | 53 ++-- .../deferred_revenue_and_expense.py | 10 +- .../test_deferred_revenue_and_expense.py | 4 - .../dimension_wise_accounts_balance_report.py | 10 +- .../accounts/report/financial_statements.py | 15 +- .../general_and_payment_ledger_comparison.py | 11 +- ...t_general_and_payment_ledger_comparison.py | 6 +- .../report/general_ledger/general_ledger.py | 50 ++-- .../general_ledger/test_general_ledger.py | 4 +- .../gross_and_net_profit_report.py | 8 +- .../report/gross_profit/gross_profit.py | 35 ++- .../report/gross_profit/test_gross_profit.py | 2 +- .../inactive_sales_items.py | 2 - .../item_wise_purchase_register.py | 16 +- .../item_wise_sales_register.py | 68 +++--- .../report/payment_ledger/payment_ledger.py | 2 +- .../payment_ledger/test_payment_ledger.py | 4 +- .../payment_period_based_on_invoice_date.py | 8 +- .../report/pos_register/pos_register.py | 20 +- .../profit_and_loss_statement.py | 4 +- .../purchase_register/purchase_register.py | 18 +- .../test_purchase_register.py | 10 +- .../sales_payment_summary.py | 34 +-- .../test_sales_payment_summary.py | 16 +- .../report/sales_register/sales_register.py | 9 +- .../report/share_balance/share_balance.py | 2 +- .../report/share_ledger/share_ledger.py | 10 +- .../accounts/report/tax_detail/tax_detail.py | 10 +- .../report/tax_detail/test_tax_detail.py | 21 +- .../tds_computation_summary.py | 14 +- .../tds_payable_monthly.py | 16 +- .../report/trial_balance/trial_balance.py | 14 +- .../trial_balance_for_party.py | 20 +- erpnext/accounts/report/utils.py | 8 +- .../voucher_wise_balance.py | 4 +- erpnext/accounts/test/test_reports.py | 3 +- erpnext/accounts/test/test_utils.py | 27 +-- erpnext/accounts/utils.py | 229 +++++++----------- erpnext/assets/dashboard_fixtures.py | 5 +- erpnext/assets/doctype/asset/asset.py | 102 ++++---- erpnext/assets/doctype/asset/depreciation.py | 41 +--- erpnext/assets/doctype/asset/test_asset.py | 32 +-- .../asset_capitalization.py | 66 +++-- .../test_asset_capitalization.py | 16 +- .../doctype/asset_category/asset_category.py | 4 +- .../asset_category/test_asset_category.py | 4 +- .../asset_maintenance/asset_maintenance.py | 4 +- .../test_asset_maintenance.py | 7 +- .../doctype/asset_movement/asset_movement.py | 24 +- .../asset_movement/test_asset_movement.py | 30 ++- .../doctype/asset_repair/asset_repair.py | 8 +- .../doctype/asset_repair/test_asset_repair.py | 8 +- .../asset_shift_allocation.py | 20 +- .../asset_shift_factor/asset_shift_factor.py | 4 +- .../asset_value_adjustment.py | 2 +- .../test_asset_value_adjustment.py | 8 +- erpnext/assets/doctype/location/location.py | 8 +- .../assets/doctype/location/test_location.py | 4 +- .../fixed_asset_register.py | 18 +- .../doctype/purchase_order/purchase_order.py | 30 +-- .../purchase_order/test_purchase_order.py | 38 ++- .../request_for_quotation.py | 21 +- .../test_request_for_quotation.py | 8 +- erpnext/buying/doctype/supplier/supplier.py | 5 +- .../supplier_quotation/supplier_quotation.py | 4 +- .../supplier_scorecard/supplier_scorecard.py | 8 +- .../supplier_scorecard_criteria.py | 12 +- .../supplier_scorecard_period.py | 14 +- .../test_procurement_tracker.py | 9 - .../purchase_order_analysis.py | 10 +- .../requested_items_to_order_and_receive.py | 8 +- .../subcontract_order_summary.py | 2 +- .../test_subcontracted_item_to_be_received.py | 4 +- ...tracted_raw_materials_to_be_transferred.py | 4 +- .../supplier_quotation_comparison.py | 12 +- erpnext/buying/utils.py | 14 +- erpnext/controllers/accounts_controller.py | 207 +++++++--------- erpnext/controllers/buying_controller.py | 52 ++-- erpnext/controllers/item_variant.py | 22 +- erpnext/controllers/print_settings.py | 2 +- erpnext/controllers/queries.py | 119 ++++----- .../controllers/sales_and_purchase_return.py | 39 ++- erpnext/controllers/selling_controller.py | 23 +- erpnext/controllers/status_updater.py | 85 +++---- erpnext/controllers/stock_controller.py | 55 ++--- .../controllers/subcontracting_controller.py | 51 ++-- erpnext/controllers/taxes_and_totals.py | 60 ++--- .../tests/test_accounts_controller.py | 29 +-- erpnext/controllers/tests/test_mapper.py | 1 - .../controllers/tests/test_qty_based_taxes.py | 2 +- erpnext/controllers/tests/test_queries.py | 5 +- .../tests/test_subcontracting_controller.py | 20 +- .../tests/test_transaction_base.py | 5 +- erpnext/controllers/trends.py | 60 +++-- .../controllers/website_list_for_contact.py | 4 +- .../crm/doctype/appointment/appointment.py | 8 +- .../appointment_booking_settings.py | 8 +- erpnext/crm/doctype/contract/contract.py | 6 +- erpnext/crm/doctype/lead/lead.py | 18 +- erpnext/crm/doctype/lead/test_lead.py | 6 +- .../linkedin_settings/linkedin_settings.py | 20 +- .../crm/doctype/opportunity/opportunity.py | 8 +- .../doctype/opportunity/test_opportunity.py | 20 +- erpnext/crm/doctype/prospect/test_prospect.py | 2 +- .../social_media_post/social_media_post.py | 2 +- .../twitter_settings/twitter_settings.py | 14 +- erpnext/crm/doctype/utils.py | 9 +- .../campaign_efficiency.py | 10 +- .../lost_opportunity/lost_opportunity.py | 16 +- .../opportunity_summary_by_sales_stage.py | 3 +- .../prospects_engaged_but_not_converted.py | 6 +- .../sales_pipeline_analytics.py | 6 +- erpnext/crm/utils.py | 4 +- erpnext/e_commerce/api.py | 1 - .../e_commerce_settings.py | 1 - .../doctype/item_review/item_review.py | 1 - .../doctype/item_review/test_item_review.py | 2 - .../doctype/website_item/test_website_item.py | 10 +- .../doctype/website_item/website_item.py | 26 +- .../website_item_tabbed_section.py | 1 - .../doctype/website_offer/website_offer.py | 1 - .../doctype/wishlist/test_wishlist.py | 21 +- .../e_commerce/doctype/wishlist/wishlist.py | 1 - .../doctype/wishlist_item/wishlist_item.py | 1 - erpnext/e_commerce/legacy_search.py | 4 +- .../e_commerce/product_data_engine/filters.py | 18 +- .../e_commerce/product_data_engine/query.py | 4 +- .../test_product_data_engine.py | 20 +- erpnext/e_commerce/redisearch_utils.py | 14 +- erpnext/e_commerce/shopping_cart/cart.py | 22 +- .../e_commerce/shopping_cart/product_info.py | 4 +- .../shopping_cart/test_shopping_cart.py | 12 +- erpnext/e_commerce/shopping_cart/utils.py | 5 +- erpnext/e_commerce/variant_selector/utils.py | 12 +- .../connectors/woocommerce_connection.py | 9 +- .../exotel_settings/exotel_settings.py | 2 +- .../doctype/gocardless_settings/__init__.py | 2 +- .../gocardless_settings.py | 13 +- .../doctype/mpesa_settings/mpesa_connector.py | 20 +- .../doctype/mpesa_settings/mpesa_settings.py | 14 +- .../mpesa_settings/test_mpesa_settings.py | 4 +- .../doctype/plaid_settings/plaid_settings.py | 12 +- .../quickbooks_migrator.py | 79 +++--- .../tally_migration/tally_migration.py | 20 +- .../taxjar_settings/taxjar_settings.py | 10 +- .../woocommerce_settings.py | 2 +- .../exotel_integration.py | 8 +- .../taxjar_integration.py | 12 +- erpnext/erpnext_integrations/utils.py | 6 +- erpnext/hooks.py | 16 +- .../top_10_pledged_loan_securities.py | 12 +- erpnext/loan_management/doctype/loan/loan.py | 1 - .../loan_management/doctype/loan/test_loan.py | 136 +++-------- .../loan_application/loan_application.py | 16 +- .../loan_balance_adjustment.py | 4 +- .../loan_disbursement/loan_disbursement.py | 13 +- .../test_loan_disbursement.py | 25 +- .../loan_interest_accrual.py | 30 +-- .../test_loan_interest_accrual.py | 8 +- .../doctype/loan_repayment/loan_repayment.py | 41 ++-- .../loan_security_pledge.py | 1 - .../loan_security_price.py | 1 - .../loan_security_shortfall.py | 7 +- .../loan_security_unpledge.py | 7 +- .../process_loan_interest_accrual.py | 1 - .../applicant_wise_loan_security_exposure.py | 12 +- .../loan_interest_report.py | 20 +- .../loan_security_status.py | 7 +- .../maintenance_schedule.py | 11 +- .../maintenance_visit/maintenance_visit.py | 8 +- .../doctype/blanket_order/blanket_order.py | 6 +- .../blanket_order/test_blanket_order.py | 4 +- erpnext/manufacturing/doctype/bom/bom.py | 51 ++-- erpnext/manufacturing/doctype/bom/test_bom.py | 25 +- .../doctype/bom_update_log/bom_update_log.py | 20 +- .../bom_update_log/bom_updation_utils.py | 24 +- .../bom_update_log/test_bom_update_log.py | 4 +- .../bom_update_tool/bom_update_tool.py | 8 +- .../doctype/job_card/job_card.py | 55 ++--- .../doctype/job_card/test_job_card.py | 3 - .../manufacturing_settings.py | 3 +- .../production_plan/production_plan.py | 64 +++-- .../production_plan/test_production_plan.py | 49 ++-- .../manufacturing/doctype/routing/routing.py | 6 +- .../doctype/work_order/test_work_order.py | 51 ++-- .../doctype/work_order/work_order.py | 58 ++--- .../doctype/workstation/workstation.py | 12 +- .../bom_stock_calculated.py | 4 +- .../bom_stock_report/bom_stock_report.py | 4 +- .../cost_of_poor_quality_report.py | 6 +- .../exponential_smoothing_forecasting.py | 5 +- .../process_loss_report.py | 9 +- .../production_analytics.py | 9 +- .../production_plan_summary.py | 16 +- .../production_planning_report.py | 15 +- erpnext/manufacturing/report/test_reports.py | 3 +- .../work_order_consumed_materials.py | 4 +- .../v10_0/item_barcode_childtable_migrate.py | 4 +- .../v10_0/set_currency_in_pricing_rule.py | 4 +- .../transfer_subscription_to_auto_repeat.py | 1 - ...ate_department_records_for_each_company.py | 21 +- .../v11_0/make_italian_localization_fields.py | 10 +- .../v11_0/merge_land_unit_with_location.py | 6 +- ...efaults_to_child_table_for_multicompany.py | 4 +- .../patches/v11_0/refactor_naming_series.py | 4 +- .../v11_0/rename_asset_adjustment_doctype.py | 4 +- erpnext/patches/v11_0/rename_bom_wo_fields.py | 4 +- .../rename_production_order_to_work_order.py | 8 +- .../rename_supplier_type_to_supplier_group.py | 6 +- .../v11_0/set_department_for_doctypes.py | 1 - ...pdate_field_and_value_in_workflow_state.py | 1 - .../update_allow_transfer_for_manufacture.py | 6 +- ...e_backflush_subcontract_rm_based_on_bom.py | 4 +- .../v11_0/update_department_lft_rgt.py | 6 +- .../v11_0/update_sales_partner_type.py | 2 +- .../patches/v11_0/update_total_qty_field.py | 20 +- .../patches/v11_1/make_job_card_time_logs.py | 8 +- .../move_customer_lead_to_dynamic_column.py | 8 +- .../v11_1/set_missing_opportunity_from.py | 5 +- ...default_buying_selling_terms_in_company.py | 4 +- ...counting_dimensions_in_missing_doctypes.py | 3 - .../create_irs_1099_field_united_states.py | 1 - .../v12_0/fix_quotation_expired_status.py | 8 +- .../patches/v12_0/make_item_manufacturer.py | 4 +- .../move_bank_account_swift_number_to_bank.py | 2 +- ...e_credit_limit_to_customer_credit_limit.py | 10 +- .../move_item_tax_to_item_tax_template.py | 20 +- ...arget_distribution_from_parent_to_child.py | 4 +- .../patches/v12_0/purchase_receipt_status.py | 6 +- .../rename_bank_reconciliation_fields.py | 12 +- ...ock_ledger_entries_for_target_warehouse.py | 18 +- ...anket_order_in_sales_and_purchase_order.py | 9 +- ...eferred_accounting_in_accounts_settings.py | 4 +- ...qty_field_in_sales_order_for_work_order.py | 1 - ...t_purchase_receipt_delivery_note_detail.py | 12 +- erpnext/patches/v12_0/set_quotation_status.py | 1 - erpnext/patches/v12_0/set_task_status.py | 2 +- .../patches/v12_0/stock_entry_enhancements.py | 1 - erpnext/patches/v12_0/update_bom_in_so_mr.py | 8 +- .../v12_0/update_is_cancelled_field.py | 12 +- ...r_fields_in_acc_dimension_custom_fields.py | 7 +- .../v12_0/update_pricing_rule_fields.py | 23 +- .../v13_0/add_bin_unique_constraint.py | 1 - .../patches/v13_0/add_cost_center_in_loans.py | 4 +- .../add_missing_fg_item_for_stock_entry.py | 8 +- .../patches/v13_0/add_po_to_global_search.py | 4 +- .../v13_0/agriculture_deprecation_warning.py | 1 - ...nge_default_item_manufacturer_fieldtype.py | 1 - .../convert_qi_parameter_to_link_field.py | 4 +- ...ebsite_item_in_item_card_group_template.py | 5 +- ...py_custom_field_filters_to_website_item.py | 8 +- .../create_accounting_dimensions_in_orders.py | 4 +- ...e_accounting_dimensions_in_pos_doctypes.py | 2 - .../v13_0/create_uae_pos_invoice_fields.py | 4 +- .../custom_fields_for_taxjar_integration.py | 4 +- .../delete_bank_reconciliation_detail.py | 2 - .../v13_0/enable_provisional_accounting.py | 4 +- .../fix_additional_cost_in_mfg_stock_entry.py | 4 +- erpnext/patches/v13_0/fix_invoice_statuses.py | 2 +- .../v13_0/healthcare_deprecation_warning.py | 1 - .../v13_0/hospitality_deprecation_warning.py | 1 - .../v13_0/item_naming_series_not_mandatory.py | 1 - .../v13_0/move_branch_code_to_bank_account.py | 5 +- .../v13_0/non_profit_deprecation_warning.py | 1 - .../v13_0/rename_issue_doctype_fields.py | 6 +- .../patches/v13_0/requeue_failed_reposts.py | 1 - .../set_per_billed_in_return_delivery_note.py | 6 +- .../v13_0/set_work_order_qty_in_so_from_mr.py | 4 +- .../v13_0/shopify_deprecation_warning.py | 1 - .../v13_0/shopping_cart_to_ecommerce.py | 2 - .../v13_0/trim_whitespace_from_serial_nos.py | 4 +- .../v13_0/update_accounts_in_loan_docs.py | 4 +- .../update_actual_start_and_end_date_in_wo.py | 2 +- .../v13_0/update_disbursement_account.py | 1 - .../patches/v13_0/update_job_card_status.py | 1 - ...ate_maintenance_schedule_field_in_visit.py | 4 +- erpnext/patches/v13_0/update_old_loans.py | 5 +- .../v13_0/update_reserved_qty_closed_wo.py | 1 - .../v13_0/update_sane_transfer_against.py | 4 +- .../v13_0/update_schedule_type_in_loans.py | 6 +- .../patches/v13_0/update_sla_enhancements.py | 10 +- erpnext/patches/v13_0/update_subscription.py | 1 - .../patches/v13_0/update_timesheet_changes.py | 8 +- .../v13_0/wipe_serial_no_field_for_0_qty.py | 5 +- .../change_is_subcontracted_fieldtype.py | 12 +- ...ted_value_to_is_old_subcontracting_flow.py | 4 +- ...correct_asset_value_if_je_with_workflow.py | 8 +- ...g_dimensions_in_subcontracting_doctypes.py | 2 - erpnext/patches/v14_0/crm_ux_cleanup.py | 7 +- .../v14_0/delete_agriculture_doctypes.py | 4 +- .../v14_0/delete_education_doctypes.py | 8 +- .../v14_0/delete_healthcare_doctypes.py | 8 +- erpnext/patches/v14_0/delete_hub_doctypes.py | 1 - .../v14_0/delete_non_profit_doctypes.py | 4 +- .../patches/v14_0/fix_crm_no_of_employees.py | 6 +- .../v14_0/migrate_cost_center_allocations.py | 4 +- .../v14_0/migrate_gl_to_payment_ledger.py | 3 +- .../v14_0/remove_hr_and_payroll_modules.py | 8 +- ...ate_asset_value_for_manual_depr_entries.py | 10 +- .../patches/v14_0/update_closing_balances.py | 1 - .../v14_0/update_flag_for_return_invoices.py | 4 +- .../v14_0/update_partial_tds_fields.py | 24 +- erpnext/portal/doctype/homepage/homepage.py | 1 - erpnext/projects/doctype/project/project.py | 27 +-- .../projects/doctype/project/test_project.py | 11 +- .../project_template/test_project_template.py | 4 +- .../doctype/project_update/project_update.py | 13 +- erpnext/projects/doctype/task/task.py | 17 +- erpnext/projects/doctype/task/test_task.py | 4 +- .../doctype/timesheet/test_timesheet.py | 10 +- .../projects/doctype/timesheet/timesheet.py | 28 +-- erpnext/projects/report/billing_summary.py | 4 +- .../test_delayed_tasks_summary.py | 4 +- erpnext/projects/utils.py | 13 +- .../quality_procedure/quality_procedure.py | 15 +- .../doctype/quality_review/quality_review.py | 4 +- erpnext/regional/address_template/setup.py | 5 +- .../test_regional_address_template.py | 2 +- .../import_supplier_invoice.py | 9 +- erpnext/regional/italy/setup.py | 3 +- erpnext/regional/italy/utils.py | 14 +- .../fichier_des_ecritures_comptables_[fec].py | 22 +- erpnext/regional/report/irs_1099/irs_1099.py | 8 +- .../report/uae_vat_201/uae_vat_201.py | 48 ++-- .../vat_audit_report/vat_audit_report.py | 30 +-- erpnext/regional/saudi_arabia/setup.py | 3 +- .../operations/setup_ksa_vat_setting.py | 2 +- .../regional/united_arab_emirates/utils.py | 11 +- erpnext/regional/united_states/setup.py | 4 +- .../united_states/test_united_states.py | 2 - erpnext/selling/doctype/customer/customer.py | 56 ++--- .../selling/doctype/customer/test_customer.py | 9 +- .../installation_note/installation_note.py | 2 +- .../doctype/product_bundle/product_bundle.py | 6 +- .../selling/doctype/quotation/quotation.py | 18 +- .../doctype/quotation/test_quotation.py | 12 +- .../doctype/sales_order/sales_order.py | 68 +++--- .../doctype/sales_order/test_sales_order.py | 97 +++----- .../page/point_of_sale/point_of_sale.py | 19 +- .../selling/page/sales_funnel/sales_funnel.py | 4 +- .../address_and_contacts.py | 6 +- .../customer_acquisition_and_loyalty.py | 15 +- .../customer_credit_balance.py | 1 - .../customer_wise_item_price.py | 11 +- .../inactive_customers/inactive_customers.py | 18 +- .../item_wise_sales_history.py | 10 +- .../report/lost_quotations/lost_quotations.py | 4 +- .../payment_terms_status_for_sales_order.py | 12 +- .../pending_so_items_for_purchase_request.py | 8 +- .../quotation_trends/quotation_trends.py | 4 +- .../report/sales_analytics/sales_analytics.py | 49 ++-- .../sales_order_analysis.py | 8 +- .../sales_partner_commission_summary.py | 16 +- .../item_group_wise_sales_target_variance.py | 12 +- ...ner_target_variance_based_on_item_group.py | 2 - .../sales_partner_transaction_summary.py | 17 +- .../sales_person_commission_summary.py | 21 +- .../sales_person_wise_transaction_summary.py | 29 +-- ...ory_target_variance_based_on_item_group.py | 2 - .../territory_wise_sales.py | 28 +-- erpnext/setup/demo.py | 3 +- .../authorization_control.py | 51 ++-- .../authorization_rule/authorization_rule.py | 4 +- erpnext/setup/doctype/company/company.py | 80 +++--- .../currency_exchange/currency_exchange.py | 2 +- .../test_currency_exchange.py | 3 +- .../doctype/customer_group/customer_group.py | 2 +- .../setup/doctype/department/department.py | 8 +- .../doctype/email_digest/email_digest.py | 71 ++---- erpnext/setup/doctype/employee/employee.py | 21 +- .../doctype/holiday_list/holiday_list.py | 4 +- .../doctype/holiday_list/test_holiday_list.py | 4 +- erpnext/setup/doctype/incoterm/incoterm.py | 2 +- .../setup/doctype/item_group/item_group.py | 4 +- .../doctype/item_group/test_item_group.py | 19 +- .../setup/doctype/party_type/party_type.py | 8 +- .../doctype/sales_partner/sales_partner.py | 2 +- .../doctype/sales_person/sales_person.py | 3 +- .../terms_and_conditions.py | 7 +- erpnext/setup/doctype/territory/territory.py | 2 +- .../test_transaction_deletion_record.py | 6 +- .../transaction_deletion_record.py | 36 ++- erpnext/setup/install.py | 3 +- .../setup_wizard/operations/defaults_setup.py | 4 +- .../operations/install_fixtures.py | 8 +- .../setup_wizard/operations/taxes_setup.py | 19 +- erpnext/setup/utils.py | 8 +- erpnext/startup/boot.py | 12 +- erpnext/startup/leaderboard.py | 6 +- erpnext/stock/__init__.py | 6 +- .../warehouse_wise_stock_value.py | 4 +- erpnext/stock/doctype/batch/batch.py | 8 +- erpnext/stock/doctype/batch/test_batch.py | 12 +- erpnext/stock/doctype/bin/bin.py | 12 +- erpnext/stock/doctype/bin/test_bin.py | 2 +- .../closing_stock_balance.py | 2 +- .../doctype/delivery_note/delivery_note.py | 33 ++- .../delivery_note/test_delivery_note.py | 42 ++-- .../doctype/delivery_trip/delivery_trip.py | 19 +- .../delivery_trip/test_delivery_trip.py | 1 - .../inventory_dimension.py | 4 +- .../test_inventory_dimension.py | 61 +++-- erpnext/stock/doctype/item/item.py | 90 +++---- erpnext/stock/doctype/item/test_item.py | 19 +- .../item_alternative/item_alternative.py | 12 +- .../item_alternative/test_item_alternative.py | 12 +- .../doctype/item_attribute/item_attribute.py | 4 +- .../item_manufacturer/item_manufacturer.py | 4 +- .../stock/doctype/item_price/item_price.py | 3 +- .../item_variant_settings.py | 5 +- .../landed_cost_voucher.py | 23 +- .../test_landed_cost_voucher.py | 20 +- .../material_request/material_request.py | 47 ++-- .../material_request/test_material_request.py | 10 +- .../stock/doctype/packed_item/packed_item.py | 8 +- .../doctype/packed_item/test_packed_item.py | 14 +- .../doctype/packing_slip/packing_slip.py | 13 +- .../doctype/packing_slip/test_packing_slip.py | 1 - erpnext/stock/doctype/pick_list/pick_list.py | 45 ++-- .../stock/doctype/pick_list/test_pick_list.py | 16 +- .../purchase_receipt/purchase_receipt.py | 59 ++--- .../purchase_receipt/test_purchase_receipt.py | 50 ++-- .../doctype/putaway_rule/putaway_rule.py | 30 +-- .../doctype/putaway_rule/test_putaway_rule.py | 60 ++--- .../quality_inspection/quality_inspection.py | 52 ++-- .../test_quality_inspection.py | 4 +- .../quick_stock_balance.py | 8 +- .../repost_item_valuation.py | 7 +- .../test_repost_item_valuation.py | 1 - erpnext/stock/doctype/serial_no/serial_no.py | 90 +++---- .../stock/doctype/serial_no/test_serial_no.py | 10 +- .../stock/doctype/shipment/test_shipment.py | 12 +- .../stock/doctype/stock_entry/stock_entry.py | 164 +++++++------ .../doctype/stock_entry/stock_entry_utils.py | 20 +- .../doctype/stock_entry/test_stock_entry.py | 66 ++--- .../stock_ledger_entry/stock_ledger_entry.py | 14 +- .../test_stock_ledger_entry.py | 106 +++----- .../stock_reconciliation.py | 53 ++-- .../test_stock_reconciliation.py | 26 +- .../doctype/stock_settings/stock_settings.py | 6 +- .../stock_settings/test_stock_settings.py | 1 - .../stock/doctype/warehouse/test_warehouse.py | 3 +- erpnext/stock/doctype/warehouse/warehouse.py | 4 +- erpnext/stock/get_item_details.py | 93 +++---- erpnext/stock/reorder_item.py | 21 +- .../batch_item_expiry_status.py | 22 +- .../batch_wise_balance_history.py | 32 +-- .../cogs_by_item_group/cogs_by_item_group.py | 20 +- .../delayed_item_report.py | 2 +- .../delayed_order_report.py | 2 +- ...eue_vs_qty_after_transaction_comparison.py | 5 +- ...incorrect_balance_qty_after_transaction.py | 2 +- .../incorrect_serial_no_valuation.py | 6 +- .../incorrect_stock_value_report.py | 8 +- .../stock/report/item_prices/item_prices.py | 4 +- .../itemwise_recommended_reorder_level.py | 4 +- .../stock/report/stock_ageing/stock_ageing.py | 53 ++-- .../report/stock_analytics/stock_analytics.py | 23 +- .../stock_analytics/test_stock_analytics.py | 4 +- .../stock_and_account_value_comparison.py | 6 +- .../report/stock_balance/stock_balance.py | 39 +-- .../stock_balance/test_stock_balance.py | 10 +- .../stock/report/stock_ledger/stock_ledger.py | 28 +-- .../stock_ledger_variance.py | 6 +- .../stock_projected_qty.py | 8 +- .../supplier_wise_sales_analytics.py | 31 ++- erpnext/stock/report/test_reports.py | 3 +- .../total_stock_summary.py | 7 +- ...rehouse_wise_item_balance_age_and_value.py | 4 +- .../warehouse_wise_stock_balance.py | 14 +- erpnext/stock/stock_balance.py | 9 +- erpnext/stock/stock_ledger.py | 116 ++++----- erpnext/stock/tests/test_get_item_details.py | 4 - erpnext/stock/tests/test_utils.py | 4 +- erpnext/stock/tests/test_valuation.py | 9 +- erpnext/stock/utils.py | 34 +-- erpnext/stock/valuation.py | 33 +-- .../subcontracting_order.py | 15 +- .../test_subcontracting_order.py | 2 +- .../subcontracting_receipt.py | 30 ++- .../test_subcontracting_receipt.py | 26 +- erpnext/support/doctype/issue/issue.py | 9 +- erpnext/support/doctype/issue/test_issue.py | 58 ++--- .../service_level_agreement.py | 39 ++- .../test_service_level_agreement.py | 32 +-- .../report/issue_analytics/issue_analytics.py | 20 +- .../report/issue_summary/issue_summary.py | 44 ++-- .../support_hour_distribution.py | 4 +- .../telephony/doctype/call_log/call_log.py | 10 +- .../incoming_call_settings.py | 3 +- erpnext/templates/pages/home.py | 4 +- .../pages/integrations/gocardless_checkout.py | 6 +- .../integrations/gocardless_confirmation.py | 5 +- erpnext/templates/pages/order.py | 4 +- erpnext/templates/pages/product_search.py | 11 +- erpnext/templates/pages/projects.py | 8 +- erpnext/templates/pages/rfq.py | 10 +- erpnext/templates/pages/search_help.py | 4 +- erpnext/tests/test_init.py | 27 +-- erpnext/tests/test_webform.py | 14 +- erpnext/tests/utils.py | 12 +- erpnext/utilities/activation.py | 4 +- erpnext/utilities/bulk_transaction.py | 12 +- erpnext/utilities/doctype/video/video.py | 4 +- erpnext/utilities/naming.py | 26 +- erpnext/utilities/product.py | 12 +- erpnext/utilities/transaction_base.py | 4 +- erpnext/www/all-products/index.py | 4 +- 618 files changed, 4188 insertions(+), 6384 deletions(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 497416b12aba..2940c9f4c0ec 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -36,10 +36,8 @@ def get_default_cost_center(company): if not frappe.flags.company_cost_center: frappe.flags.company_cost_center = {} - if not company in frappe.flags.company_cost_center: - frappe.flags.company_cost_center[company] = frappe.get_cached_value( - "Company", company, "cost_center" - ) + if company not in frappe.flags.company_cost_center: + frappe.flags.company_cost_center[company] = frappe.get_cached_value("Company", company, "cost_center") return frappe.flags.company_cost_center[company] @@ -47,7 +45,7 @@ def get_company_currency(company): """Returns the default company currency""" if not frappe.flags.company_currency: frappe.flags.company_currency = {} - if not company in frappe.flags.company_currency: + if company not in frappe.flags.company_currency: frappe.flags.company_currency[company] = frappe.db.get_value( "Company", company, "default_currency", cache=True ) @@ -81,7 +79,7 @@ def is_perpetual_inventory_enabled(company): if not hasattr(frappe.local, "enable_perpetual_inventory"): frappe.local.enable_perpetual_inventory = {} - if not company in frappe.local.enable_perpetual_inventory: + if company not in frappe.local.enable_perpetual_inventory: frappe.local.enable_perpetual_inventory[company] = ( frappe.get_cached_value("Company", company, "enable_perpetual_inventory") or 0 ) @@ -96,7 +94,7 @@ def get_default_finance_book(company=None): if not hasattr(frappe.local, "default_finance_book"): frappe.local.default_finance_book = {} - if not company in frappe.local.default_finance_book: + if company not in frappe.local.default_finance_book: frappe.local.default_finance_book[company] = frappe.get_cached_value( "Company", company, "default_finance_book" ) @@ -108,7 +106,7 @@ def get_party_account_type(party_type): if not hasattr(frappe.local, "party_account_types"): frappe.local.party_account_types = {} - if not party_type in frappe.local.party_account_types: + if party_type not in frappe.local.party_account_types: frappe.local.party_account_types[party_type] = ( frappe.db.get_value("Party Type", party_type, "account_type") or "" ) diff --git a/erpnext/accounts/custom/address.py b/erpnext/accounts/custom/address.py index 775a81fd25f3..ef57a6325069 100644 --- a/erpnext/accounts/custom/address.py +++ b/erpnext/accounts/custom/address.py @@ -11,14 +11,14 @@ class ERPNextAddress(Address): def validate(self): self.validate_reference() self.update_compnay_address() - super(ERPNextAddress, self).validate() + super().validate() def link_address(self): """Link address based on owner""" if self.is_your_company_address: return - return super(ERPNextAddress, self).link_address() + return super().link_address() def update_compnay_address(self): for link in self.get("links"): @@ -26,11 +26,11 @@ def update_compnay_address(self): self.is_your_company_address = 1 def validate_reference(self): - if self.is_your_company_address and not [ - row for row in self.links if row.link_doctype == "Company" - ]: + if self.is_your_company_address and not [row for row in self.links if row.link_doctype == "Company"]: frappe.throw( - _("Address needs to be linked to a Company. Please add a row for Company in the Links table."), + _( + "Address needs to be linked to a Company. Please add a row for Company in the Links table." + ), title=_("Company Not Linked"), ) diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py index fefec0ee7b41..7e06c5b8c83d 100644 --- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py +++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py @@ -37,7 +37,7 @@ def get( filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json) account = filters.get("account") - company = filters.get("company") + filters.get("company") if not account and chart_name: frappe.throw( @@ -83,7 +83,6 @@ def build_result(account, dates, gl_entries): # get balances in debit for entry in gl_entries: - # entry date is after the current pointer, so move the pointer forward while getdate(entry.posting_date) > result[date_index][0]: date_index += 1 @@ -133,8 +132,6 @@ def get_dates_from_timegrain(from_date, to_date, timegrain): dates = [get_period_ending(from_date, timegrain)] while getdate(dates[-1]) < getdate(to_date): - date = get_period_ending( - add_to_date(dates[-1], years=years, months=months, days=days), timegrain - ) + date = get_period_ending(add_to_date(dates[-1], years=years, months=months, days=days), timegrain) dates.append(date) return dates diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index d0940c7df213..9ffdf186f027 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -24,14 +24,10 @@ def validate_service_stop_date(doc): """Validates service_stop_date for Purchase Invoice and Sales Invoice""" - enable_check = ( - "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense" - ) + enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense" old_stop_dates = {} - old_doc = frappe.db.get_all( - "{0} Item".format(doc.doctype), {"parent": doc.name}, ["name", "service_stop_date"] - ) + old_doc = frappe.db.get_all(f"{doc.doctype} Item", {"parent": doc.name}, ["name", "service_stop_date"]) for d in old_doc: old_stop_dates[d.name] = d.service_stop_date or "" @@ -62,16 +58,14 @@ def build_conditions(process_type, account, company): ) if account: - conditions += "AND %s='%s'" % (deferred_account, account) + conditions += f"AND {deferred_account}='{account}'" elif company: conditions += f"AND p.company = {frappe.db.escape(company)}" return conditions -def convert_deferred_expense_to_expense( - deferred_process, start_date=None, end_date=None, conditions="" -): +def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=""): # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM if not start_date: @@ -81,16 +75,14 @@ def convert_deferred_expense_to_expense( # check for the purchase invoice for which GL entries has to be done invoices = frappe.db.sql_list( - """ + f""" select distinct item.parent from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p where item.service_start_date<=%s and item.service_end_date>=%s and item.enable_deferred_expense = 1 and item.parent=p.name and item.docstatus = 1 and ifnull(item.amount, 0) > 0 - {0} - """.format( - conditions - ), + {conditions} + """, (end_date, start_date), ) # nosec @@ -103,9 +95,7 @@ def convert_deferred_expense_to_expense( send_mail(deferred_process) -def convert_deferred_revenue_to_income( - deferred_process, start_date=None, end_date=None, conditions="" -): +def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=""): # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM if not start_date: @@ -115,16 +105,14 @@ def convert_deferred_revenue_to_income( # check for the sales invoice for which GL entries has to be done invoices = frappe.db.sql_list( - """ + f""" select distinct item.parent from `tabSales Invoice Item` item, `tabSales Invoice` p where item.service_start_date<=%s and item.service_end_date>=%s and item.enable_deferred_revenue = 1 and item.parent=p.name and item.docstatus = 1 and ifnull(item.amount, 0) > 0 - {0} - """.format( - conditions - ), + {conditions} + """, (end_date, start_date), ) # nosec @@ -243,9 +231,7 @@ def calculate_monthly_amount( already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount( doc, item ) - base_amount = flt( - item.base_net_amount - already_booked_amount, item.precision("base_net_amount") - ) + base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount")) if account_currency == doc.company_currency: amount = base_amount else: @@ -265,17 +251,13 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a if account_currency == doc.company_currency: amount = base_amount else: - amount = flt( - item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount") - ) + amount = flt(item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount")) else: already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount( doc, item ) - base_amount = flt( - item.base_net_amount - already_booked_amount, item.precision("base_net_amount") - ) + base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount")) if account_currency == doc.company_currency: amount = base_amount else: @@ -296,26 +278,22 @@ def get_already_booked_amount(doc, item): gl_entries_details = frappe.db.sql( """ - select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no + select sum({}) as total_credit, sum({}) as total_credit_in_account_currency, voucher_detail_no from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s and is_cancelled = 0 group by voucher_detail_no - """.format( - total_credit_debit, total_credit_debit_currency - ), + """.format(total_credit_debit, total_credit_debit_currency), (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True, ) journal_entry_details = frappe.db.sql( """ - SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no + SELECT sum(c.{}) as total_credit, sum(c.{}) as total_credit_in_account_currency, reference_detail_no FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s and p.docstatus < 2 group by reference_detail_no - """.format( - total_credit_debit, total_credit_debit_currency - ), + """.format(total_credit_debit, total_credit_debit_currency), (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True, ) @@ -337,9 +315,7 @@ def get_already_booked_amount(doc, item): def book_deferred_income_or_expense(doc, deferred_process, posting_date=None): - enable_check = ( - "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense" - ) + enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense" accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") @@ -440,9 +416,7 @@ def _book_deferred_revenue_or_expense( via_journal_entry = cint( frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry") ) - submit_journal_entry = cint( - frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries") - ) + submit_journal_entry = cint(frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries")) book_deferred_entries_based_on = frappe.db.get_singles_value( "Accounts Settings", "book_deferred_entries_based_on" ) @@ -462,9 +436,7 @@ def process_deferred_accounting(posting_date=None): posting_date = today() if not cint( - frappe.db.get_singles_value( - "Accounts Settings", "automatically_process_deferred_accounting_entry" - ) + frappe.db.get_singles_value("Accounts Settings", "automatically_process_deferred_accounting_entry") ): return @@ -587,16 +559,13 @@ def book_revenue_via_journal_entry( deferred_process=None, submit="No", ): - if amount == 0: return journal_entry = frappe.new_doc("Journal Entry") journal_entry.posting_date = posting_date journal_entry.company = doc.company - journal_entry.voucher_type = ( - "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense" - ) + journal_entry.voucher_type = "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense" journal_entry.process_deferred_accounting = deferred_process debit_entry = { @@ -645,7 +614,6 @@ def book_revenue_via_journal_entry( def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr): - if doctype == "Sales Invoice": credit_account, debit_account = frappe.db.get_value( "Sales Invoice Item", diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 283e9d2f4efe..8cbaef431806 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -29,7 +29,7 @@ def on_update(self): if frappe.local.flags.ignore_update_nsm: return else: - super(Account, self).on_update() + super().on_update() def onload(self): frozen_accounts_modifier = frappe.db.get_value( @@ -87,9 +87,7 @@ def validate_parent(self): def set_root_and_report_type(self): if self.parent_account: - par = frappe.db.get_value( - "Account", self.parent_account, ["report_type", "root_type"], as_dict=1 - ) + par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1) if par.report_type: self.report_type = par.report_type @@ -144,9 +142,7 @@ def validate_root_details(self): def validate_root_company_and_sync_account_to_children(self): # ignore validation while creating new compnay or while syncing to child companies - if ( - frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation - ): + if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation: return ancestors = get_root_company(self.company) if ancestors: @@ -341,7 +337,7 @@ def on_trash(self): if self.check_gle_exists(): throw(_("Account with existing transaction can not be deleted")) - super(Account, self).on_trash(True) + super().on_trash(True) @frappe.whitelist() @@ -349,9 +345,8 @@ def on_trash(self): def get_parent_account(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql( """select name from tabAccount - where is_group = 1 and docstatus != 2 and company = %s - and %s like %s order by name limit %s offset %s""" - % ("%s", searchfield, "%s", "%s", "%s"), + where is_group = 1 and docstatus != 2 and company = {} + and {} like {} order by name limit {} offset {}""".format("%s", searchfield, "%s", "%s", "%s"), (filters["company"], "%%%s%%" % txt, page_len, start), as_list=1, ) @@ -409,9 +404,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda if not account: return - old_acc_name, old_acc_number = frappe.db.get_value( - "Account", name, ["account_name", "account_number"] - ) + old_acc_name, old_acc_number = frappe.db.get_value("Account", name, ["account_name", "account_number"]) # check if account exists in parent company ancestors = get_ancestors_of("Company", account.company) @@ -519,7 +512,5 @@ def sync_update_account_number_in_child( if old_acc_number: filters["account_number"] = old_acc_number - for d in frappe.db.get_values( - "Account", filters=filters, fieldname=["company", "name"], as_dict=True - ): + for d in frappe.db.get_values("Account", filters=filters, fieldname=["company", "name"], as_dict=True): update_account_number(d["name"], account_name, account_number, from_descendant=True) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index 216135a39753..ea5db9dccb76 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -31,7 +31,6 @@ def _import_accounts(children, parent, root_type, root_account=False): "tax_rate", "account_currency", ]: - account_number = cstr(child.get("account_number")).strip() account_name, account_name_in_db = add_suffix_if_duplicate( account_name, account_number, accounts @@ -39,7 +38,9 @@ def _import_accounts(children, parent, root_type, root_account=False): is_group = identify_is_group(child) report_type = ( - "Balance Sheet" if root_type in ["Asset", "Liability", "Equity"] else "Profit and Loss" + "Balance Sheet" + if root_type in ["Asset", "Liability", "Equity"] + else "Profit and Loss" ) account = frappe.get_doc( @@ -141,7 +142,7 @@ def get_chart(chart_template, existing_company=None): for fname in os.listdir(path): fname = frappe.as_unicode(fname) if fname.endswith(".json"): - with open(os.path.join(path, fname), "r") as f: + with open(os.path.join(path, fname)) as f: chart = f.read() if chart and json.loads(chart).get("name") == chart_template: return json.loads(chart).get("tree") @@ -173,7 +174,7 @@ def _get_chart_name(content): for fname in os.listdir(path): fname = frappe.as_unicode(fname) if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"): - with open(os.path.join(path, fname), "r") as f: + with open(os.path.join(path, fname)) as f: _get_chart_name(f.read()) # if more than one charts, returned then add the standard @@ -247,7 +248,13 @@ def validate_bank_account(coa, bank_account): def _get_account_names(account_master): for account_name, child in account_master.items(): - if account_name not in ["account_number", "account_type", "root_type", "is_group", "tax_rate"]: + if account_name not in [ + "account_number", + "account_type", + "root_type", + "is_group", + "tax_rate", + ]: accounts.append(account_name) _get_account_names(child) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py index 3f25ada8b353..928d51d98980 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py @@ -26,7 +26,7 @@ def go(): default_account_types = get_default_account_types() country_dirs = [] - for basepath, folders, files in os.walk(path): + for basepath, _folders, _files in os.walk(path): basename = os.path.basename(basepath) if basename.startswith("l10n_"): country_dirs.append(basename) @@ -35,9 +35,7 @@ def go(): accounts, charts = {}, {} country_path = os.path.join(path, country_dir) manifest = ast.literal_eval(open(os.path.join(country_path, "__openerp__.py")).read()) - data_files = ( - manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", []) - ) + data_files = manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", []) files_path = [os.path.join(country_path, d) for d in data_files] xml_roots = get_xml_roots(files_path) csv_content = get_csv_contents(files_path) @@ -90,10 +88,10 @@ def get_csv_contents(files_path): fname = os.path.basename(filepath) for file_type in ["account.account.template", "account.account.type", "account.chart.template"]: if fname.startswith(file_type) and fname.endswith(".csv"): - with open(filepath, "r") as csvfile: + with open(filepath) as csvfile: try: csv_content.setdefault(file_type, []).append(read_csv_content(csvfile.read())) - except Exception as e: + except Exception: continue return csv_content @@ -138,7 +136,7 @@ def get_account_types(root_list, csv_content, prefix=None): if csv_content and csv_content[0][0] == "id": for row in csv_content[1:]: - row_dict = dict(zip(csv_content[0], row)) + row_dict = dict(zip(csv_content[0], row, strict=False)) data = {} if row_dict.get("code") and account_type_map.get(row_dict["code"]): data["account_type"] = account_type_map[row_dict["code"]] @@ -150,7 +148,7 @@ def get_account_types(root_list, csv_content, prefix=None): def make_maps_for_xml(xml_roots, account_types, country_dir): """make maps for `charts` and `accounts`""" - for model, root_list in xml_roots.items(): + for _model, root_list in xml_roots.items(): for root in root_list: for node in root[0].findall("record"): if node.get("model") == "account.account.template": @@ -186,7 +184,7 @@ def make_maps_for_xml(xml_roots, account_types, country_dir): def make_maps_for_csv(csv_content, account_types, country_dir): for content in csv_content.get("account.account.template", []): for row in content[1:]: - data = dict(zip(content[0], row)) + data = dict(zip(content[0], row, strict=False)) account = { "name": data.get("name"), "parent_id": data.get("parent_id:id") or data.get("parent_id/id"), @@ -206,7 +204,7 @@ def make_maps_for_csv(csv_content, account_types, country_dir): for content in csv_content.get("account.chart.template", []): for row in content[1:]: if row: - data = dict(zip(content[0], row)) + data = dict(zip(content[0], row, strict=False)) charts.setdefault(data.get("id"), {}).update( { "account_root_id": data.get("account_root_id:id") or data.get("account_root_id/id"), @@ -241,7 +239,7 @@ def make_charts(): if not src.get("name") or not src.get("account_root_id"): continue - if not src["account_root_id"] in accounts: + if src["account_root_id"] not in accounts: continue filename = src["id"][5:] + "_" + chart_id @@ -259,10 +257,16 @@ def make_charts(): val["root_type"] = "" if chart: fpath = os.path.join( - "erpnext", "erpnext", "accounts", "doctype", "account", "chart_of_accounts", filename + ".json" + "erpnext", + "erpnext", + "accounts", + "doctype", + "account", + "chart_of_accounts", + filename + ".json", ) - with open(fpath, "r") as chartfile: + with open(fpath) as chartfile: old_content = chartfile.read() if not old_content or ( json.loads(old_content).get("is_active", "No") == "No" diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py index 30eebef7fba4..49d3f66e9125 100644 --- a/erpnext/accounts/doctype/account/test_account.py +++ b/erpnext/accounts/doctype/account/test_account.py @@ -260,28 +260,20 @@ def test_child_company_account_rename_sync(self): acc.insert() self.assertTrue( - frappe.db.exists( - "Account", {"account_name": "Test Group Account", "company": "_Test Company 4"} - ) + frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 4"}) ) self.assertTrue( - frappe.db.exists( - "Account", {"account_name": "Test Group Account", "company": "_Test Company 5"} - ) + frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}) ) # Try renaming child company account acc_tc_5 = frappe.db.get_value( "Account", {"account_name": "Test Group Account", "company": "_Test Company 5"} ) - self.assertRaises( - frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account" - ) + self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account") # Rename child company account with allow_account_creation_against_child_company enabled - frappe.db.set_value( - "Company", "_Test Company 5", "allow_account_creation_against_child_company", 1 - ) + frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1) update_account_number(acc_tc_5, "Test Modified Account") self.assertTrue( @@ -290,9 +282,7 @@ def test_child_company_account_rename_sync(self): ) ) - frappe.db.set_value( - "Company", "_Test Company 5", "allow_account_creation_against_child_company", 0 - ) + frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0) to_delete = [ "Test Group Account - _TC3", @@ -317,9 +307,7 @@ def test_validate_account_currency(self): self.assertEqual(acc.account_currency, "INR") # Make a JV against this account - make_journal_entry( - "Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True - ) + make_journal_entry("Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True) acc.account_currency = "USD" self.assertRaises(frappe.ValidationError, acc.save) 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 d06bd833c8bc..f6f5506efc07 100644 --- a/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py +++ b/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py @@ -17,16 +17,12 @@ class AccountClosingBalance(Document): def make_closing_entries(closing_entries, voucher_name, company, closing_date): accounting_dimensions = get_accounting_dimensions() - previous_closing_entries = get_previous_closing_entries( - company, closing_date, accounting_dimensions - ) + previous_closing_entries = get_previous_closing_entries(company, closing_date, accounting_dimensions) combined_entries = closing_entries + previous_closing_entries - merged_entries = aggregate_with_last_account_closing_balance( - combined_entries, accounting_dimensions - ) + merged_entries = aggregate_with_last_account_closing_balance(combined_entries, accounting_dimensions) - for key, value in merged_entries.items(): + for _key, value in merged_entries.items(): cle = frappe.new_doc("Account Closing Balance") cle.update(value) cle.update(value["dimensions"]) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index c6c5f207a6a1..edddcb54df03 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -17,7 +17,8 @@ def before_insert(self): self.set_fieldname_and_label() def validate(self): - if self.document_type in core_doctypes_list + ( + if self.document_type in ( + *core_doctypes_list, "Accounting Dimension", "Project", "Cost Center", @@ -25,13 +26,10 @@ def validate(self): "Company", "Account", ): - msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type) frappe.throw(msg) - exists = frappe.db.get_value( - "Accounting Dimension", {"document_type": self.document_type}, ["name"] - ) + exists = frappe.db.get_value("Accounting Dimension", {"document_type": self.document_type}, ["name"]) if exists and self.is_new(): frappe.throw(_("Document Type already used as a dimension")) @@ -89,7 +87,6 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None): count = 0 for doctype in doclist: - if (doc_count + 1) % 2 == 0: insert_after_field = "dimension_col_break" else: @@ -123,7 +120,7 @@ def add_dimension_to_budget_doctype(df, doc): df.update( { "insert_after": "cost_center", - "depends_on": "eval:doc.budget_against == '{0}'".format(doc.document_type), + "depends_on": f"eval:doc.budget_against == '{doc.document_type}'", } ) @@ -157,19 +154,17 @@ def delete_accounting_dimension(doc): frappe.db.sql( """ DELETE FROM `tabCustom Field` - WHERE fieldname = %s - AND dt IN (%s)""" - % ("%s", ", ".join(["%s"] * len(doclist))), # nosec - tuple([doc.fieldname] + doclist), + WHERE fieldname = {} + AND dt IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec + tuple([doc.fieldname, *doclist]), ) frappe.db.sql( """ DELETE FROM `tabProperty Setter` - WHERE field_name = %s - AND doc_type IN (%s)""" - % ("%s", ", ".join(["%s"] * len(doclist))), # nosec - tuple([doc.fieldname] + doclist), + WHERE field_name = {} + AND doc_type IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec + tuple([doc.fieldname, *doclist]), ) budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options") @@ -218,7 +213,6 @@ def get_doctypes_with_dimensions(): def get_accounting_dimensions(as_list=True, filters=None): - if not filters: filters = {"disabled": 0} @@ -249,7 +243,6 @@ def get_checks_for_pl_and_bs_accounts(): def get_dimension_with_children(doctype, dimensions): - if isinstance(dimensions, str): dimensions = [dimensions] @@ -257,9 +250,7 @@ def get_dimension_with_children(doctype, dimensions): for dimension in dimensions: lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"]) - children = frappe.get_all( - doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft" - ) + children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft") all_dimensions += [c.name for c in children] return all_dimensions diff --git a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py index 3dc87bb4e386..50ca06267834 100644 --- a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py +++ b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py @@ -57,9 +57,7 @@ def tearDown(self): def create_accounting_dimension_filter(): - if not frappe.db.get_value( - "Accounting Dimension Filter", {"accounting_dimension": "Cost Center"} - ): + if not frappe.db.get_value("Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}): frappe.get_doc( { "doctype": "Accounting Dimension Filter", diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index d5f37a68067f..7bb36df3beac 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -67,7 +67,10 @@ def bootstrap_doctypes_for_closing(self): for doctype_for_closing in self.get_doctypes_for_closing(): self.append( "closed_documents", - {"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed}, + { + "document_type": doctype_for_closing.document_type, + "closed": doctype_for_closing.closed, + }, ) diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py index 41d94797ad62..16cae9683f93 100644 --- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py @@ -34,9 +34,7 @@ def test_accounting_period(self): ap1 = create_accounting_period(period_name="Test Accounting Period 2") ap1.save() - doc = create_sales_invoice( - do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC" - ) + doc = create_sales_invoice(do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC") self.assertRaises(ClosedAccountingPeriod, doc.save) def tearDown(self): diff --git a/erpnext/accounts/doctype/bank_account/test_bank_account.py b/erpnext/accounts/doctype/bank_account/test_bank_account.py index 8949524a561d..0ec388d9e5c1 100644 --- a/erpnext/accounts/doctype/bank_account/test_bank_account.py +++ b/erpnext/accounts/doctype/bank_account/test_bank_account.py @@ -37,11 +37,11 @@ def test_validate_iban(self): try: bank_account.validate_iban() except ValidationError: - msg = "BankAccount.validate_iban() failed for valid IBAN {}".format(iban) + msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}" self.fail(msg=msg) for not_iban in invalid_ibans: bank_account.iban = not_iban - msg = "BankAccount.validate_iban() accepted invalid IBAN {}".format(not_iban) + msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}" with self.assertRaises(ValidationError, msg=msg): bank_account.validate_iban() diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py index 8ad0bd17b486..6445deba6c39 100644 --- a/erpnext/accounts/doctype/bank_clearance/bank_clearance.py +++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py @@ -27,7 +27,7 @@ def get_payment_entries(self): condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')" journal_entries = frappe.db.sql( - """ + f""" select "Journal Entry" as payment_document, t1.name as payment_entry, t1.cheque_no as cheque_number, t1.cheque_date, @@ -41,9 +41,7 @@ def get_payment_entries(self): and ifnull(t1.is_opening, 'No') = 'No' {condition} group by t2.account, t1.name order by t1.posting_date ASC, t1.name DESC - """.format( - condition=condition - ), + """, {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1, ) @@ -52,7 +50,7 @@ def get_payment_entries(self): condition += "and bank_account = %(bank_account)s" payment_entries = frappe.db.sql( - """ + f""" select "Payment Entry" as payment_document, name as payment_entry, reference_no as cheque_number, reference_date as cheque_date, @@ -67,9 +65,7 @@ def get_payment_entries(self): {condition} order by posting_date ASC, name DESC - """.format( - condition=condition - ), + """, { "account": self.account, "from": self.from_date, @@ -132,11 +128,9 @@ def get_payment_entries(self): query = query.where(loan_repayment.clearance_date.isnull()) if frappe.db.has_column("Loan Repayment", "repay_from_salary"): - query = query.where((loan_repayment.repay_from_salary == 0)) + query = query.where(loan_repayment.repay_from_salary == 0) - query = query.orderby(loan_repayment.posting_date).orderby( - loan_repayment.name, order=frappe.qb.desc - ) + query = query.orderby(loan_repayment.posting_date).orderby(loan_repayment.name, order=frappe.qb.desc) loan_repayments = query.run(as_dict=True) 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 6017c5a491da..2987bac677c3 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -61,9 +61,7 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None): def get_account_balance(bank_account, till_date): # returns account balance till the specified date account = frappe.db.get_value("Bank Account", bank_account, "account") - filters = frappe._dict( - {"account": account, "report_date": till_date, "include_pos_transactions": 1} - ) + filters = frappe._dict({"account": account, "report_date": till_date, "include_pos_transactions": 1}) data = get_entries(filters) balance_as_per_system = get_balance_on(filters["account"], filters["report_date"]) @@ -76,10 +74,7 @@ def get_account_balance(bank_account, till_date): amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters) bank_bal = ( - flt(balance_as_per_system) - - flt(total_debit) - + flt(total_credit) - + amounts_not_reflected_in_system + flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system ) return bank_bal @@ -377,12 +372,13 @@ def auto_reconcile_vouchers( ) transaction = frappe.get_doc("Bank Transaction", transaction.name) account = frappe.db.get_value("Bank Account", transaction.bank_account, "account") - matched_trans = 0 for voucher in vouchers: gl_entry = frappe.db.get_value( "GL Entry", dict( - account=account, voucher_type=voucher["payment_doctype"], voucher_no=voucher["payment_name"] + account=account, + voucher_type=voucher["payment_doctype"], + voucher_no=voucher["payment_name"], ), ["credit", "debit"], as_dict=1, @@ -731,7 +727,7 @@ def get_lr_matching_query(bank_account, exact_match, filters): ) if frappe.db.has_column("Loan Repayment", "repay_from_salary"): - query = query.where((loan_repayment.repay_from_salary == 0)) + query = query.where(loan_repayment.repay_from_salary == 0) if exact_match: query.where(loan_repayment.amount_paid == filters.get("amount")) @@ -764,7 +760,7 @@ def get_pe_matching_query( if cint(filter_by_reference_date): filter_by_date = f"AND reference_date between '{from_reference_date}' and '{to_reference_date}'" order_by = " reference_date" - if frappe.flags.auto_reconcile_vouchers == True: + if frappe.flags.auto_reconcile_vouchers is True: filter_by_reference_no = f"AND reference_no = '{transaction.reference_number}'" return f""" SELECT @@ -815,7 +811,7 @@ def get_je_matching_query( if cint(filter_by_reference_date): filter_by_date = f"AND je.cheque_date between '{from_reference_date}' and '{to_reference_date}'" order_by = " je.cheque_date" - if frappe.flags.auto_reconcile_vouchers == True: + if frappe.flags.auto_reconcile_vouchers is True: filter_by_reference_no = f"AND je.cheque_no = '{transaction.reference_number}'" return f""" SELECT 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 3f5c064f4b9d..78a27c3b96d9 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py @@ -21,7 +21,7 @@ class BankStatementImport(DataImport): def __init__(self, *args, **kwargs): - super(BankStatementImport, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def validate(self): doc_before_save = self.get_doc_before_save() @@ -30,7 +30,6 @@ def validate(self): or (doc_before_save and doc_before_save.import_file != self.import_file) or (doc_before_save and doc_before_save.google_sheets_url != self.google_sheets_url) ): - template_options_dict = {} column_to_field_map = {} bank = frappe.get_doc("Bank", self.bank) @@ -45,7 +44,6 @@ def validate(self): self.validate_google_sheets_url() def start_import(self): - preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template( self.import_file, self.google_sheets_url ) @@ -102,7 +100,7 @@ def download_errored_template(data_import_name): def parse_data_from_template(raw_data): data = [] - for i, row in enumerate(raw_data): + for _i, row in enumerate(raw_data): if all(v in INVALID_VALUES for v in row): # empty row continue @@ -112,9 +110,7 @@ def parse_data_from_template(raw_data): return data -def start_import( - data_import, bank_account, import_file_path, google_sheets_url, bank, template_options -): +def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options): """This method runs in background job""" update_mapping_db(bank, template_options) diff --git a/erpnext/accounts/doctype/bank_transaction/auto_match_party.py b/erpnext/accounts/doctype/bank_transaction/auto_match_party.py index 04dab4c28a05..230407ba5a42 100644 --- a/erpnext/accounts/doctype/bank_transaction/auto_match_party.py +++ b/erpnext/accounts/doctype/bank_transaction/auto_match_party.py @@ -1,5 +1,3 @@ -from typing import Tuple, Union - import frappe from frappe.utils import flt from rapidfuzz import fuzz, process @@ -19,7 +17,7 @@ def __init__(self, **kwargs) -> None: def get(self, key): return self.__dict__.get(key, None) - def match(self) -> Union[Tuple, None]: + def match(self) -> tuple | None: result = None result = AutoMatchbyAccountIBAN( bank_party_account_number=self.bank_party_account_number, @@ -50,7 +48,7 @@ def match(self): result = self.match_account_in_party() return result - def match_account_in_party(self) -> Union[Tuple, None]: + def match_account_in_party(self) -> tuple | None: """Check if there is a IBAN/Account No. match in Customer/Supplier/Employee""" result = None parties = get_parties_in_order(self.deposit) @@ -97,7 +95,7 @@ def __init__(self, **kwargs) -> None: def get(self, key): return self.__dict__.get(key, None) - def match(self) -> Union[Tuple, None]: + def match(self) -> tuple | None: # fuzzy search by customer/supplier & employee if not (self.bank_party_name or self.description): return None @@ -105,7 +103,7 @@ def match(self) -> Union[Tuple, None]: result = self.match_party_name_desc_in_party() return result - def match_party_name_desc_in_party(self) -> Union[Tuple, None]: + def match_party_name_desc_in_party(self) -> tuple | None: """Fuzzy search party name and/or description against parties in the system""" result = None parties = get_parties_in_order(self.deposit) @@ -130,7 +128,7 @@ def match_party_name_desc_in_party(self) -> Union[Tuple, None]: return result - def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]: + def fuzzy_search_and_return_result(self, party, names, field) -> tuple | None: skip = False result = process.extract( query=self.get(field), @@ -147,7 +145,7 @@ def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, No party_name, ), skip - def process_fuzzy_result(self, result: Union[list, None]): + def process_fuzzy_result(self, result: list | None): """ If there are multiple valid close matches return None as result may be faulty. Return the result only if one accurate match stands out. diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index c0a65ed0d4c6..49c5a9fe4ee2 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -186,9 +186,7 @@ def get_clearance_details(transaction, payment_entry): """ gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account") gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry) - bt_allocations = get_total_allocated_amount( - payment_entry.payment_document, payment_entry.payment_entry - ) + bt_allocations = get_total_allocated_amount(payment_entry.payment_document, payment_entry.payment_entry) unallocated_amount = min( transaction.unallocated_amount, @@ -286,7 +284,6 @@ def get_total_allocated_amount(doctype, docname): def get_paid_amount(payment_entry, currency, gl_bank_account): if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]: - paid_amount_field = "paid_amount" if payment_entry.payment_document == "Payment Entry": doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry) @@ -325,9 +322,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account): ) elif payment_entry.payment_document == "Loan Repayment": - return frappe.db.get_value( - payment_entry.payment_document, payment_entry.payment_entry, "amount_paid" - ) + return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid") elif payment_entry.payment_document == "Bank Transaction": dep, wth = frappe.db.get_value( @@ -337,9 +332,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account): else: frappe.throw( - "Please reconcile {0}: {1} manually".format( - payment_entry.payment_document, payment_entry.payment_entry - ) + f"Please reconcile {payment_entry.payment_document}: {payment_entry.payment_entry} manually" ) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py index 372c53d49926..2fec01ad3971 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction_upload.py @@ -18,12 +18,12 @@ def upload_bank_statement(): fcontent = frappe.local.uploaded_file fname = frappe.local.uploaded_filename - if frappe.safe_encode(fname).lower().endswith("csv".encode("utf-8")): + if frappe.safe_encode(fname).lower().endswith(b"csv"): from frappe.utils.csvutils import read_csv_content rows = read_csv_content(fcontent, False) - elif frappe.safe_encode(fname).lower().endswith("xlsx".encode("utf-8")): + elif frappe.safe_encode(fname).lower().endswith(b"xlsx"): from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file rows = read_xlsx_file_from_attached_file(fcontent=fcontent) diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py index b35ed01cd9ab..71b901327d74 100644 --- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py @@ -430,9 +430,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"): mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"}) - if not frappe.db.get_value( - "Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"} - ): + if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}): mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account}) mode_of_payment.save() diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index 42b6b44690b1..bdff463a8690 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -40,10 +40,11 @@ def validate_duplicate(self): select b.name, ba.account from `tabBudget` b, `tabBudget Account` ba where - ba.parent = b.name and b.docstatus < 2 and b.company = %s and %s=%s and - b.fiscal_year=%s and b.name != %s and ba.account in (%s) """ - % ("%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))), - (self.company, budget_against, self.fiscal_year, self.name) + tuple(accounts), + ba.parent = b.name and b.docstatus < 2 and b.company = {} and {}={} and + b.fiscal_year={} and b.name != {} and ba.account in ({}) """.format( + "%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts)) + ), + (self.company, budget_against, self.fiscal_year, self.name, *tuple(accounts)), as_dict=1, ) @@ -66,12 +67,14 @@ def validate_accounts(self): if account_details.is_group: frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account)) elif account_details.company != self.company: - frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company)) + frappe.throw( + _("Account {0} does not belongs to company {1}").format(d.account, self.company) + ) elif account_details.report_type != "Profit and Loss": frappe.throw( - _("Budget cannot be assigned against {0}, as it's not an Income or Expense account").format( - d.account - ) + _( + "Budget cannot be assigned against {0}, as it's not an Income or Expense account" + ).format(d.account) ) if d.account in account_list: @@ -118,9 +121,7 @@ def validate_expense_against_budget(args, expense_amount=0): "Company", args.get("company"), "exception_budget_approver_role" ) - if not frappe.get_cached_value( - "Budget", {"fiscal_year": args.fiscal_year, "company": args.company} - ): # nosec + if not frappe.get_cached_value("Budget", {"fiscal_year": args.fiscal_year, "company": args.company}): # nosec return if not args.account: @@ -151,30 +152,24 @@ def validate_expense_against_budget(args, expense_amount=0): and args.account and (frappe.get_cached_value("Account", args.account, "root_type") == "Expense") ): - doctype = dimension.get("document_type") if frappe.get_cached_value("DocType", doctype, "is_tree"): lft, rgt = frappe.get_cached_value(doctype, args.get(budget_against), ["lft", "rgt"]) - condition = """and exists(select name from `tab%s` - where lft<=%s and rgt>=%s and name=b.%s)""" % ( - doctype, - lft, - rgt, - budget_against, - ) # nosec + condition = f"""and exists(select name from `tab{doctype}` + where lft<={lft} and rgt>={rgt} and name=b.{budget_against})""" # nosec args.is_tree = True else: - condition = "and b.%s=%s" % (budget_against, frappe.db.escape(args.get(budget_against))) + condition = f"and b.{budget_against}={frappe.db.escape(args.get(budget_against))}" args.is_tree = False args.budget_against_field = budget_against args.budget_against_doctype = doctype budget_records = frappe.db.sql( - """ + f""" select - b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution, + b.{budget_against} as budget_against, ba.budget_amount, b.monthly_distribution, ifnull(b.applicable_on_material_request, 0) as for_material_request, ifnull(applicable_on_purchase_order, 0) as for_purchase_order, ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses, @@ -187,9 +182,7 @@ def validate_expense_against_budget(args, expense_amount=0): b.name=ba.parent and b.fiscal_year=%s and ba.account=%s and b.docstatus=1 {condition} - """.format( - condition=condition, budget_against_field=budget_against - ), + """, (args.fiscal_year, args.account), as_dict=True, ) # nosec @@ -217,7 +210,12 @@ def validate_budget_records(args, budget_records, expense_amount): args["month_end_date"] = get_last_day(args.posting_date) compare_expense_with_budget( - args, budget_amount, _("Accumulated Monthly"), monthly_action, budget.budget_against, amount + args, + budget_amount, + _("Accumulated Monthly"), + monthly_action, + budget.budget_against, + amount, ) @@ -245,9 +243,8 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_ frappe.bold(fmt_money(diff, currency=currency)), ) - if ( - frappe.flags.exception_approver_role - and frappe.flags.exception_approver_role in frappe.get_roles(frappe.session.user) + if frappe.flags.exception_approver_role and frappe.flags.exception_approver_role in frappe.get_roles( + frappe.session.user ): action = "Warn" @@ -293,10 +290,8 @@ def get_requested_amount(args, budget): data = frappe.db.sql( """ select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and - child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and - parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format( - condition - ), + child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {} and + parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition), item_code, as_list=1, ) @@ -309,12 +304,10 @@ def get_ordered_amount(args, budget): condition = get_other_condition(args, budget, "Purchase Order") data = frappe.db.sql( - """ select ifnull(sum(child.amount - child.billed_amt), 0) as amount + f""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount from `tabPurchase Order Item` child, `tabPurchase Order` parent where parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt - and parent.status != 'Closed' and {0}""".format( - condition - ), + and parent.status != 'Closed' and {condition}""", item_code, as_list=1, ) @@ -327,7 +320,7 @@ def get_other_condition(args, budget, for_doc): budget_against_field = args.get("budget_against_field") if budget_against_field and args.get(budget_against_field): - condition += " and child.%s = '%s'" % (budget_against_field, args.get(budget_against_field)) + condition += f" and child.{budget_against_field} = '{args.get(budget_against_field)}'" if args.get("fiscal_year"): date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date" @@ -335,12 +328,8 @@ def get_other_condition(args, budget, for_doc): "Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"] ) - condition += """ and parent.%s - between '%s' and '%s' """ % ( - date_field, - start_date, - end_date, - ) + condition += f""" and parent.{date_field} + between '{start_date}' and '{end_date}' """ return condition @@ -362,18 +351,17 @@ def get_actual_expense(args): condition2 = """and exists(select name from `tab{doctype}` where lft>=%(lft)s and rgt<=%(rgt)s and name=gle.{budget_against_field})""".format( - doctype=args.budget_against_doctype, budget_against_field=budget_against_field # nosec + doctype=args.budget_against_doctype, + budget_against_field=budget_against_field, # nosec ) else: - condition2 = """and exists(select name from `tab{doctype}` - where name=gle.{budget_against} and - gle.{budget_against} = %({budget_against})s)""".format( - doctype=args.budget_against_doctype, budget_against=budget_against_field - ) + condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}` + where name=gle.{budget_against_field} and + gle.{budget_against_field} = %({budget_against_field})s)""" amount = flt( frappe.db.sql( - """ + f""" select sum(gle.debit) - sum(gle.credit) from `tabGL Entry` gle where @@ -384,9 +372,7 @@ def get_actual_expense(args): and gle.company=%(company)s and gle.docstatus=1 {condition2} - """.format( - condition1=condition1, condition2=condition2 - ), + """, (args), )[0][0] ) # nosec diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py index 11af9a29f6f4..6d9a6f514686 100644 --- a/erpnext/accounts/doctype/budget/test_budget.py +++ b/erpnext/accounts/doctype/budget/test_budget.py @@ -41,9 +41,7 @@ def test_monthly_budget_crossed_stop1(self): budget = make_budget(budget_against="Cost Center") - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", @@ -63,9 +61,7 @@ def test_exception_approver_role(self): budget = make_budget(budget_against="Cost Center") - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", @@ -97,9 +93,7 @@ def test_monthly_budget_crossed_for_mr(self): ) fiscal_year = get_fiscal_year(nowdate())[0] - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year) mr = frappe.get_doc( @@ -138,9 +132,7 @@ def test_monthly_budget_crossed_for_po(self): ) fiscal_year = get_fiscal_year(nowdate())[0] - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year) po = create_purchase_order(transaction_date=nowdate(), do_not_submit=True) @@ -158,9 +150,7 @@ def test_monthly_budget_crossed_stop2(self): budget = make_budget(budget_against="Project") - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") project = frappe.get_value("Project", {"project_name": "_Test Project"}) @@ -223,7 +213,7 @@ def test_monthly_budget_on_cancellation1(self): if month > 9: month = 9 - for i in range(month + 1): + for _i in range(month + 1): jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", "_Test Bank - _TC", @@ -237,9 +227,7 @@ def test_monthly_budget_on_cancellation1(self): frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name}) ) - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") self.assertRaises(BudgetError, jv.cancel) @@ -255,7 +243,7 @@ def test_monthly_budget_on_cancellation2(self): month = 9 project = frappe.get_value("Project", {"project_name": "_Test Project"}) - for i in range(month + 1): + for _i in range(month + 1): jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", "_Test Bank - _TC", @@ -270,9 +258,7 @@ def test_monthly_budget_on_cancellation2(self): frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name}) ) - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") self.assertRaises(BudgetError, jv.cancel) @@ -284,9 +270,7 @@ def test_monthly_budget_against_group_cost_center(self): set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC") budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC") - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", @@ -316,9 +300,7 @@ def test_monthly_budget_against_parent_group_cost_center(self): ).insert(ignore_permissions=True) budget = make_budget(budget_against="Cost Center", cost_center=cost_center) - frappe.db.set_value( - "Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop" - ) + frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop") jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", @@ -423,13 +405,11 @@ def make_budget(**args): fiscal_year = get_fiscal_year(nowdate())[0] if budget_against == "Project": - project_name = "{0}%".format("_Test Project/" + fiscal_year) + project_name = "{}%".format("_Test Project/" + fiscal_year) budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", project_name)}) else: - cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year) - budget_list = frappe.get_all( - "Budget", fields=["name"], filters={"name": ("like", cost_center_name)} - ) + cost_center_name = "{}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year) + budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", cost_center_name)}) for d in budget_list: frappe.db.sql("delete from `tabBudget` where name = %(name)s", d) frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d) @@ -451,24 +431,18 @@ def make_budget(**args): budget.action_if_annual_budget_exceeded = "Stop" budget.action_if_accumulated_monthly_budget_exceeded = "Ignore" budget.budget_against = budget_against - budget.append( - "accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000} - ) + budget.append("accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000}) if args.applicable_on_material_request: budget.applicable_on_material_request = 1 - budget.action_if_annual_budget_exceeded_on_mr = ( - args.action_if_annual_budget_exceeded_on_mr or "Warn" - ) + budget.action_if_annual_budget_exceeded_on_mr = args.action_if_annual_budget_exceeded_on_mr or "Warn" budget.action_if_accumulated_monthly_budget_exceeded_on_mr = ( args.action_if_accumulated_monthly_budget_exceeded_on_mr or "Warn" ) if args.applicable_on_purchase_order: budget.applicable_on_purchase_order = 1 - budget.action_if_annual_budget_exceeded_on_po = ( - args.action_if_annual_budget_exceeded_on_po or "Warn" - ) + budget.action_if_annual_budget_exceeded_on_po = args.action_if_annual_budget_exceeded_on_po or "Warn" budget.action_if_accumulated_monthly_budget_exceeded_on_po = ( args.action_if_accumulated_monthly_budget_exceeded_on_po or "Warn" ) 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 ea73847555db..0846841e84cf 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 @@ -26,9 +26,7 @@ class ChartofAccountsImporter(Document): def validate(self): if self.import_file: - get_coa( - "Chart of Accounts Importer", "All Accounts", file_name=self.import_file, for_validate=1 - ) + get_coa("Chart of Accounts Importer", "All Accounts", file_name=self.import_file, for_validate=1) def validate_columns(data): @@ -104,7 +102,7 @@ def generate_data_from_csv(file_doc, as_dict=False): file_path = file_doc.get_full_path() data = [] - with open(file_path, "r") as in_file: + with open(file_path) as in_file: csv_reader = list(csv.reader(in_file)) headers = csv_reader[0] del csv_reader[0] # delete top row and headers row @@ -203,10 +201,10 @@ def return_parent(data, child): for row in data: account_name, parent_account, account_number, parent_account_number = row[0:4] if account_number: - account_name = "{} - {}".format(account_number, account_name) + account_name = f"{account_number} - {account_name}" if parent_account_number: parent_account_number = cstr(parent_account_number).strip() - parent_account = "{} - {}".format(parent_account_number, parent_account) + parent_account = f"{parent_account_number} - {parent_account}" if parent_account == account_name == child: return [parent_account] @@ -218,7 +216,7 @@ def return_parent(data, child): frappe.bold(parent_account) ) ) - return [child] + parent_account_list + return [child, *parent_account_list] charts_map, paths = {}, [] @@ -238,12 +236,12 @@ def return_parent(data, child): ) = i if not account_name: - error_messages.append("Row {0}: Please enter Account Name".format(line_no)) + error_messages.append(f"Row {line_no}: Please enter Account Name") name = account_name if account_number: account_number = cstr(account_number).strip() - account_name = "{} - {}".format(account_number, account_name) + account_name = f"{account_number} - {account_name}" charts_map[account_name] = {} charts_map[account_name]["account_name"] = name @@ -340,9 +338,9 @@ def get_template(template_type, company): def get_sample_template(writer, company): currency = frappe.db.get_value("Company", company, "default_currency") - with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv")) as f: for row in f: - row = row.strip().split(",") + [currency] + row = [*row.strip().split(","), currency] writer.writerow(row) return writer @@ -451,7 +449,7 @@ def unset_existing_data(company): "Purchase Taxes and Charges Template", ]: frappe.db.sql( - '''delete from `tab{0}` where `company`="%s"'''.format(doctype) % (company) # nosec + f'''delete from `tab{doctype}` where `company`="%s"''' % (company) # nosec ) 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 f8ac66444b4d..9851c4c5a850 100644 --- a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py +++ b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py @@ -31,71 +31,71 @@ def create_or_update_cheque_print_format(template_name): cheque_print.html = """ -
-
- +
+ - %(message_to_show)s + {message_to_show} - - {{ frappe.utils.formatdate(doc.reference_date) or '' }} + {{{{ frappe.utils.formatdate(doc.reference_date) or '' }}}} - - {{ doc.account_no or '' }} + {{{{ doc.account_no or '' }}}} - - {{doc.party_name}} + {{{{doc.party_name}}}} - - {{frappe.utils.money_in_words(doc.base_paid_amount or doc.base_received_amount)}} + + {{{{frappe.utils.money_in_words(doc.base_paid_amount or doc.base_received_amount)}}}} - - {{doc.get_formatted("base_paid_amount") or doc.get_formatted("base_received_amount")}} + {{{{doc.get_formatted("base_paid_amount") or doc.get_formatted("base_received_amount")}}}} - - {{doc.company}} + {{{{doc.company}}}}
-
""" % { - "starting_position_from_top_edge": doc.starting_position_from_top_edge +
""".format( + starting_position_from_top_edge=doc.starting_position_from_top_edge if doc.cheque_size == "A4" else 0.0, - "cheque_width": doc.cheque_width, - "cheque_height": doc.cheque_height, - "acc_pay_dist_from_top_edge": doc.acc_pay_dist_from_top_edge, - "acc_pay_dist_from_left_edge": doc.acc_pay_dist_from_left_edge, - "message_to_show": doc.message_to_show if doc.message_to_show else _("Account Pay Only"), - "date_dist_from_top_edge": doc.date_dist_from_top_edge, - "date_dist_from_left_edge": doc.date_dist_from_left_edge, - "acc_no_dist_from_top_edge": doc.acc_no_dist_from_top_edge, - "acc_no_dist_from_left_edge": doc.acc_no_dist_from_left_edge, - "payer_name_from_top_edge": doc.payer_name_from_top_edge, - "payer_name_from_left_edge": doc.payer_name_from_left_edge, - "amt_in_words_from_top_edge": doc.amt_in_words_from_top_edge, - "amt_in_words_from_left_edge": doc.amt_in_words_from_left_edge, - "amt_in_word_width": doc.amt_in_word_width, - "amt_in_words_line_spacing": doc.amt_in_words_line_spacing, - "amt_in_figures_from_top_edge": doc.amt_in_figures_from_top_edge, - "amt_in_figures_from_left_edge": doc.amt_in_figures_from_left_edge, - "signatory_from_top_edge": doc.signatory_from_top_edge, - "signatory_from_left_edge": doc.signatory_from_left_edge, - } + cheque_width=doc.cheque_width, + cheque_height=doc.cheque_height, + acc_pay_dist_from_top_edge=doc.acc_pay_dist_from_top_edge, + acc_pay_dist_from_left_edge=doc.acc_pay_dist_from_left_edge, + message_to_show=doc.message_to_show if doc.message_to_show else _("Account Pay Only"), + date_dist_from_top_edge=doc.date_dist_from_top_edge, + date_dist_from_left_edge=doc.date_dist_from_left_edge, + acc_no_dist_from_top_edge=doc.acc_no_dist_from_top_edge, + acc_no_dist_from_left_edge=doc.acc_no_dist_from_left_edge, + payer_name_from_top_edge=doc.payer_name_from_top_edge, + payer_name_from_left_edge=doc.payer_name_from_left_edge, + amt_in_words_from_top_edge=doc.amt_in_words_from_top_edge, + amt_in_words_from_left_edge=doc.amt_in_words_from_left_edge, + amt_in_word_width=doc.amt_in_word_width, + amt_in_words_line_spacing=doc.amt_in_words_line_spacing, + amt_in_figures_from_top_edge=doc.amt_in_figures_from_top_edge, + amt_in_figures_from_left_edge=doc.amt_in_figures_from_left_edge, + signatory_from_top_edge=doc.signatory_from_top_edge, + signatory_from_left_edge=doc.signatory_from_left_edge, + ) cheque_print.save(ignore_permissions=True) diff --git a/erpnext/accounts/doctype/cost_center/cost_center.py b/erpnext/accounts/doctype/cost_center/cost_center.py index e8b34bbf034c..ec6c17ad639d 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center.py +++ b/erpnext/accounts/doctype/cost_center/cost_center.py @@ -15,9 +15,7 @@ class CostCenter(NestedSet): def autoname(self): from erpnext.accounts.utils import get_autoname_with_number - self.name = get_autoname_with_number( - self.cost_center_number, self.cost_center_name, self.company - ) + self.name = get_autoname_with_number(self.cost_center_number, self.cost_center_name, self.company) def validate(self): self.validate_mandatory() @@ -90,14 +88,14 @@ def before_rename(self, olddn, newdn, merge=False): new_cost_center = get_name_with_abbr(newdn, self.company) # Validate properties before merging - super(CostCenter, self).before_rename(olddn, new_cost_center, merge, "is_group") + super().before_rename(olddn, new_cost_center, merge, "is_group") if not merge: new_cost_center = get_name_with_number(new_cost_center, self.cost_center_number) return new_cost_center def after_rename(self, olddn, newdn, merge=False): - super(CostCenter, self).after_rename(olddn, newdn, merge) + super().after_rename(olddn, newdn, merge) if not merge: new_cost_center = frappe.db.get_value( diff --git a/erpnext/accounts/doctype/cost_center/test_cost_center.py b/erpnext/accounts/doctype/cost_center/test_cost_center.py index 2ec16092d4db..7d01918fb549 100644 --- a/erpnext/accounts/doctype/cost_center/test_cost_center.py +++ b/erpnext/accounts/doctype/cost_center/test_cost_center.py @@ -10,7 +10,6 @@ class TestCostCenter(unittest.TestCase): def test_cost_center_creation_against_child_node(self): - if not frappe.db.get_value("Cost Center", {"name": "_Test Cost Center 2 - _TC"}): frappe.get_doc(test_records[1]).insert() 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 54ffe21a1522..c6cf232ceb89 100644 --- a/erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.py +++ b/erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.py @@ -29,7 +29,7 @@ class InvalidDateError(frappe.ValidationError): class CostCenterAllocation(Document): def __init__(self, *args, **kwargs): - super(CostCenterAllocation, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._skip_from_date_validation = False def validate(self): @@ -44,9 +44,7 @@ def validate_total_allocation_percentage(self): total_percentage = sum([d.percentage for d in self.get("allocation_percentages", [])]) if total_percentage != 100: - frappe.throw( - _("Total percentage against cost centers should be 100"), WrongPercentageAllocation - ) + frappe.throw(_("Total percentage against cost centers should be 100"), WrongPercentageAllocation) def validate_from_date_based_on_existing_gle(self): # Check if GLE exists against the main cost center 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 7a420f984ad5..39aff032b3d6 100644 --- a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py +++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py @@ -18,7 +18,6 @@ def validate(self): def set_parameters_and_result(self): if self.service_provider == "exchangerate.host": - if not self.access_key: frappe.throw( _("Access Key is required for Service Provider: {0}").format( @@ -53,9 +52,7 @@ def validate_parameters(self): transaction_date=nowdate(), to_currency="INR", from_currency="USD" ) - api_url = self.api_endpoint.format( - transaction_date=nowdate(), to_currency="INR", from_currency="USD" - ) + api_url = self.api_endpoint.format(transaction_date=nowdate(), to_currency="INR", from_currency="USD") try: response = requests.get(api_url, params=params) @@ -75,14 +72,14 @@ def validate_result(self, response, value): ] except Exception: frappe.throw(_("Invalid result key. Response:") + " " + response.text) - if not isinstance(value, (int, float)): + if not isinstance(value, int | float): frappe.throw(_("Returned exchange rate is neither integer not float.")) self.url = response.url @frappe.whitelist() -def get_api_endpoint(service_provider: str = None, use_http: bool = False): +def get_api_endpoint(service_provider: str | None = None, use_http: bool = False): if service_provider and service_provider in ["exchangerate.host", "frankfurter.app"]: if service_provider == "exchangerate.host": api = "api.exchangerate.host/convert" 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 00d62f3f6019..24a325b91648 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -246,7 +246,6 @@ def calculate_new_account_balance(company, posting_date, account_details): # Handle Accounts with '0' balance in Account/Base Currency for d in [x for x in account_details if x.zero_balance]: - if d.balance != 0: current_exchange_rate = new_exchange_rate = 0 @@ -259,7 +258,8 @@ def calculate_new_account_balance(company, posting_date, account_details): new_balance_in_account_currency = 0 current_exchange_rate = ( - calculate_exchange_rate_using_last_gle(company, d.account, d.party_type, d.party) or 0.0 + calculate_exchange_rate_using_last_gle(company, d.account, d.party_type, d.party) + or 0.0 ) gain_loss = new_balance_in_account_currency - ( @@ -313,9 +313,7 @@ def make_jv_entries(self): revaluation_jv = self.make_jv_for_revaluation() if revaluation_jv: - frappe.msgprint( - f"Revaluation Journal: {get_link_to_form('Journal Entry', revaluation_jv.name)}" - ) + frappe.msgprint(f"Revaluation Journal: {get_link_to_form('Journal Entry', revaluation_jv.name)}") return { "revaluation_jv": revaluation_jv.name if revaluation_jv else None, @@ -372,7 +370,8 @@ def make_jv_for_zero_balance(self): journal_account.update( { dr_or_cr: flt( - abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency") + abs(d.get("balance_in_account_currency")), + d.precision("balance_in_account_currency"), ), reverse_dr_or_cr: 0, "debit": 0, @@ -498,7 +497,9 @@ def make_jv_for_revaluation(self): abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency") ), "cost_center": erpnext.get_default_cost_center(self.company), - "exchange_rate": flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")), + "exchange_rate": flt( + d.get("current_exchange_rate"), d.precision("current_exchange_rate") + ), "reference_type": "Exchange Rate Revaluation", "reference_name": self.name, } @@ -576,7 +577,7 @@ def calculate_exchange_rate_using_last_gle(company, account, party_type, party): @frappe.whitelist() def get_account_details( - company, posting_date, account, party_type=None, party=None, rounding_loss_allowance: float = None + company, posting_date, account, party_type=None, party=None, rounding_loss_allowance: float | None = None ): if not (company and posting_date): frappe.throw(_("Company and Posting Date is mandatory")) @@ -589,7 +590,7 @@ def get_account_details( frappe.throw(_("Party Type and Party is mandatory for {0} account").format(account_type)) account_details = {} - company_currency = erpnext.get_company_currency(company) + erpnext.get_company_currency(company) account_details = { "account_currency": account_currency, @@ -603,9 +604,7 @@ def get_account_details( rounding_loss_allowance=rounding_loss_allowance, ) - if account_balance and ( - account_balance[0].balance or account_balance[0].balance_in_account_currency - ): + if account_balance and (account_balance[0].balance or account_balance[0].balance_in_account_currency): if account_with_new_balance := ExchangeRateRevaluation.calculate_new_account_balance( company, posting_date, account_balance ): diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py index ced04ced3fdd..709be43e6996 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py @@ -1,21 +1,14 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe -from frappe import qb from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, flt, today -from erpnext import get_default_cost_center from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry -from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -from erpnext.accounts.party import get_party_account from erpnext.accounts.test.accounts_mixin import AccountsTestMixin -from erpnext.stock.doctype.item.test_item import create_item class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase): @@ -73,9 +66,7 @@ def test_01_revaluation_of_forex_balance(self): err.extend("accounts", accounts) row = err.accounts[0] row.new_exchange_rate = 85 - row.new_balance_in_base_currency = flt( - row.new_exchange_rate * flt(row.balance_in_account_currency) - ) + row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency)) row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency) err.set_total_gain_loss() err = err.save().submit() @@ -127,9 +118,9 @@ def test_02_accounts_only_with_base_currency_balance(self): pe.save().submit() # Cancel the auto created gain/loss JE to simulate balance only in base currency - je = frappe.db.get_all( - "Journal Entry Account", filters={"reference_name": si.name}, pluck="parent" - )[0] + je = frappe.db.get_all("Journal Entry Account", filters={"reference_name": si.name}, pluck="parent")[ + 0 + ] frappe.get_doc("Journal Entry", je).cancel() err = frappe.new_doc("Exchange Rate Revaluation") @@ -235,9 +226,9 @@ def test_03_accounts_only_with_account_currency_balance(self): self.assertEqual(flt(acc.debit, precision), 0.0) self.assertEqual(flt(acc.credit, precision), 0.0) - row = [x for x in je.accounts if x.account == self.debtors_usd][0] + row = next(x for x in je.accounts if x.account == self.debtors_usd) self.assertEqual(flt(row.credit_in_account_currency, precision), 5.0) # in USD - row = [x for x in je.accounts if x.account != self.debtors_usd][0] + row = next(x for x in je.accounts if x.account != self.debtors_usd) self.assertEqual(flt(row.debit_in_account_currency, precision), 421.06) # in INR # total_debit and total_credit will be 0.0, as JV is posting only to account currency fields @@ -294,5 +285,5 @@ def test_04_get_account_details_function(self): "new_balance_in_account_currency": 100.0, } - for key, val in expected_data.items(): + for key, _val in expected_data.items(): self.assertEqual(expected_data.get(key), account_details.get(key)) diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index a945860a7112..4acdd9a7e8ef 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -98,9 +98,9 @@ def validate_overlap(self): if overlap: frappe.throw( - _("Year start date or end date is overlapping with {0}. To avoid please set company").format( - existing.name - ), + _( + "Year start date or end date is overlapping with {0}. To avoid please set company" + ).format(existing.name), frappe.NameError, ) @@ -116,9 +116,9 @@ def check_duplicate_fiscal_year(doc): not frappe.flags.in_test ): frappe.throw( - _("Fiscal Year Start Date and Fiscal Year End Date are already set in Fiscal Year {0}").format( - fiscal_year - ) + _( + "Fiscal Year Start Date and Fiscal Year End Date are already set in Fiscal Year {0}" + ).format(fiscal_year) ) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 346fee81812a..6ca5e6377c53 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -63,13 +63,18 @@ def on_update(self): ]: # Update outstanding amt on against voucher if ( - self.against_voucher_type in ["Journal Entry", "Sales Invoice", "Purchase Invoice", "Fees"] + self.against_voucher_type + in ["Journal Entry", "Sales Invoice", "Purchase Invoice", "Fees"] and self.against_voucher and self.flags.update_outstanding == "Yes" and not frappe.flags.is_reverse_depr_entry ): update_outstanding_amt( - self.account, self.party_type, self.party, self.against_voucher_type, self.against_voucher + self.account, + self.party_type, + self.party, + self.against_voucher_type, + self.against_voucher, ) def check_mandatory(self): @@ -139,9 +144,9 @@ def validate_dimensions_for_pl_and_bs(self): ): if not self.get(dimension.fieldname): frappe.throw( - _("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.").format( - dimension.label, self.account - ) + _( + "Accounting Dimension {0} is required for 'Profit and Loss' account {1}." + ).format(dimension.label, self.account) ) if ( @@ -153,9 +158,9 @@ def validate_dimensions_for_pl_and_bs(self): ): if not self.get(dimension.fieldname): frappe.throw( - _("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.").format( - dimension.label, self.account - ) + _( + "Accounting Dimension {0} is required for 'Balance Sheet' account {1}." + ).format(dimension.label, self.account) ) def check_pl_account(self): @@ -203,9 +208,7 @@ def validate_cost_center(self): if not self.cost_center: return - is_group, company = frappe.get_cached_value( - "Cost Center", self.cost_center, ["is_group", "company"] - ) + is_group, company = frappe.get_cached_value("Cost Center", self.cost_center, ["is_group", "company"]) if company != self.company: frappe.throw( @@ -274,7 +277,7 @@ def update_outstanding_amt( account, party_type, party, against_voucher_type, against_voucher, on_cancel=False ): if party_type and party: - party_condition = " and party_type={0} and party={1}".format( + party_condition = " and party_type={} and party={}".format( frappe.db.escape(party_type), frappe.db.escape(party) ) else: @@ -282,23 +285,19 @@ def update_outstanding_amt( if against_voucher_type == "Sales Invoice": party_account = frappe.get_cached_value(against_voucher_type, against_voucher, "debit_to") - account_condition = "and account in ({0}, {1})".format( - frappe.db.escape(account), frappe.db.escape(party_account) - ) + account_condition = f"and account in ({frappe.db.escape(account)}, {frappe.db.escape(party_account)})" else: - account_condition = " and account = {0}".format(frappe.db.escape(account)) + account_condition = f" and account = {frappe.db.escape(account)}" # get final outstanding amt bal = flt( frappe.db.sql( - """ + f""" select sum(debit_in_account_currency) - sum(credit_in_account_currency) from `tabGL Entry` where against_voucher_type=%s and against_voucher=%s and voucher_type != 'Invoice Discounting' - {0} {1}""".format( - party_condition, account_condition - ), + {party_condition} {account_condition}""", (against_voucher_type, against_voucher), )[0][0] or 0.0 @@ -309,12 +308,10 @@ def update_outstanding_amt( elif against_voucher_type == "Journal Entry": against_voucher_amount = flt( frappe.db.sql( - """ + f""" select sum(debit_in_account_currency) - sum(credit_in_account_currency) from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s - and account = %s and (against_voucher is null or against_voucher='') {0}""".format( - party_condition - ), + and account = %s and (against_voucher is null or against_voucher='') {party_condition}""", (against_voucher, account), )[0][0] ) @@ -333,7 +330,9 @@ def update_outstanding_amt( # Validation : Outstanding can not be negative for JV if bal < 0 and not on_cancel: frappe.throw( - _("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal)) + _("Outstanding for {0} cannot be less than zero ({1})").format( + against_voucher, fmt_money(bal) + ) ) if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]: @@ -406,7 +405,7 @@ def rename_temporarily_named_docs(doctype): set_name_from_naming_options(frappe.get_meta(doctype).autoname, doc) newname = doc.name frappe.db.sql( - "UPDATE `tab{}` SET name = %s, to_rename = 0 where name = %s".format(doctype), + f"UPDATE `tab{doctype}` SET name = %s, to_rename = 0 where name = %s", (newname, oldname), auto_commit=True, ) diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py index b188b09843ad..3edfd67b0051 100644 --- a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py @@ -14,9 +14,7 @@ class TestGLEntry(unittest.TestCase): def test_round_off_entry(self): frappe.db.set_value("Company", "_Test Company", "round_off_account", "_Test Write Off - _TC") - frappe.db.set_value( - "Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC" - ) + frappe.db.set_value("Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC") jv = make_journal_entry( "_Test Account Cost for Goods Sold - _TC", @@ -73,7 +71,9 @@ def test_rename_entries(self): ) self.assertTrue(all(entry.to_rename == 0 for entry in new_gl_entries)) - self.assertTrue(all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries))) + self.assertTrue( + all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries, strict=False)) + ) new_naming_series_current_value = frappe.db.sql( "SELECT current from tabSeries where name = %s", naming_series diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index 5bd4585a9a8d..2322d68c0004 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -55,9 +55,7 @@ def validate_invoices(self): frappe.throw( _( "Row({0}): Outstanding Amount cannot be greater than actual Outstanding Amount {1} in {2}" - ).format( - record.idx, frappe.bold(actual_outstanding), frappe.bold(record.sales_invoice) - ) + ).format(record.idx, frappe.bold(actual_outstanding), frappe.bold(record.sales_invoice)) ) def calculate_total_amount(self): @@ -77,7 +75,9 @@ def set_status(self, status=None, cancel=0): self.status = status self.db_set("status", status) for d in self.invoices: - frappe.get_doc("Sales Invoice", d.sales_invoice).set_status(update=True, update_modified=False) + frappe.get_doc("Sales Invoice", d.sales_invoice).set_status( + update=True, update_modified=False + ) else: self.status = "Draft" if self.docstatus == 1: diff --git a/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py index a85fdfcad7f7..65e3c3dcd6ad 100644 --- a/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py @@ -75,7 +75,7 @@ def test_gl_entries_in_base_currency(self): gle = get_gl_entries("Invoice Discounting", inv_disc.name) expected_gle = {inv.debit_to: [0.0, 200], self.ar_credit: [200, 0.0]} - for i, gle in enumerate(gle): + for _i, gle in enumerate(gle): self.assertEqual([gle.debit, gle.credit], expected_gle.get(gle.account)) def test_loan_on_submit(self): @@ -92,9 +92,7 @@ def test_loan_on_submit(self): period=60, ) self.assertEqual(inv_disc.status, "Sanctioned") - self.assertEqual( - inv_disc.loan_end_date, add_days(inv_disc.loan_start_date, inv_disc.loan_period) - ) + self.assertEqual(inv_disc.loan_end_date, add_days(inv_disc.loan_start_date, inv_disc.loan_period)) def test_on_disbursed(self): inv = create_sales_invoice(rate=500) @@ -262,13 +260,9 @@ def test_make_payment_before_loan_period(self): je_on_payment.submit() self.assertEqual(je_on_payment.accounts[0].account, self.ar_discounted) - self.assertEqual( - je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount) - ) + self.assertEqual(je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount)) self.assertEqual(je_on_payment.accounts[1].account, self.bank_account) - self.assertEqual( - je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount) - ) + self.assertEqual(je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount)) inv.reload() self.assertEqual(inv.outstanding_amount, 0) @@ -304,13 +298,9 @@ def test_make_payment_before_after_period(self): je_on_payment.submit() self.assertEqual(je_on_payment.accounts[0].account, self.ar_unpaid) - self.assertEqual( - je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount) - ) + self.assertEqual(je_on_payment.accounts[0].credit_in_account_currency, flt(inv.outstanding_amount)) self.assertEqual(je_on_payment.accounts[1].account, self.bank_account) - self.assertEqual( - je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount) - ) + self.assertEqual(je_on_payment.accounts[1].debit_in_account_currency, flt(inv.outstanding_amount)) inv.reload() self.assertEqual(inv.outstanding_amount, 0) 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 23f36ec6d8d0..755ff4908859 100644 --- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py +++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py @@ -14,7 +14,7 @@ def validate(self): def autoname(self): if self.company and self.title: abbr = frappe.get_cached_value("Company", self.company, "abbr") - self.name = "{0} - {1}".format(self.title, abbr) + self.name = f"{self.title} - {abbr}" def validate_tax_accounts(self): """Check whether Tax Rate is not entered twice for same Tax Type""" diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 883881286533..b4fb13e42c3d 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -33,7 +33,7 @@ class StockAccountInvalidTransaction(frappe.ValidationError): class JournalEntry(AccountsController): def __init__(self, *args, **kwargs): - super(JournalEntry, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def get_feed(self): return self.voucher_type @@ -102,7 +102,7 @@ def on_submit(self): def on_cancel(self): # References for this Journal are removed on the `on_cancel` event in accounts_controller - super(JournalEntry, self).on_cancel() + super().on_cancel() self.ignore_linked_doctypes = ( "GL Entry", "Stock Ledger Entry", @@ -137,10 +137,7 @@ def update_advance_paid(self): frappe.get_doc(voucher_type, voucher_no).set_total_advance_paid() def validate_inter_company_accounts(self): - if ( - self.voucher_type == "Inter Company Journal Entry" - and self.inter_company_journal_entry_reference - ): + if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference: doc = frappe.get_doc("Journal Entry", self.inter_company_journal_entry_reference) account_currency = frappe.get_cached_value("Company", self.company, "default_currency") previous_account_currency = frappe.get_cached_value("Company", doc.company, "default_currency") @@ -286,10 +283,7 @@ def update_asset_value(self): asset.set_status() def update_inter_company_jv(self): - if ( - self.voucher_type == "Inter Company Journal Entry" - and self.inter_company_journal_entry_reference - ): + if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference: frappe.db.set_value( "Journal Entry", self.inter_company_journal_entry_reference, @@ -317,17 +311,25 @@ def _validate_invoice_discounting_status(inv_disc, id_status, expected_status, r if d.account == inv_disc_doc.short_term_loan and d.reference_name == inv_disc: if self.docstatus == 1: if d.credit > 0: - _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Sanctioned", d.idx) + _validate_invoice_discounting_status( + inv_disc, inv_disc_doc.status, "Sanctioned", d.idx + ) status = "Disbursed" elif d.debit > 0: - _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Disbursed", d.idx) + _validate_invoice_discounting_status( + inv_disc, inv_disc_doc.status, "Disbursed", d.idx + ) status = "Settled" else: if d.credit > 0: - _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Disbursed", d.idx) + _validate_invoice_discounting_status( + inv_disc, inv_disc_doc.status, "Disbursed", d.idx + ) status = "Sanctioned" elif d.debit > 0: - _validate_invoice_discounting_status(inv_disc, inv_disc_doc.status, "Settled", d.idx) + _validate_invoice_discounting_status( + inv_disc, inv_disc_doc.status, "Settled", d.idx + ) status = "Disbursed" break if status: @@ -384,10 +386,7 @@ def unlink_asset_reference(self): ) def unlink_inter_company_jv(self): - if ( - self.voucher_type == "Inter Company Journal Entry" - and self.inter_company_journal_entry_reference - ): + if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference: frappe.db.set_value( "Journal Entry", self.inter_company_journal_entry_reference, @@ -409,9 +408,9 @@ def validate_party(self): if account_type in ["Receivable", "Payable"]: if not (d.party_type and d.party): frappe.throw( - _("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format( - d.idx, d.account - ) + _( + "Row {0}: Party Type and Party is required for Receivable / Payable account {1}" + ).format(d.idx, d.account) ) elif ( d.party_type @@ -476,16 +475,18 @@ def validate_entries_for_advance(self): def system_generated_gain_loss(self): return ( - self.voucher_type == "Exchange Gain Or Loss" - and self.multi_currency - and self.is_system_generated + self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency and self.is_system_generated ) def validate_against_jv(self): for d in self.get("accounts"): if d.reference_type == "Journal Entry": account_root_type = frappe.get_cached_value("Account", d.account, "root_type") - if account_root_type == "Asset" and flt(d.debit) > 0 and not self.system_generated_gain_loss(): + if ( + account_root_type == "Asset" + and flt(d.debit) > 0 + and not self.system_generated_gain_loss() + ): frappe.throw( _( "Row #{0}: For {1}, you can select reference document only if account gets credited" @@ -567,11 +568,13 @@ def validate_reference_doc(self): if d.reference_type == "Purchase Order" and flt(d.credit) > 0: frappe.throw( - _("Row {0}: Credit entry can not be linked with a {1}").format(d.idx, d.reference_type) + _("Row {0}: Credit entry can not be linked with a {1}").format( + d.idx, d.reference_type + ) ) # set totals - if not d.reference_name in self.reference_totals: + if d.reference_name not in self.reference_totals: self.reference_totals[d.reference_name] = 0.0 if self.voucher_type not in ("Deferred Revenue", "Deferred Expense"): @@ -589,7 +592,10 @@ def validate_reference_doc(self): # check if party and account match if d.reference_type in ("Sales Invoice", "Purchase Invoice"): - if self.voucher_type in ("Deferred Revenue", "Deferred Expense") and d.reference_detail_no: + if ( + self.voucher_type in ("Deferred Revenue", "Deferred Expense") + and d.reference_detail_no + ): debit_or_credit = "Debit" if d.debit else "Credit" party_account = get_deferred_booking_accounts( d.reference_type, d.reference_detail_no, debit_or_credit @@ -598,7 +604,8 @@ def validate_reference_doc(self): else: if d.reference_type == "Sales Invoice": party_account = ( - get_party_account_based_on_invoice_discounting(d.reference_name) or against_voucher[1] + get_party_account_based_on_invoice_discounting(d.reference_name) + or against_voucher[1] ) else: party_account = against_voucher[1] @@ -722,7 +729,9 @@ def validate_total_debit_and_credit(self): if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency): if self.difference: frappe.throw( - _("Total Debit must be equal to Total Credit. The difference is {0}").format(self.difference) + _("Total Debit must be equal to Total Credit. The difference is {0}").format( + self.difference + ) ) def set_total_debit_credit(self): @@ -786,7 +795,6 @@ def set_exchange_rate(self): and self.posting_date ) ): - ignore_exchange_rate = False if self.get("flags") and self.flags.get("ignore_exchange_rate"): ignore_exchange_rate = True @@ -1032,27 +1040,21 @@ def get_outstanding_invoices(self): self.validate_total_debit_and_credit() def get_values(self): - cond = ( - " and outstanding_amount <= {0}".format(self.write_off_amount) - if flt(self.write_off_amount) > 0 - else "" - ) + cond = f" and outstanding_amount <= {self.write_off_amount}" if flt(self.write_off_amount) > 0 else "" if self.write_off_based_on == "Accounts Receivable": return frappe.db.sql( """select name, debit_to as account, customer as party, outstanding_amount - from `tabSales Invoice` where docstatus = 1 and company = %s - and outstanding_amount > 0 %s""" - % ("%s", cond), + from `tabSales Invoice` where docstatus = 1 and company = {} + and outstanding_amount > 0 {}""".format("%s", cond), self.company, as_dict=True, ) elif self.write_off_based_on == "Accounts Payable": return frappe.db.sql( """select name, credit_to as account, supplier as party, outstanding_amount - from `tabPurchase Invoice` where docstatus = 1 and company = %s - and outstanding_amount > 0 %s""" - % ("%s", cond), + from `tabPurchase Invoice` where docstatus = 1 and company = {} + and outstanding_amount > 0 {}""".format("%s", cond), self.company, as_dict=True, ) @@ -1161,7 +1163,7 @@ def get_payment_entry_against_order( "amount_field_bank": amount_field_bank, "amount": amount, "debit_in_account_currency": debit_in_account_currency, - "remarks": "Advance Payment received against {0} {1}".format(dt, dn), + "remarks": f"Advance Payment received against {dt} {dn}", "is_advance": "Yes", "bank_account": bank_account, "journal_entry": journal_entry, @@ -1200,7 +1202,7 @@ def get_payment_entry_against_invoice( "amount_field_bank": amount_field_bank, "amount": amount if amount else abs(ref_doc.outstanding_amount), "debit_in_account_currency": debit_in_account_currency, - "remarks": "Payment received against {0} {1}. {2}".format(dt, dn, ref_doc.remarks), + "remarks": f"Payment received against {dt} {dn}. {ref_doc.remarks}", "is_advance": "No", "bank_account": bank_account, "journal_entry": journal_entry, @@ -1226,9 +1228,7 @@ def get_payment_entry(ref_doc, args): ) je = frappe.new_doc("Journal Entry") - je.update( - {"voucher_type": "Bank Entry", "company": ref_doc.company, "remark": args.get("remarks")} - ) + je.update({"voucher_type": "Bank Entry", "company": ref_doc.company, "remark": args.get("remarks")}) party_row = je.append( "accounts", @@ -1251,9 +1251,7 @@ def get_payment_entry(ref_doc, args): bank_row = je.append("accounts") # Make it bank_details - bank_account = get_default_bank_cash_account( - ref_doc.company, "Bank", account=args.get("bank_account") - ) + bank_account = get_default_bank_cash_account(ref_doc.company, "Bank", account=args.get("bank_account")) if bank_account: bank_row.update(bank_account) # Modified to include the posting date for which the exchange rate is required. @@ -1293,7 +1291,7 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters): return [] return frappe.db.sql( - """ + f""" SELECT jv.name, jv.posting_date, jv.user_remark FROM `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail WHERE jv_detail.parent = jv.name @@ -1304,16 +1302,14 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters): OR jv_detail.reference_type = '' ) AND jv.docstatus = 1 - AND jv.`{0}` LIKE %(txt)s + AND jv.`{searchfield}` LIKE %(txt)s ORDER BY jv.name DESC LIMIT %(limit)s offset %(offset)s - """.format( - searchfield - ), + """, dict( account=filters.get("account"), party=cstr(filters.get("party")), - txt="%{0}%".format(txt), + txt=f"%{txt}%", offset=start, limit=page_len, ), @@ -1335,19 +1331,15 @@ def get_outstanding(args): condition = " and party=%(party)s" if args.get("party") else "" against_jv_amount = frappe.db.sql( - """ + f""" select sum(debit_in_account_currency) - sum(credit_in_account_currency) - from `tabJournal Entry Account` where parent=%(docname)s and account=%(account)s {0} - and (reference_type is null or reference_type = '')""".format( - condition - ), + from `tabJournal Entry Account` where parent=%(docname)s and account=%(account)s {condition} + and (reference_type is null or reference_type = '')""", args, ) against_jv_amount = flt(against_jv_amount[0][0]) if against_jv_amount else 0 - amount_field = ( - "credit_in_account_currency" if against_jv_amount > 0 else "debit_in_account_currency" - ) + amount_field = "credit_in_account_currency" if against_jv_amount > 0 else "debit_in_account_currency" return {amount_field: abs(against_jv_amount)} elif args.get("doctype") in ("Sales Invoice", "Purchase Invoice"): party_type = "Customer" if args.get("doctype") == "Sales Invoice" else "Supplier" @@ -1360,9 +1352,7 @@ def get_outstanding(args): due_date = invoice.get("due_date") - exchange_rate = ( - invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1 - ) + exchange_rate = invoice.conversion_rate if (args.get("account_currency") != company_currency) else 1 if args["doctype"] == "Sales Invoice": amount_field = ( @@ -1400,17 +1390,13 @@ def get_party_account_and_currency(company, party_type, party): @frappe.whitelist() -def get_account_details_and_party_type( - account, date, company, debit=None, credit=None, exchange_rate=None -): +def get_account_details_and_party_type(account, date, company, debit=None, credit=None, exchange_rate=None): """Returns dict of account details and party type to be set in Journal Entry on selection of account.""" if not frappe.has_permission("Account"): frappe.msgprint(_("No Permission"), raise_exception=1) company_currency = erpnext.get_company_currency(company) - account_details = frappe.db.get_value( - "Account", account, ["account_type", "account_currency"], as_dict=1 - ) + account_details = frappe.db.get_value("Account", account, ["account_type", "account_currency"], as_dict=1) if not account_details: return diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py index e44ebc6afce3..979f964b62ac 100644 --- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py @@ -69,10 +69,8 @@ def jv_against_voucher_testcase(self, base_jv, test_voucher): self.assertTrue( frappe.db.sql( - """select name from `tabJournal Entry Account` - where reference_type = %s and reference_name = %s and {0}=400""".format( - dr_or_cr - ), + f"""select name from `tabJournal Entry Account` + where reference_type = %s and reference_name = %s and {dr_or_cr}=400""", (submitted_voucher.doctype, submitted_voucher.name), ) ) @@ -84,9 +82,8 @@ def jv_against_voucher_testcase(self, base_jv, test_voucher): def advance_paid_testcase(self, base_jv, test_voucher, dr_or_cr): # Test advance paid field advance_paid = frappe.db.sql( - """select advance_paid from `tab%s` - where name=%s""" - % (test_voucher.doctype, "%s"), + """select advance_paid from `tab{}` + where name={}""".format(test_voucher.doctype, "%s"), (test_voucher.name), ) payment_against_order = base_jv.get("accounts")[0].get(dr_or_cr) @@ -159,9 +156,7 @@ def test_jv_against_stock_account(self): jv.cancel() def test_multi_currency(self): - jv = make_journal_entry( - "_Test Bank USD - _TC", "_Test Bank - _TC", 100, exchange_rate=50, save=False - ) + jv = make_journal_entry("_Test Bank USD - _TC", "_Test Bank - _TC", 100, exchange_rate=50, save=False) jv.get("accounts")[1].credit_in_account_currency = 5000 jv.submit() @@ -201,7 +196,7 @@ def test_multi_currency(self): "credit", "credit_in_account_currency", ): - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][field], gle[field]) # cancel @@ -263,7 +258,7 @@ def test_reverse_journal_entry(self): "credit", "credit_in_account_currency", ): - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][field], gle[field]) def test_disallow_change_in_account_currency_for_a_party(self): diff --git a/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py b/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py index 992ce9ede5dd..dccd73c62a9c 100644 --- a/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py +++ b/erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py @@ -83,7 +83,10 @@ def test_partial_merge_success(self): "account": "Indirect Income - _TC", "merge_accounts": [ {"account": "Indirect Test Income - _TC", "account_name": "Indirect Test Income"}, - {"account": "Administrative Test Income - _TC", "account_name": "Administrative Test Income"}, + { + "account": "Administrative Test Income - _TC", + "account_name": "Administrative Test Income", + }, ], } ).insert(ignore_permissions=True) diff --git a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py index a134f7466351..8da5a3f909f5 100644 --- a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py +++ b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py @@ -25,13 +25,11 @@ def get_loyalty_details( condition += " and expiry_date>='%s' " % expiry_date loyalty_point_details = frappe.db.sql( - """select sum(loyalty_points) as loyalty_points, + f"""select sum(loyalty_points) as loyalty_points, sum(purchase_amount) as total_spent from `tabLoyalty Point Entry` where customer=%s and loyalty_program=%s and posting_date <= %s {condition} - group by customer""".format( - condition=condition - ), + group by customer""", (customer, loyalty_program, expiry_date), as_dict=1, ) @@ -52,9 +50,7 @@ def get_loyalty_program_details_with_points( include_expired_entry=False, current_transaction_amount=0, ): - lp_details = get_loyalty_program_details( - customer, loyalty_program, company=company, silent=silent - ) + lp_details = get_loyalty_program_details(customer, loyalty_program, company=company, silent=silent) loyalty_program = frappe.get_doc("Loyalty Program", loyalty_program) lp_details.update( get_loyalty_details(customer, loyalty_program.name, expiry_date, company, include_expired_entry) diff --git a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py index 3641ac4428f1..4d21fb698066 100644 --- a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py +++ b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py @@ -19,9 +19,7 @@ def setUpClass(self): create_records() def test_loyalty_points_earned_single_tier(self): - frappe.db.set_value( - "Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty" - ) + frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty") # create a new sales invoice si_original = create_sales_invoice_record() si_original.insert() @@ -69,9 +67,7 @@ def test_loyalty_points_earned_single_tier(self): d.cancel() def test_loyalty_points_earned_multiple_tier(self): - frappe.db.set_value( - "Customer", "Test Loyalty Customer", "loyalty_program", "Test Multiple Loyalty" - ) + frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Multiple Loyalty") # assign multiple tier program to the customer customer = frappe.get_doc("Customer", {"customer_name": "Test Loyalty Customer"}) customer.loyalty_program = frappe.get_doc( @@ -128,9 +124,7 @@ def test_loyalty_points_earned_multiple_tier(self): def test_cancel_sales_invoice(self): """cancelling the sales invoice should cancel the earned points""" - frappe.db.set_value( - "Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty" - ) + frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty") # create a new sales invoice si = create_sales_invoice_record() si.insert() @@ -140,7 +134,7 @@ def test_cancel_sales_invoice(self): "Loyalty Point Entry", {"invoice_type": "Sales Invoice", "invoice": si.name, "customer": si.customer}, ) - self.assertEqual(True, not (lpe is None)) + self.assertEqual(True, lpe is not None) # cancelling sales invoice si.cancel() @@ -148,9 +142,7 @@ def test_cancel_sales_invoice(self): self.assertEqual(True, (lpe is None)) def test_sales_invoice_return(self): - frappe.db.set_value( - "Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty" - ) + frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty") # create a new sales invoice si_original = create_sales_invoice_record(2) si_original.conversion_rate = flt(1) @@ -346,9 +338,7 @@ def create_records(): ).insert() # create item price - if not frappe.db.exists( - "Item Price", {"price_list": "Standard Selling", "item_code": "Loyal Item"} - ): + if not frappe.db.exists("Item Price", {"price_list": "Standard Selling", "item_code": "Loyal Item"}): frappe.get_doc( { "doctype": "Item Price", diff --git a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py index 1d19708eddfc..e5b2e74b4a45 100644 --- a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py +++ b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py @@ -37,9 +37,7 @@ def validate(self): total = sum(flt(d.percentage_allocation) for d in self.get("percentages")) if flt(total, 2) != 100.0: - frappe.throw( - _("Percentage Allocation should be equal to 100%") + " ({0}%)".format(str(flt(total, 2))) - ) + frappe.throw(_("Percentage Allocation should be equal to 100%") + f" ({flt(total, 2)!s}%)") def get_periodwise_distribution_data(distribution_id, period_list, periodicity): diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py index 1e22c64c8f29..d365959c2cd0 100644 --- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py +++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py @@ -83,9 +83,7 @@ def test_opening_sales_invoice_creation_with_missing_debit_account(self): company = "_Test Opening Invoice Company" party_1, party_2 = make_customer("Customer A"), make_customer("Customer B") - old_default_receivable_account = frappe.db.get_value( - "Company", company, "default_receivable_account" - ) + old_default_receivable_account = frappe.db.get_value("Company", company, "default_receivable_account") frappe.db.set_value("Company", company, "default_receivable_account", "") if not frappe.db.exists("Cost Center", "_Test Opening Invoice Company - _TOIC"): @@ -121,9 +119,7 @@ def test_opening_sales_invoice_creation_with_missing_debit_account(self): self.assertTrue(error_log) # teardown - frappe.db.set_value( - "Company", company, "default_receivable_account", old_default_receivable_account - ) + frappe.db.set_value("Company", company, "default_receivable_account", old_default_receivable_account) def test_renaming_of_invoice_using_invoice_number_field(self): company = "_Test Opening Invoice Company" @@ -169,7 +165,7 @@ def get_opening_invoice_creation_dict(**args): { "qty": 1.0, "outstanding_amount": 300, - "party": args.get("party_1") or "_Test {0}".format(party), + "party": args.get("party_1") or f"_Test {party}", "item_name": "Opening Item", "due_date": "2016-09-10", "posting_date": "2016-09-05", @@ -179,7 +175,7 @@ def get_opening_invoice_creation_dict(**args): { "qty": 2.0, "outstanding_amount": 250, - "party": args.get("party_2") or "_Test {0} 1".format(party), + "party": args.get("party_2") or f"_Test {party} 1", "item_name": "Opening Item", "due_date": "2016-09-10", "posting_date": "2016-09-05", diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py index 312cfd2c0a11..d3148c3c4555 100644 --- a/erpnext/accounts/doctype/party_link/party_link.py +++ b/erpnext/accounts/doctype/party_link/party_link.py @@ -24,7 +24,10 @@ def validate(self): if existing_party_link: frappe.throw( _("{} {} is already linked with {} {}").format( - self.primary_role, bold(self.primary_party), self.secondary_role, bold(self.secondary_party) + self.primary_role, + bold(self.primary_party), + self.secondary_role, + bold(self.secondary_party), ) ) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index fefb331ff272..370e1deaa408 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -47,7 +47,7 @@ class InvalidPaymentEntry(ValidationError): class PaymentEntry(AccountsController): def __init__(self, *args, **kwargs): - super(PaymentEntry, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if not self.is_new(): self.setup_party_account_field() @@ -113,7 +113,7 @@ def on_cancel(self): "Unreconcile Payment", "Unreconcile Payment Entries", ) - super(PaymentEntry, self).on_cancel() + super().on_cancel() self.make_gl_entries(cancel=1) self.update_outstanding_amounts() self.update_advance_paid() @@ -221,9 +221,7 @@ def validate_allocated_amount_with_latest_data(self): # If term based allocation is enabled, throw if ( d.payment_term is None or d.payment_term == "" - ) and self.term_based_allocation_enabled_for_reference( - d.reference_doctype, d.reference_name - ): + ) and self.term_based_allocation_enabled_for_reference(d.reference_doctype, d.reference_name): frappe.throw( _( "{0} has Payment Term based allocation enabled. Select a Payment Term for Row #{1} in Payment References section" @@ -235,7 +233,9 @@ def validate_allocated_amount_with_latest_data(self): # The reference has already been fully paid if not latest: frappe.throw( - _("{0} {1} has already been fully paid.").format(_(d.reference_doctype), d.reference_name) + _("{0} {1} has already been fully paid.").format( + _(d.reference_doctype), d.reference_name + ) ) # The reference has already been partly paid elif ( @@ -259,14 +259,14 @@ def validate_allocated_amount_with_latest_data(self): and latest.payment_term_outstanding and (flt(d.allocated_amount) > flt(latest.payment_term_outstanding)) ) - and self.term_based_allocation_enabled_for_reference(d.reference_doctype, d.reference_name) + and self.term_based_allocation_enabled_for_reference( + d.reference_doctype, d.reference_name + ) ): frappe.throw( _( "Row #{0}: Allocated amount:{1} is greater than outstanding amount:{2} for Payment Term {3}" - ).format( - d.idx, d.allocated_amount, latest.payment_term_outstanding, d.payment_term - ) + ).format(d.idx, d.allocated_amount, latest.payment_term_outstanding, d.payment_term) ) if (flt(d.allocated_amount)) > 0 and flt(d.allocated_amount) > flt(latest.outstanding_amount): @@ -343,7 +343,7 @@ def set_missing_ref_details( for d in self.get("references"): if d.allocated_amount: if update_ref_details_only_for and ( - not (d.reference_doctype, d.reference_name) in update_ref_details_only_for + (d.reference_doctype, d.reference_name) not in update_ref_details_only_for ): continue @@ -390,7 +390,9 @@ def set_source_exchange_rate(self, ref_doc=None): else: if ref_doc: if self.paid_from_account_currency == ref_doc.currency: - self.source_exchange_rate = ref_doc.get("exchange_rate") or ref_doc.get("conversion_rate") + self.source_exchange_rate = ref_doc.get("exchange_rate") or ref_doc.get( + "conversion_rate" + ) if not self.source_exchange_rate: self.source_exchange_rate = get_exchange_rate( @@ -427,7 +429,7 @@ def validate_reference_documents(self): if d.reference_doctype not in valid_reference_doctypes: frappe.throw( _("Reference Doctype must be one of {0}").format( - comma_or((_(d) for d in valid_reference_doctypes)) + comma_or(_(d) for d in valid_reference_doctypes) ) ) @@ -450,7 +452,8 @@ def validate_reference_documents(self): if d.reference_doctype in frappe.get_hooks("invoice_doctypes"): if self.party_type == "Customer": ref_party_account = ( - get_party_account_based_on_invoice_discounting(d.reference_name) or ref_doc.debit_to + get_party_account_based_on_invoice_discounting(d.reference_name) + or ref_doc.debit_to ) elif self.party_type == "Supplier": ref_party_account = ref_doc.credit_to @@ -460,7 +463,10 @@ def validate_reference_documents(self): if ref_party_account != self.party_account: frappe.throw( _("{0} {1} is associated with {2}, but Party Account is {3}").format( - _(d.reference_doctype), d.reference_name, ref_party_account, self.party_account + _(d.reference_doctype), + d.reference_name, + ref_party_account, + self.party_account, ) ) @@ -471,7 +477,9 @@ def validate_reference_documents(self): ) if ref_doc.docstatus != 1: - frappe.throw(_("{0} {1} must be submitted").format(_(d.reference_doctype), d.reference_name)) + frappe.throw( + _("{0} {1} must be submitted").format(_(d.reference_doctype), d.reference_name) + ) def get_valid_reference_doctypes(self): if self.party_type == "Customer": @@ -642,9 +650,7 @@ def get_allocated_amount_in_transaction_currency( if not (is_single_currency and reference_is_multi_currency): return allocated_amount - allocated_amount = flt( - allocated_amount / ref_exchange_rate, self.precision("total_allocated_amount") - ) + allocated_amount = flt(allocated_amount / ref_exchange_rate, self.precision("total_allocated_amount")) return allocated_amount @@ -692,7 +698,6 @@ def set_tax_withholding(self): accounts = [] for d in self.taxes: if d.account_head == tax_withholding_details.get("account_head"): - # Preserve user updated included in paid amount if d.included_in_paid_amount: tax_withholding_details.update({"included_in_paid_amount": d.included_in_paid_amount}) @@ -812,7 +817,6 @@ def calculate_base_allocated_amount_for_reference(self, d) -> float: flt(d.allocated_amount) * flt(exchange_rate), self.precision("base_paid_amount") ) else: - # Use source/target exchange rate, so no difference amount is calculated. # then update exchange gain/loss amount in reference table # if there is an exchange gain/loss amount in reference table, submit a JE for that @@ -929,7 +933,9 @@ def validate_payment_against_negative_invoice(self): total_negative_outstanding = flt( sum( - abs(flt(d.outstanding_amount)) for d in self.get("references") if flt(d.outstanding_amount) < 0 + abs(flt(d.outstanding_amount)) + for d in self.get("references") + if flt(d.outstanding_amount) < 0 ), self.references[0].precision("outstanding_amount") if self.references else None, ) @@ -982,7 +988,6 @@ def set_remarks(self): ) ] else: - remarks = [ _("Amount {0} {1} {2} {3}").format( self.party_account_currency, @@ -1002,14 +1007,19 @@ def set_remarks(self): if d.allocated_amount: remarks.append( _("Amount {0} {1} against {2} {3}").format( - self.party_account_currency, d.allocated_amount, d.reference_doctype, d.reference_name + self.party_account_currency, + d.allocated_amount, + d.reference_doctype, + d.reference_name, ) ) for d in self.get("deductions"): if d.amount: remarks.append( - _("Amount {0} {1} deducted against {2}").format(self.company_currency, d.amount, d.account) + _("Amount {0} {1} deducted against {2}").format( + self.company_currency, d.amount, d.account + ) ) self.set("remarks", "\n".join(remarks)) @@ -1444,7 +1454,8 @@ def get_outstanding_reference_documents(args): return [] elif supplier_status["hold_type"] == "Payments": if ( - not supplier_status["release_date"] or getdate(nowdate()) <= supplier_status["release_date"] + not supplier_status["release_date"] + or getdate(nowdate()) <= supplier_status["release_date"] ): return [] @@ -1454,7 +1465,7 @@ def get_outstanding_reference_documents(args): # Get positive outstanding sales /purchase invoices condition = "" if args.get("voucher_type") and args.get("voucher_no"): - condition = " and voucher_type={0} and voucher_no={1}".format( + condition = " and voucher_type={} and voucher_no={}".format( frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]) ) common_filter.append(ple.voucher_type == args["voucher_type"]) @@ -1469,7 +1480,7 @@ def get_outstanding_reference_documents(args): active_dimensions = get_dimensions()[0] for dim in active_dimensions: if args.get(dim.fieldname): - condition += " and {0}='{1}'".format(dim.fieldname, args.get(dim.fieldname)) + condition += f" and {dim.fieldname}='{args.get(dim.fieldname)}'" accounting_dimensions_filter.append(ple[dim.fieldname] == args.get(dim.fieldname)) date_fields_dict = { @@ -1479,21 +1490,21 @@ def get_outstanding_reference_documents(args): for fieldname, date_fields in date_fields_dict.items(): if args.get(date_fields[0]) and args.get(date_fields[1]): - condition += " and {0} between '{1}' and '{2}'".format( + condition += " and {} between '{}' and '{}'".format( fieldname, args.get(date_fields[0]), args.get(date_fields[1]) ) posting_and_due_date.append(ple[fieldname][args.get(date_fields[0]) : args.get(date_fields[1])]) elif args.get(date_fields[0]): # if only from date is supplied - condition += " and {0} >= '{1}'".format(fieldname, args.get(date_fields[0])) + condition += f" and {fieldname} >= '{args.get(date_fields[0])}'" posting_and_due_date.append(ple[fieldname].gte(args.get(date_fields[0]))) elif args.get(date_fields[1]): # if only to date is supplied - condition += " and {0} <= '{1}'".format(fieldname, args.get(date_fields[1])) + condition += f" and {fieldname} <= '{args.get(date_fields[1])}'" posting_and_due_date.append(ple[fieldname].lte(args.get(date_fields[1]))) if args.get("company"): - condition += " and company = {0}".format(frappe.db.escape(args.get("company"))) + condition += " and company = {}".format(frappe.db.escape(args.get("company"))) common_filter.append(ple.company == args.get("company")) outstanding_invoices = [] @@ -1565,9 +1576,7 @@ def get_outstanding_reference_documents(args): frappe.msgprint( _( "No outstanding {0} found for the {1} {2} which qualify the filters you have specified." - ).format( - _(ref_document_type), _(args.get("party_type")).lower(), frappe.bold(args.get("party")) - ) + ).format(_(ref_document_type), _(args.get("party_type")).lower(), frappe.bold(args.get("party"))) ) return data @@ -1603,12 +1612,10 @@ def split_invoices_based_on_payment_terms(outstanding_invoices, company) -> list return outstanding_invoices_after_split -def get_currency_data(outstanding_invoices: list, company: str = None) -> dict: +def get_currency_data(outstanding_invoices: list, company: str | None = None) -> dict: """Get currency and conversion data for a list of invoices.""" exc_rates = frappe._dict() - company_currency = ( - frappe.db.get_value("Company", company, "default_currency") if company else None - ) + company_currency = frappe.db.get_value("Company", company, "default_currency") if company else None for doctype in ["Sales Invoice", "Purchase Invoice"]: invoices = [x.voucher_no for x in outstanding_invoices if x.voucher_type == doctype] @@ -1703,7 +1710,7 @@ def get_orders_to_be_billed( active_dimensions = get_dimensions()[0] for dim in active_dimensions: if filters.get(dim.fieldname): - condition += " and {0}='{1}'".format(dim.fieldname, filters.get(dim.fieldname)) + condition += f" and {dim.fieldname}='{filters.get(dim.fieldname)}'" if party_account_currency == company_currency: grand_total_field = "base_grand_total" @@ -1852,18 +1859,14 @@ def get_account_details(account, date, cost_center=None): frappe.has_permission("Payment Entry", throw=True) # to check if the passed account is accessible under reference doctype Payment Entry - account_list = frappe.get_list( - "Account", {"name": account}, reference_doctype="Payment Entry", limit=1 - ) + account_list = frappe.get_list("Account", {"name": account}, reference_doctype="Payment Entry", limit=1) # There might be some user permissions which will allow account under certain doctypes # except for Payment Entry, only in such case we should throw permission error if not account_list: frappe.throw(_("Account: {0} is not permitted under Payment Entry").format(account)) - account_balance = get_balance_on( - account, date, cost_center=cost_center, ignore_account_permission=True - ) + account_balance = get_balance_on(account, date, cost_center=cost_center, ignore_account_permission=True) return frappe._dict( { @@ -1910,9 +1913,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre total_amount = outstanding_amount = exchange_rate = None ref_doc = frappe.get_doc(reference_doctype, reference_name) - company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency( - ref_doc.company - ) + company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(ref_doc.company) if reference_doctype == "Dunning": total_amount = outstanding_amount = ref_doc.get("dunning_amount") @@ -1921,9 +1922,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1: total_amount = ref_doc.get("total_amount") if ref_doc.multi_currency: - exchange_rate = get_exchange_rate( - party_account_currency, company_currency, ref_doc.posting_date - ) + exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date) else: exchange_rate = 1 outstanding_amount = get_outstanding_on_journal_entry(reference_name) @@ -1981,9 +1980,7 @@ def get_payment_entry( ): doc = frappe.get_doc(dt, dn) over_billing_allowance = frappe.db.get_single_value("Accounts Settings", "over_billing_allowance") - if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= ( - 100.0 + over_billing_allowance - ): + if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= (100.0 + over_billing_allowance): frappe.throw(_("Can only make payment against unbilled {0}").format(_(dt))) if not party_type: @@ -2036,9 +2033,7 @@ def get_payment_entry( pe.paid_from_account_currency = ( party_account_currency if payment_type == "Receive" else bank.account_currency ) - pe.paid_to_account_currency = ( - party_account_currency if payment_type == "Pay" else bank.account_currency - ) + pe.paid_to_account_currency = party_account_currency if payment_type == "Pay" else bank.account_currency pe.paid_amount = paid_amount pe.received_amount = received_amount pe.letter_head = doc.get("letter_head") @@ -2067,7 +2062,6 @@ def get_payment_entry( {"name": doc.payment_terms_template}, "allocate_payment_based_on_payment_terms", ): - for reference in get_reference_as_per_payment_terms( doc.payment_schedule, dt, dn, doc, grand_total, outstanding_amount, party_account_currency ): @@ -2188,9 +2182,9 @@ def set_party_account_currency(dt, party_account, doc): def set_payment_type(dt, doc): - if ( - dt == "Sales Order" or (dt in ("Sales Invoice", "Dunning") and doc.outstanding_amount > 0) - ) or (dt == "Purchase Invoice" and doc.outstanding_amount < 0): + if (dt == "Sales Order" or (dt in ("Sales Invoice", "Dunning") and doc.outstanding_amount > 0)) or ( + dt == "Purchase Invoice" and doc.outstanding_amount < 0 + ): payment_type = "Receive" else: payment_type = "Pay" @@ -2250,9 +2244,7 @@ def set_paid_amount_and_received_amount( return paid_amount, received_amount -def apply_early_payment_discount( - paid_amount, received_amount, doc, party_account_currency, reference_date -): +def apply_early_payment_discount(paid_amount, received_amount, doc, party_account_currency, reference_date): total_discount = 0 valid_discounts = [] eligible_for_payments = ["Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"] @@ -2262,7 +2254,6 @@ def apply_early_payment_discount( if doc.doctype in eligible_for_payments and has_payment_schedule: for term in doc.payment_schedule: if not term.discounted_amount and term.discount and reference_date <= term.discount_date: - if term.discount_type == "Percentage": grand_total = doc.get("grand_total") if is_multi_currency else doc.get("base_grand_total") discount_amount = flt(grand_total) * (term.discount / 100) @@ -2291,9 +2282,7 @@ def apply_early_payment_discount( return paid_amount, received_amount, total_discount, valid_discounts -def set_pending_discount_loss( - pe, doc, discount_amount, base_total_discount_loss, party_account_currency -): +def set_pending_discount_loss(pe, doc, discount_amount, base_total_discount_loss, party_account_currency): # If multi-currency, get base discount amount to adjust with base currency deductions/losses if party_account_currency != doc.company_currency: discount_amount = discount_amount * doc.get("conversion_rate", 1) @@ -2313,7 +2302,8 @@ def set_pending_discount_loss( pe.set_gain_or_loss( account_details={ "account": frappe.get_cached_value("Company", pe.company, account_type), - "cost_center": pe.cost_center or frappe.get_cached_value("Company", pe.company, "cost_center"), + "cost_center": pe.cost_center + or frappe.get_cached_value("Company", pe.company, "cost_center"), "amount": discount_amount * positive_negative, } ) @@ -2336,9 +2326,7 @@ def split_early_payment_discount_loss(pe, doc, valid_discounts) -> float: def get_total_discount_percent(doc, valid_discounts) -> float: """Get total percentage and amount discount applied as a percentage.""" total_discount_percent = ( - sum( - discount.get("discount") for discount in valid_discounts if discount.get("type") == "Percentage" - ) + sum(discount.get("discount") for discount in valid_discounts if discount.get("type") == "Percentage") or 0.0 ) @@ -2381,9 +2369,7 @@ def add_tax_discount_loss(pe, doc, total_discount_percentage) -> float: # The same account head could be used more than once for tax in doc.get("taxes", []): - base_tax_loss = tax.get("base_tax_amount_after_discount_amount") * ( - total_discount_percentage / 100 - ) + base_tax_loss = tax.get("base_tax_amount_after_discount_amount") * (total_discount_percentage / 100) account = tax.get("account_head") if not tax_discount_loss.get(account): @@ -2400,7 +2386,8 @@ def add_tax_discount_loss(pe, doc, total_discount_percentage) -> float: "deductions", { "account": account, - "cost_center": pe.cost_center or frappe.get_cached_value("Company", pe.company, "cost_center"), + "cost_center": pe.cost_center + or frappe.get_cached_value("Company", pe.company, "cost_center"), "amount": flt(loss, precision), }, ) @@ -2423,7 +2410,8 @@ def get_reference_as_per_payment_terms( if not is_multi_currency_acc: # If accounting is done in company currency for multi-currency transaction payment_term_outstanding = flt( - payment_term_outstanding * doc.get("conversion_rate"), payment_term.precision("payment_amount") + payment_term_outstanding * doc.get("conversion_rate"), + payment_term.precision("payment_amount"), ) if payment_term_outstanding: @@ -2451,7 +2439,7 @@ def get_paid_amount(dt, dn, party_type, party, account, due_date): dr_or_cr = "debit_in_account_currency - credit_in_account_currency" paid_amount = frappe.db.sql( - """ + f""" select ifnull(sum({dr_or_cr}), 0) as paid_amount from `tabGL Entry` where against_voucher_type = %s @@ -2461,9 +2449,7 @@ def get_paid_amount(dt, dn, party_type, party, account, due_date): and account = %s and due_date = %s and {dr_or_cr} > 0 - """.format( - dr_or_cr=dr_or_cr - ), + """, (dt, dn, party_type, party, account, due_date), ) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index d035149ff93d..ec3b4196bdec 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -2,7 +2,6 @@ # See license.txt import json -import unittest import frappe from frappe import qb @@ -470,9 +469,7 @@ def test_payment_entry_multicurrency_accounting_si_with_early_payment_discount(s si.save() si.submit() - pe = get_payment_entry( - "Sales Invoice", si.name, bank_account="_Test Bank - _TC", bank_amount=4700 - ) + pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC", bank_amount=4700) pe.reference_no = si.name pe.reference_date = nowdate() @@ -639,9 +636,7 @@ def test_payment_entry_retrieves_last_exchange_rate(self): pe.set_exchange_rate() pe.set_amounts() - self.assertEqual( - pe.source_exchange_rate, 65.1, "{0} is not equal to {1}".format(pe.source_exchange_rate, 65.1) - ) + self.assertEqual(pe.source_exchange_rate, 65.1, f"{pe.source_exchange_rate} is not equal to {65.1}") def test_internal_transfer_usd_to_inr(self): pe = frappe.new_doc("Payment Entry") @@ -910,9 +905,7 @@ def test_payment_entry_against_purchase_invoice_with_cost_center(self): cost_center = "_Test Cost Center for BS Account - _TC" create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company") - pi = make_purchase_invoice_against_cost_center( - cost_center=cost_center, credit_to="Creditors - _TC" - ) + pi = make_purchase_invoice_against_cost_center(cost_center=cost_center, credit_to="Creditors - _TC") pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC") self.assertEqual(pe.cost_center, pi.cost_center) @@ -953,9 +946,7 @@ def test_payment_entry_account_and_party_balance_with_cost_center(self): si = create_sales_invoice_against_cost_center(cost_center=cost_center, debit_to="Debtors - _TC") account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=si.cost_center) - party_balance = get_balance_on( - party_type="Customer", party=si.customer, cost_center=si.cost_center - ) + party_balance = get_balance_on(party_type="Customer", party=si.customer, cost_center=si.cost_center) party_account_balance = get_balance_on(si.debit_to, cost_center=si.cost_center) pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC") @@ -1214,7 +1205,7 @@ def test_overallocation_validation_shouldnt_misfire(self): Overallocation validation shouldn't fire for Template without "Allocate Payment based on Payment Terms" enabled """ - customer = create_customer() + create_customer() create_payment_terms_template() template = frappe.get_doc("Payment Terms Template", "Test Receivable Template") @@ -1273,9 +1264,7 @@ def test_outstanding_invoices_api(self): create_payment_terms_template() # SI has an earlier due date and SI2 has a later due date - si = create_sales_invoice( - qty=1, rate=100, customer=customer, posting_date=add_days(nowdate(), -4) - ) + si = create_sales_invoice(qty=1, rate=100, customer=customer, posting_date=add_days(nowdate(), -4)) si2 = create_sales_invoice(do_not_save=1, qty=1, rate=100, customer=customer) si2.payment_terms_template = "Test Receivable Template" si2.submit() @@ -1401,12 +1390,11 @@ def create_payment_entry(**args): def create_payment_terms_template(): - create_payment_term("Basic Amount Receivable") create_payment_term("Tax Receivable") if not frappe.db.exists("Payment Terms Template", "Test Receivable Template"): - payment_term_template = frappe.get_doc( + frappe.get_doc( { "doctype": "Payment Terms Template", "template_name": "Test Receivable Template", 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 bd438ee76063..8be3d76474ff 100644 --- a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py +++ b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.py @@ -108,9 +108,9 @@ def validate_dimensions_for_pl_and_bs(self): ): if not self.get(dimension.fieldname): frappe.throw( - _("Accounting Dimension {0} is required for 'Profit and Loss' account {1}.").format( - dimension.label, self.account - ) + _( + "Accounting Dimension {0} is required for 'Profit and Loss' account {1}." + ).format(dimension.label, self.account) ) if ( @@ -121,9 +121,9 @@ def validate_dimensions_for_pl_and_bs(self): ): if not self.get(dimension.fieldname): frappe.throw( - _("Accounting Dimension {0} is required for 'Balance Sheet' account {1}.").format( - dimension.label, self.account - ) + _( + "Accounting Dimension {0} is required for 'Balance Sheet' account {1}." + ).format(dimension.label, self.account) ) def validate(self): diff --git a/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py b/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py index ce9579ed613e..c867e68d1a6f 100644 --- a/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py +++ b/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py @@ -159,9 +159,7 @@ def clear_old_entries(self): for doctype in doctype_list: qb.from_(qb.DocType(doctype)).delete().where(qb.DocType(doctype).company == self.company).run() - def create_journal_entry( - self, acc1=None, acc2=None, amount=0, posting_date=None, cost_center=None - ): + def create_journal_entry(self, acc1=None, acc2=None, amount=0, posting_date=None, cost_center=None): je = frappe.new_doc("Journal Entry") je.posting_date = posting_date or nowdate() je.company = self.company @@ -319,9 +317,7 @@ def test_cr_note_against_invoice(self): ple.amount, ple.delinked, ) - .where( - (ple.against_voucher_type == cr_note1.doctype) & (ple.against_voucher_no == cr_note1.name) - ) + .where((ple.against_voucher_type == cr_note1.doctype) & (ple.against_voucher_no == cr_note1.name)) .orderby(ple.creation) .run(as_dict=True) ) @@ -362,9 +358,7 @@ def test_je_against_inv_and_note(self): ) cr_note2.is_return = 1 cr_note2 = cr_note2.save().submit() - je1 = self.create_journal_entry( - self.debit_to, self.debit_to, amount, posting_date=transaction_date - ) + je1 = self.create_journal_entry(self.debit_to, self.debit_to, amount, posting_date=transaction_date) je1.get("accounts")[0].party_type = je1.get("accounts")[1].party_type = "Customer" je1.get("accounts")[0].party = je1.get("accounts")[1].party = self.customer je1.get("accounts")[0].reference_type = cr_note2.doctype @@ -419,9 +413,7 @@ def test_je_against_inv_and_note(self): ple.amount, ple.delinked, ) - .where( - (ple.against_voucher_type == cr_note2.doctype) & (ple.against_voucher_no == cr_note2.name) - ) + .where((ple.against_voucher_type == cr_note2.doctype) & (ple.against_voucher_no == cr_note2.name)) .orderby(ple.creation) .run(as_dict=True) ) @@ -518,7 +510,7 @@ def test_advance_payment_unlink_on_order_cancellation(self): amount = 100 so = self.create_sales_order(qty=1, rate=amount, posting_date=transaction_date).save().submit() - pe = get_payment_entry(so.doctype, so.name).save().submit() + get_payment_entry(so.doctype, so.name).save().submit() so.reload() so.cancel() diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py index ff9615d14fc6..dde9b094c011 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.py +++ b/erpnext/accounts/doctype/payment_order/payment_order.py @@ -66,9 +66,7 @@ def make_journal_entry(doc, supplier, mode_of_payment=None): je = frappe.new_doc("Journal Entry") je.payment_order = doc.name je.posting_date = nowdate() - mode_of_payment_type = frappe._dict( - frappe.get_all("Mode of Payment", fields=["name", "type"], as_list=1) - ) + mode_of_payment_type = frappe._dict(frappe.get_all("Mode of Payment", fields=["name", "type"], as_list=1)) je.voucher_type = "Bank Entry" if mode_of_payment and mode_of_payment_type.get(mode_of_payment) == "Cash": diff --git a/erpnext/accounts/doctype/payment_order/test_payment_order.py b/erpnext/accounts/doctype/payment_order/test_payment_order.py index 60f288e1f070..7af096647ca7 100644 --- a/erpnext/accounts/doctype/payment_order/test_payment_order.py +++ b/erpnext/accounts/doctype/payment_order/test_payment_order.py @@ -1,7 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.tests.utils import FrappeTestCase @@ -41,9 +40,7 @@ def test_payment_order_creation_against_payment_entry(self): payment_entry.insert() payment_entry.submit() - doc = create_payment_order_against_payment_entry( - payment_entry, "Payment Entry", self.bank_account - ) + doc = create_payment_order_against_payment_entry(payment_entry, "Payment Entry", self.bank_account) reference_doc = doc.get("references")[0] self.assertEqual(reference_doc.reference_name, payment_entry.name) self.assertEqual(reference_doc.reference_doctype, "Payment Entry") diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 33f736fe915f..b03475149054 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -25,7 +25,7 @@ class PaymentReconciliation(Document): def __init__(self, *args, **kwargs): - super(PaymentReconciliation, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.common_filter_conditions = [] self.accounting_dimension_filter_conditions = [] self.ple_posting_date_filter = [] @@ -219,7 +219,6 @@ def get_return_invoices(self): self.return_invoices = self.return_invoices_query.run(as_dict=True) def get_dr_or_cr_notes(self): - self.build_qb_filter_conditions(get_return_invoices=True) ple = qb.DocType("Payment Ledger Entry") @@ -340,9 +339,7 @@ def calculate_difference_on_allocation_change(self, payment_entry, invoice, allo payment_entry[0].get("reference_name") ) - new_difference_amount = self.get_difference_amount( - payment_entry[0], invoice[0], allocated_amount - ) + new_difference_amount = self.get_difference_amount(payment_entry[0], invoice[0], allocated_amount) return new_difference_amount @frappe.whitelist() @@ -460,9 +457,9 @@ def reconcile(self): if running_doc: frappe.throw( - _("A Reconciliation Job {0} is running for the same filters. Cannot reconcile now").format( - get_link_to_form("Auto Reconcile", running_doc) - ) + _( + "A Reconciliation Job {0} is running for the same filters. Cannot reconcile now" + ).format(get_link_to_form("Auto Reconcile", running_doc)) ) return @@ -555,9 +552,7 @@ def get_invoice_exchange_map(self, invoices, payments): invoice_exchange_map.update(purchase_invoice_map) - journals = [ - d.get("invoice_number") for d in invoices if d.get("invoice_type") == "Journal Entry" - ] + journals = [d.get("invoice_number") for d in invoices if d.get("invoice_type") == "Journal Entry"] journals.extend( [d.get("reference_name") for d in payments if d.get("reference_type") == "Journal Entry"] ) @@ -677,7 +672,7 @@ def get_payment_entry_conditions(self): def get_journal_filter_conditions(self): conditions = [] je = qb.DocType("Journal Entry") - jea = qb.DocType("Journal Entry Account") + qb.DocType("Journal Entry Account") conditions.append(je.company == self.company) if self.from_payment_date: @@ -797,7 +792,7 @@ def adjust_allocations_for_taxes(doc): @frappe.whitelist() -def get_queries_for_dimension_filters(company: str = None): +def get_queries_for_dimension_filters(company: str | None = None): dimensions_with_filters = [] for d in get_dimensions()[0]: filters = {} diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index 662077d027eb..25525a483e29 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe import qb @@ -250,9 +249,7 @@ def create_payment_reconciliation(self, party_is_customer=True): pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate() return pr - def create_journal_entry( - self, acc1=None, acc2=None, amount=0, posting_date=None, cost_center=None - ): + def create_journal_entry(self, acc1=None, acc2=None, amount=0, posting_date=None, cost_center=None): je = frappe.new_doc("Journal Entry") je.posting_date = posting_date or nowdate() je.company = self.company @@ -402,7 +399,7 @@ def test_filter_invoice_limit(self): rate = 100 invoices = [] payments = [] - for i in range(5): + for _i in range(5): invoices.append(self.create_sales_invoice(qty=1, rate=rate, posting_date=transaction_date)) pe = self.create_payment_entry(amount=rate, posting_date=transaction_date).save().submit() payments.append(pe) @@ -821,9 +818,7 @@ def test_pr_output_foreign_currency_and_amount(self): cr_note.cancel() - pay = self.create_payment_entry( - amount=amount, posting_date=transaction_date, customer=self.customer3 - ) + pay = self.create_payment_entry(amount=amount, posting_date=transaction_date, customer=self.customer3) pay.paid_from = self.debtors_eur pay.paid_from_account_currency = "EUR" pay.source_exchange_rate = exchange_rate @@ -1025,9 +1020,7 @@ def test_cost_center_filter_on_vouchers(self): rate = 100 # 'Main - PR' Cost Center - si1 = self.create_sales_invoice( - qty=1, rate=rate, posting_date=transaction_date, do_not_submit=True - ) + si1 = self.create_sales_invoice(qty=1, rate=rate, posting_date=transaction_date, do_not_submit=True) si1.cost_center = self.main_cc.name si1.submit() @@ -1043,9 +1036,7 @@ def test_cost_center_filter_on_vouchers(self): je1 = je1.save().submit() # 'Sub - PR' Cost Center - si2 = self.create_sales_invoice( - qty=1, rate=rate, posting_date=transaction_date, do_not_submit=True - ) + si2 = self.create_sales_invoice(qty=1, rate=rate, posting_date=transaction_date, do_not_submit=True) si2.cost_center = self.sub_cc.name si2.submit() diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index f6653f87f0f9..3291bcb26124 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -50,7 +50,7 @@ def validate_payment_request_amount(self): ) ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) - if not hasattr(ref_doc, "order_type") or getattr(ref_doc, "order_type") != "Shopping Cart": + if not hasattr(ref_doc, "order_type") or ref_doc.order_type != "Shopping Cart": ref_amount = get_amount(ref_doc, self.payment_account) if existing_payment_request_amount + flt(self.grand_total) > ref_amount: @@ -103,7 +103,7 @@ def on_submit(self): ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) if ( - hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart" + hasattr(ref_doc, "order_type") and ref_doc.order_type == "Shopping Cart" ) or self.flags.mute_email: send_mail = False @@ -155,7 +155,7 @@ def on_cancel(self): def make_invoice(self): ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) - if hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart": + if hasattr(ref_doc, "order_type") and ref_doc.order_type == "Shopping Cart": from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice si = make_sales_invoice(self.reference_name, ignore_permissions=True) @@ -241,14 +241,10 @@ def create_payment_entry(self, submit=True): else: party_account = get_party_account("Customer", ref_doc.get("customer"), ref_doc.company) - party_account_currency = ref_doc.get("party_account_currency") or get_account_currency( - party_account - ) + party_account_currency = ref_doc.get("party_account_currency") or get_account_currency(party_account) bank_amount = self.grand_total - if ( - party_account_currency == ref_doc.company_currency and party_account_currency != self.currency - ): + if party_account_currency == ref_doc.company_currency and party_account_currency != self.currency: party_amount = ref_doc.get("base_rounded_total") or ref_doc.get("base_grand_total") else: party_amount = self.grand_total @@ -266,7 +262,7 @@ def create_payment_entry(self, submit=True): "mode_of_payment": self.mode_of_payment, "reference_no": self.name, "reference_date": nowdate(), - "remarks": "Payment Entry against {0} {1} via Payment Request {2}".format( + "remarks": "Payment Entry against {} {} via Payment Request {}".format( self.reference_doctype, self.reference_name, self.name ), } @@ -380,14 +376,13 @@ def on_payment_authorized(self, status=None): and hasattr(frappe.local, "session") and frappe.local.session.user != "Guest" ) and self.payment_channel != "Phone": - success_url = shopping_cart_settings.payment_success_url if success_url: redirect_to = ({"Orders": "/orders", "Invoices": "/invoices", "My Account": "/me"}).get( success_url, "/me" ) else: - redirect_to = get_url("/orders/{0}".format(self.reference_name)) + redirect_to = get_url(f"/orders/{self.reference_name}") return redirect_to @@ -413,15 +408,11 @@ def make_payment_request(**args): frappe.db.set_value( "Sales Order", args.dn, "loyalty_points", int(args.loyalty_points), update_modified=False ) - frappe.db.set_value( - "Sales Order", args.dn, "loyalty_amount", loyalty_amount, update_modified=False - ) + frappe.db.set_value("Sales Order", args.dn, "loyalty_amount", loyalty_amount, update_modified=False) grand_total = grand_total - loyalty_amount bank_account = ( - get_party_bank_account(args.get("party_type"), args.get("party")) - if args.get("party_type") - else "" + get_party_bank_account(args.get("party_type"), args.get("party")) if args.get("party_type") else "" ) draft_payment_request = frappe.db.get_value( diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py index feb2fdffc95b..70de886ba4da 100644 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.py +++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py @@ -93,7 +93,7 @@ def test_payment_entry_against_purchase_invoice(self): return_doc=1, ) - pe = pr.create_payment_entry() + pr.create_payment_entry() pr.load_from_db() self.assertEqual(pr.status, "Paid") @@ -158,7 +158,7 @@ def test_payment_entry(self): self.assertTrue(gl_entries) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_gle[gle.account][0], gle.account) self.assertEqual(expected_gle[gle.account][1], gle.debit) self.assertEqual(expected_gle[gle.account][2], gle.credit) 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 7b04a68e89af..3cb1d87f13ac 100644 --- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py +++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py @@ -19,9 +19,7 @@ def validate_invoice_portion(self): total_portion += flt(term.get("invoice_portion", 0)) if flt(total_portion, 2) != 100.00: - frappe.msgprint( - _("Combined invoice portion must equal 100%"), raise_exception=1, indicator="red" - ) + frappe.msgprint(_("Combined invoice portion must equal 100%"), raise_exception=1, indicator="red") def validate_terms(self): terms = [] 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 88a2ca575ac5..c6ccb52f86d5 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -47,7 +47,8 @@ def on_cancel(self): enqueue_after_commit=True, ) frappe.msgprint( - _("The GL Entries will be cancelled in the background, it can take a few minutes."), alert=True + _("The GL Entries will be cancelled in the background, it can take a few minutes."), + alert=True, ) else: make_reverse_gl_entries(voucher_type="Period Closing Voucher", voucher_no=self.name) @@ -89,9 +90,7 @@ def validate_posting_date(self): self.posting_date, self.fiscal_year, self.company, label=_("Posting Date"), doc=self ) - self.year_start_date = get_fiscal_year( - self.posting_date, self.fiscal_year, company=self.company - )[1] + self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year, company=self.company)[1] self.check_if_previous_year_closed() @@ -205,7 +204,9 @@ def get_gle_for_pl_account(self, acc): "credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0, - "credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0, + "credit": abs(flt(acc.bal_in_company_currency)) + if flt(acc.bal_in_company_currency) > 0 + else 0, "is_period_closing_voucher_entry": 1, }, item=acc, @@ -229,7 +230,9 @@ def get_gle_for_closing_account(self, acc): "credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0, - "credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0, + "credit": abs(flt(acc.bal_in_company_currency)) + if flt(acc.bal_in_company_currency) < 0 + else 0, "is_period_closing_voucher_entry": 1, }, item=acc, 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 115b415eedad..f61bfdb58ab5 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py @@ -33,7 +33,7 @@ def validate_duplicate_pos_invoices(self): for key, value in pos_occurences.items(): if len(value) > 1: error_list.append( - _("{} is added multiple times on rows: {}".format(frappe.bold(key), frappe.bold(value))) + _(f"{frappe.bold(key)} is added multiple times on rows: {frappe.bold(value)}") ) if error_list: @@ -128,9 +128,7 @@ def get_pos_invoices(start, end, pos_profile, user): as_dict=1, ) - data = list( - filter(lambda d: get_datetime(start) <= get_datetime(d.timestamp) <= get_datetime(end), data) - ) + data = list(filter(lambda d: get_datetime(start) <= get_datetime(d.timestamp) <= get_datetime(end), data)) # need to get taxes and payments so can't avoid get_doc data = [frappe.get_doc("POS Invoice", d.name).as_dict() for d in data] @@ -201,7 +199,11 @@ def make_closing_entry_from_opening(opening_entry): else: payments.append( frappe._dict( - {"mode_of_payment": p.mode_of_payment, "opening_amount": 0, "expected_amount": p.amount} + { + "mode_of_payment": p.mode_of_payment, + "opening_amount": 0, + "expected_amount": p.amount, + } ) ) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 383b9dab24a2..4abe91680e89 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -27,7 +27,7 @@ class POSInvoice(SalesInvoice): def __init__(self, *args, **kwargs): - super(POSInvoice, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def validate(self): if not cint(self.is_pos): @@ -129,7 +129,9 @@ def check_phone_payments(self): ) if paid_amt and pay.amount != paid_amt: - return frappe.throw(_("Payment related to {0} is not completed").format(pay.mode_of_payment)) + return frappe.throw( + _("Payment related to {0} is not completed").format(pay.mode_of_payment) + ) def validate_pos_reserved_serial_nos(self, item): serial_nos = get_serial_nos(item.serial_no) @@ -164,7 +166,7 @@ def validate_duplicate_serial_no(self): serial_nos = row.serial_no.split("\n") if serial_nos: - for key, value in collections.Counter(serial_nos).items(): + for _key, value in collections.Counter(serial_nos).items(): if value > 1: frappe.throw(_("Duplicate Serial No {0} found").format("key")) @@ -191,9 +193,7 @@ def validate_pos_reserved_batch_qty(self, item): frappe.throw( _( "Row #{}: Batch No. {} of item {} has less than required stock available, {} more required" - ).format( - item.idx, bold_invalid_batch_no, bold_item_name, bold_extra_batch_qty_needed - ), + ).format(item.idx, bold_invalid_batch_no, bold_item_name, bold_extra_batch_qty_needed), title=_("Item Unavailable"), ) @@ -249,7 +249,7 @@ def validate_stock_availablility(self): available_stock, is_stock_item = get_stock_availability(d.item_code, d.warehouse) - item_code, warehouse, qty = ( + item_code, warehouse, _qty = ( frappe.bold(d.item_code), frappe.bold(d.warehouse), frappe.bold(d.qty), diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index bd2fee3b0ad9..186c0ea7fd46 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -338,9 +338,7 @@ def test_pos_change_amount(self): ) pos.set("payments", []) - pos.append( - "payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 50} - ) + pos.append("payments", {"mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": 50}) pos.append( "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 60, "default": 1} ) @@ -594,9 +592,7 @@ def test_loyalty_points(self): from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records create_records() - frappe.db.set_value( - "Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty" - ) + frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty") before_lp_details = get_loyalty_program_details_with_points( "Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty" ) @@ -670,9 +666,7 @@ def test_merging_into_sales_invoice_with_discount(self): consolidate_pos_invoices() pos_inv.load_from_db() - rounded_total = frappe.db.get_value( - "Sales Invoice", pos_inv.consolidated_invoice, "rounded_total" - ) + rounded_total = frappe.db.get_value("Sales Invoice", pos_inv.consolidated_invoice, "rounded_total") self.assertEqual(rounded_total, 3470) def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self): @@ -719,9 +713,7 @@ def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self): consolidate_pos_invoices() pos_inv.load_from_db() - rounded_total = frappe.db.get_value( - "Sales Invoice", pos_inv.consolidated_invoice, "rounded_total" - ) + rounded_total = frappe.db.get_value("Sales Invoice", pos_inv.consolidated_invoice, "rounded_total") self.assertEqual(rounded_total, 840) def test_merging_with_validate_selling_price(self): @@ -773,9 +765,7 @@ def test_merging_with_validate_selling_price(self): consolidate_pos_invoices() pos_inv2.load_from_db() - rounded_total = frappe.db.get_value( - "Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total" - ) + rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total") self.assertEqual(rounded_total, 400) def test_pos_batch_item_qty_validation(self): @@ -839,19 +829,19 @@ def test_ignore_pricing_rule(self): pos_inv = create_pos_invoice(qty=1, do_not_submit=1) pos_inv.items[0].rate = 300 pos_inv.save() - self.assertEquals(pos_inv.items[0].discount_percentage, 10) + self.assertEqual(pos_inv.items[0].discount_percentage, 10) # rate shouldn't change - self.assertEquals(pos_inv.items[0].rate, 405) + self.assertEqual(pos_inv.items[0].rate, 405) pos_inv.ignore_pricing_rule = 1 pos_inv.save() - self.assertEquals(pos_inv.ignore_pricing_rule, 1) + self.assertEqual(pos_inv.ignore_pricing_rule, 1) # rate should reset since pricing rules are ignored - self.assertEquals(pos_inv.items[0].rate, 450) + self.assertEqual(pos_inv.items[0].rate, 450) pos_inv.items[0].rate = 300 pos_inv.save() - self.assertEquals(pos_inv.items[0].rate, 300) + self.assertEqual(pos_inv.items[0].rate, 300) finally: item_price.delete() @@ -874,7 +864,7 @@ def test_delivered_serial_no_case(self): dn = create_delivery_note(item_code="_Test Serialized Item With Series", serial_no=serial_no) delivery_document_no = frappe.db.get_value("Serial No", serial_no, "delivery_document_no") - self.assertEquals(delivery_document_no, dn.name) + self.assertEqual(delivery_document_no, dn.name) init_user_and_profile() 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 438ff9f3c4c1..5b0d1cfa8ce8 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 @@ -29,7 +29,7 @@ def validate_duplicate_pos_invoices(self): for key, value in pos_occurences.items(): if len(value) > 1: error_list.append( - _("{} is added multiple times on rows: {}".format(frappe.bold(key), frappe.bold(value))) + _(f"{frappe.bold(key)} is added multiple times on rows: {frappe.bold(value)}") ) if error_list: @@ -56,7 +56,9 @@ def validate_pos_invoice_status(self): bold_pos_invoice = frappe.bold(d.pos_invoice) bold_status = frappe.bold(status) if docstatus != 1: - frappe.throw(_("Row #{}: POS Invoice {} is not submitted yet").format(d.idx, bold_pos_invoice)) + frappe.throw( + _("Row #{}: POS Invoice {} is not submitted yet").format(d.idx, bold_pos_invoice) + ) if status == "Consolidated": frappe.throw( _("Row #{}: POS Invoice {} has been {}").format(d.idx, bold_pos_invoice, bold_status) @@ -75,15 +77,17 @@ def validate_pos_invoice_status(self): d.idx, bold_return_against, bold_pos_invoice, bold_unconsolidated ) msg += " " - msg += _("Original invoice should be consolidated before or along with the return invoice.") + msg += _( + "Original invoice should be consolidated before or along with the return invoice." + ) msg += "

" - msg += _("You can add original invoice {} manually to proceed.").format(bold_return_against) + msg += _("You can add original invoice {} manually to proceed.").format( + bold_return_against + ) frappe.throw(msg) def on_submit(self): - pos_invoice_docs = [ - frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices - ] + pos_invoice_docs = [frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices] returns = [d for d in pos_invoice_docs if d.get("is_return") == 1] sales = [d for d in pos_invoice_docs if d.get("is_return") == 0] @@ -100,9 +104,7 @@ def on_submit(self): self.update_pos_invoices(pos_invoice_docs, sales_invoice, credit_note) def on_cancel(self): - pos_invoice_docs = [ - frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices - ] + pos_invoice_docs = [frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices] self.update_pos_invoices(pos_invoice_docs) self.cancel_linked_invoices() @@ -192,7 +194,9 @@ def merge_pos_invoice_into(self, invoice, data): for t in taxes: if t.account_head == tax.account_head and t.cost_center == tax.cost_center: t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount_after_discount_amount) - t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount_after_discount_amount) + t.base_tax_amount = flt(t.base_tax_amount) + flt( + tax.base_tax_amount_after_discount_amount + ) update_item_wise_tax_detail(t, tax) found = True if not found: @@ -292,9 +296,7 @@ def update_item_wise_tax_detail(consolidate_tax_row, tax_row): else: consolidated_tax_detail.update({item_code: [tax_data[0], tax_data[1]]}) - consolidate_tax_row.item_wise_tax_detail = json.dumps( - consolidated_tax_detail, separators=(",", ":") - ) + consolidate_tax_row.item_wise_tax_detail = json.dumps(consolidated_tax_detail, separators=(",", ":")) def get_all_unconsolidated_invoices(): @@ -339,9 +341,7 @@ def consolidate_pos_invoices(pos_invoices=None, closing_entry=None): if len(invoices) >= 10 and closing_entry: closing_entry.set_status(update=True, status="Queued") - enqueue_job( - create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry - ) + enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry) else: create_merge_logs(invoice_by_customer, closing_entry) @@ -389,9 +389,7 @@ def split_invoices(invoices): if not item.serial_no: continue - return_against_is_added = any( - d for d in _invoices if d.pos_invoice == pos_invoice.return_against - ) + return_against_is_added = any(d for d in _invoices if d.pos_invoice == pos_invoice.return_against) if return_against_is_added: break @@ -493,7 +491,7 @@ def enqueue_job(job, **kwargs): timeout=10000, event="processing_merge_logs", job_name=job_name, - now=frappe.conf.developer_mode or frappe.flags.in_test + now=frappe.conf.developer_mode or frappe.flags.in_test, ) if job == create_merge_logs: diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py index 9e696f18b6a4..144523624e82 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py @@ -28,15 +28,11 @@ def test_consolidated_invoice_creation(self): pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) - pos_inv2.append( - "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200} - ) + pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) pos_inv2.submit() pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1) - pos_inv3.append( - "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300} - ) + pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300}) pos_inv3.submit() consolidate_pos_invoices() @@ -65,15 +61,11 @@ def test_consolidated_credit_note_creation(self): pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) - pos_inv2.append( - "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200} - ) + pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) pos_inv2.submit() pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1) - pos_inv3.append( - "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300} - ) + pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300}) pos_inv3.submit() pos_inv_cn = make_sales_return(pos_inv.name) @@ -309,7 +301,7 @@ def test_consolidation_round_off_error_3(self): init_user_and_profile() item_rates = [69, 59, 29] - for i in [1, 2]: + for _i in [1, 2]: inv = create_pos_invoice(is_return=1, do_not_save=1) inv.items = [] for rate in item_rates: diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index e8aee737f29d..2c032dd718ba 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -114,10 +114,8 @@ def set_defaults(self, include_current_pos=True): condition = " where pfu.default = 1 " pos_view_users = frappe.db.sql_list( - """select pfu.user - from `tabPOS Profile User` as pfu {0}""".format( - condition - ) + f"""select pfu.user + from `tabPOS Profile User` as pfu {condition}""" ) for user in pos_view_users: @@ -144,10 +142,8 @@ def get_item_groups(pos_profile): def get_child_nodes(group_type, root): lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"]) return frappe.db.sql( - """ Select name, lft, rgt from `tab{tab}` where - lft >= {lft} and rgt <= {rgt} order by lft""".format( - tab=group_type, lft=lft, rgt=rgt - ), + f""" Select name, lft, rgt from `tab{group_type}` where + lft >= {lft} and rgt <= {rgt} order by lft""", as_dict=1, ) diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py index 788aa62701d6..e03714bdffed 100644 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py @@ -52,11 +52,9 @@ def get_customers_list(pos_profile=None): return ( frappe.db.sql( - """ select name, customer_name, customer_group, + f""" select name, customer_name, customer_group, territory, customer_pos_id from tabCustomer where disabled = 0 - and {cond}""".format( - cond=cond - ), + and {cond}""", tuple(customer_groups), as_dict=1, ) @@ -75,7 +73,7 @@ def get_items_list(pos_profile, company): cond = "and i.item_group in (%s)" % (", ".join(["%s"] * len(args_list))) return frappe.db.sql( - """ + f""" select i.name, i.item_code, i.item_name, i.description, i.item_group, i.has_batch_no, i.has_serial_no, i.is_stock_item, i.brand, i.stock_uom, i.image, @@ -88,10 +86,8 @@ def get_items_list(pos_profile, company): where i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1 and i.is_fixed_asset = 0 {cond} - """.format( - cond=cond - ), - tuple([company] + args_list), + """, + tuple([company, *args_list]), as_dict=1, ) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index e2b015bf0212..f39aa026b471 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -77,9 +77,9 @@ def validate_mandatory(self): if self.priority and cint(self.priority) == 1: throw( - _("As the field {0} is enabled, the value of the field {1} should be more than 1.").format( - frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority") - ) + _( + "As the field {0} is enabled, the value of the field {1} should be more than 1." + ).format(frappe.bold("Apply Discount on Discounted Rate"), frappe.bold("Priority")) ) def validate_applicable_for_selling_or_buying(self): @@ -273,9 +273,7 @@ def apply_pricing_rule(args, doc=None): def get_serial_no_for_item(args): from erpnext.stock.get_item_details import get_serial_no - item_details = frappe._dict( - {"doctype": args.doctype, "name": args.name, "serial_no": args.serial_no} - ) + item_details = frappe._dict({"doctype": args.doctype, "name": args.name, "serial_no": args.serial_no}) if args.get("parenttype") in ("Sales Invoice", "Delivery Note") and flt(args.stock_qty) > 0: item_details.serial_no = get_serial_no(args) return item_details @@ -373,9 +371,11 @@ def get_pricing_rule_for_item(args, doc=None, for_validate=False): ) if pricing_rule.apply_rule_on_other_items: - item_details["apply_rule_on_other_items"] = json.dumps(pricing_rule.apply_rule_on_other_items) + item_details["apply_rule_on_other_items"] = json.dumps( + pricing_rule.apply_rule_on_other_items + ) - if pricing_rule.coupon_code_based == 1 and args.coupon_code == None: + if pricing_rule.coupon_code_based == 1 and args.coupon_code is None: return item_details if not pricing_rule.validate_applied_rule: @@ -419,7 +419,6 @@ def update_args_for_pricing_rule(args): if args.transaction_type == "selling": if args.customer and not (args.customer_group and args.territory): - if args.quotation_to and args.quotation_to != "Customer": customer = frappe._dict() else: @@ -450,9 +449,9 @@ def get_pricing_rule_details(args, pricing_rule): def apply_price_discount_rule(pricing_rule, item_details, args): item_details.pricing_rule_for = pricing_rule.rate_or_discount - if ( - pricing_rule.margin_type in ["Amount", "Percentage"] and pricing_rule.currency == args.currency - ) or (pricing_rule.margin_type == "Percentage"): + if (pricing_rule.margin_type in ["Amount", "Percentage"] and pricing_rule.currency == args.currency) or ( + pricing_rule.margin_type == "Percentage" + ): item_details.margin_type = pricing_rule.margin_type item_details.has_margin = True @@ -595,7 +594,7 @@ def get_item_uoms(doctype, txt, searchfield, start, page_len, filters): return frappe.get_all( "UOM Conversion Detail", - filters={"parent": ("in", items), "uom": ("like", "{0}%".format(txt))}, + filters={"parent": ("in", items), "uom": ("like", f"{txt}%")}, fields=["distinct uom"], as_list=1, ) diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 7f8cc4c63e0e..ab52d6c97291 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -103,8 +103,6 @@ def test_pricing_rule_for_discount(self): self.assertEqual(details.get("discount_percentage"), 15) def test_pricing_rule_for_margin(self): - from frappe import MandatoryError - from erpnext.stock.get_item_details import get_item_details test_record = { @@ -205,8 +203,6 @@ def test_mixed_conditions_for_item_group(self): self.assertEqual(details.get("discount_percentage"), 10) def test_pricing_rule_for_variants(self): - from frappe import MandatoryError - from erpnext.stock.get_item_details import get_item_details if not frappe.db.exists("Item", "Test Variant PRT"): @@ -1055,8 +1051,7 @@ def delete_existing_pricing_rules(): "Pricing Rule Item Group", "Pricing Rule Brand", ]: - - frappe.db.sql("delete from `tab{0}`".format(doctype)) + frappe.db.sql(f"delete from `tab{doctype}`") def make_item_price(item, price_list_name, item_price): diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 8396783ffa1e..ce96a3d12406 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -101,14 +101,12 @@ def _get_pricing_rules(apply_on, args, values): if not args.get(apply_on_field): return [] - child_doc = "`tabPricing Rule {0}`".format(apply_on) + child_doc = f"`tabPricing Rule {apply_on}`" conditions = item_variant_condition = item_conditions = "" values[apply_on_field] = args.get(apply_on_field) if apply_on_field in ["item_code", "brand"]: - item_conditions = "{child_doc}.{apply_on_field}= %({apply_on_field})s".format( - child_doc=child_doc, apply_on_field=apply_on_field - ) + item_conditions = f"{child_doc}.{apply_on_field}= %({apply_on_field})s" if apply_on_field == "item_code": if args.get("uom", None): @@ -121,9 +119,7 @@ def _get_pricing_rules(apply_on, args, values): args.variant_of = frappe.get_cached_value("Item", args.item_code, "variant_of") if args.variant_of: - item_variant_condition = " or {child_doc}.item_code=%(variant_of)s ".format( - child_doc=child_doc - ) + item_variant_condition = f" or {child_doc}.item_code=%(variant_of)s " values["variant_of"] = args.variant_of elif apply_on_field == "item_group": item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False) @@ -131,7 +127,7 @@ def _get_pricing_rules(apply_on, args, values): conditions += get_other_conditions(conditions, values, args) warehouse_conditions = _get_tree_conditions(args, "Warehouse", "`tabPricing Rule`") if warehouse_conditions: - warehouse_conditions = " and {0}".format(warehouse_conditions) + warehouse_conditions = f" and {warehouse_conditions}" if not args.price_list: args.price_list = None @@ -157,7 +153,7 @@ def _get_pricing_rules(apply_on, args, values): item_variant_condition=item_variant_condition, transaction_type=args.transaction_type, warehouse_cond=warehouse_conditions, - apply_on_other_field="other_{0}".format(apply_on_field), + apply_on_other_field=f"other_{apply_on_field}", conditions=conditions, ), values, @@ -196,14 +192,13 @@ def _get_tree_conditions(args, parenttype, table, allow_blank=True): frappe.throw(_("Invalid {0}").format(args.get(field))) parent_groups = frappe.db.sql_list( - """select name from `tab%s` - where lft<=%s and rgt>=%s""" - % (parenttype, "%s", "%s"), + """select name from `tab{}` + where lft<={} and rgt>={}""".format(parenttype, "%s", "%s"), (lft, rgt), ) if parenttype in ["Customer Group", "Item Group", "Territory"]: - parent_field = "parent_{0}".format(frappe.scrub(parenttype)) + parent_field = f"parent_{frappe.scrub(parenttype)}" root_name = frappe.db.get_list( parenttype, {"is_group": 1, parent_field: ("is", "not set")}, @@ -229,10 +224,10 @@ def _get_tree_conditions(args, parenttype, table, allow_blank=True): def get_other_conditions(conditions, values, args): for field in ["company", "customer", "supplier", "campaign", "sales_partner"]: if args.get(field): - conditions += " and ifnull(`tabPricing Rule`.{0}, '') in (%({1})s, '')".format(field, field) + conditions += f" and ifnull(`tabPricing Rule`.{field}, '') in (%({field})s, '')" values[field] = args.get(field) else: - conditions += " and ifnull(`tabPricing Rule`.{0}, '') = ''".format(field) + conditions += f" and ifnull(`tabPricing Rule`.{field}, '') = ''" for parenttype in ["Customer Group", "Territory", "Supplier Group"]: group_condition = _get_tree_conditions(args, parenttype, "`tabPricing Rule`") @@ -504,7 +499,7 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=None): "transaction_date" if frappe.get_meta(doctype).has_field("transaction_date") else "posting_date" ) - child_doctype = "{0} Item".format(doctype) + child_doctype = f"{doctype} Item" apply_on = frappe.scrub(pr_doc.get("apply_on")) values = [pr_doc.valid_from, pr_doc.valid_upto] @@ -514,9 +509,7 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=None): warehouses = get_child_warehouses(pr_doc.warehouse) condition += """ and `tab{child_doc}`.warehouse in ({warehouses}) - """.format( - child_doc=child_doctype, warehouses=",".join(["%s"] * len(warehouses)) - ) + """.format(child_doc=child_doctype, warehouses=",".join(["%s"] * len(warehouses))) values.extend(warehouses) @@ -528,16 +521,14 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=None): values.extend(items) data_set = frappe.db.sql( - """ SELECT `tab{child_doc}`.stock_qty, - `tab{child_doc}`.amount - FROM `tab{child_doc}`, `tab{parent_doc}` + f""" SELECT `tab{child_doctype}`.stock_qty, + `tab{child_doctype}`.amount + FROM `tab{child_doctype}`, `tab{doctype}` WHERE - `tab{child_doc}`.parent = `tab{parent_doc}`.name and `tab{parent_doc}`.{date_field} - between %s and %s and `tab{parent_doc}`.docstatus = 1 - {condition} group by `tab{child_doc}`.name - """.format( - parent_doc=doctype, child_doc=child_doctype, condition=condition, date_field=date_field - ), + `tab{child_doctype}`.parent = `tab{doctype}`.name and `tab{doctype}`.{date_field} + between %s and %s and `tab{doctype}`.docstatus = 1 + {condition} group by `tab{child_doctype}`.name + """, tuple(values), as_dict=1, ) @@ -556,11 +547,9 @@ def apply_pricing_rule_on_transaction(doc): conditions = get_other_conditions(conditions, values, doc) pricing_rules = frappe.db.sql( - """ Select `tabPricing Rule`.* from `tabPricing Rule` + f""" Select `tabPricing Rule`.* from `tabPricing Rule` where {conditions} and `tabPricing Rule`.disable = 0 - """.format( - conditions=conditions - ), + """, values, as_dict=1, ) @@ -583,7 +572,9 @@ def apply_pricing_rule_on_transaction(doc): continue if ( - d.validate_applied_rule and doc.get(field) is not None and doc.get(field) < d.get(pr_field) + d.validate_applied_rule + and doc.get(field) is not None + and doc.get(field) < d.get(pr_field) ): frappe.msgprint(_("User has not applied rule on the invoice {0}").format(doc.name)) else: @@ -643,9 +634,7 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None): qty = pricing_rule.free_qty or 1 if pricing_rule.is_recursive: - transaction_qty = ( - args.get("qty") if args else doc.total_qty - ) - pricing_rule.apply_recursion_over + transaction_qty = (args.get("qty") if args else doc.total_qty) - pricing_rule.apply_recursion_over if transaction_qty: qty = flt(transaction_qty) * qty / pricing_rule.recurse_for if pricing_rule.round_free_qty: diff --git a/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py index 263621dcf4db..fddd9f839267 100644 --- a/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py +++ b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py @@ -40,7 +40,7 @@ def test_creation_of_ledger_entry_on_submit(self): si.save() si.submit() - process_deferred_accounting = doc = frappe.get_doc( + process_deferred_accounting = frappe.get_doc( dict( doctype="Process Deferred Accounting", posting_date="2023-07-01", 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 a93fd46caf67..33cff14ac4e1 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py @@ -41,9 +41,7 @@ def on_submit(self): def on_cancel(self): self.db_set("status", "Cancelled") - log = frappe.db.get_value( - "Process Payment Reconciliation Log", filters={"process_pr": self.name} - ) + log = frappe.db.get_value("Process Payment Reconciliation Log", filters={"process_pr": self.name}) if log: frappe.db.set_value("Process Payment Reconciliation Log", log, "status", "Cancelled") @@ -129,7 +127,7 @@ def trigger_job_for_doc(docname: str | None = None): frappe.db.set_value("Process Payment Reconciliation", docname, "status", "Running") job_name = f"start_processing_{docname}" if not is_job_running(job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.reconcile_based_on_filters", queue="long", is_async=True, @@ -147,7 +145,7 @@ def trigger_job_for_doc(docname: str | None = None): # Resume tasks for running doc job_name = f"start_processing_{docname}" if not is_job_running(job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.reconcile_based_on_filters", queue="long", is_async=True, @@ -224,7 +222,7 @@ def reconcile_based_on_filters(doc: None | str = None) -> None: job_name = f"process_{doc}_fetch_and_allocate" if not is_job_running(job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.fetch_and_allocate", queue="long", timeout="3600", @@ -245,7 +243,7 @@ def reconcile_based_on_filters(doc: None | str = None) -> None: if not allocated: job_name = f"process__{doc}_fetch_and_allocate" if not is_job_running(job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.fetch_and_allocate", queue="long", timeout="3600", @@ -263,7 +261,7 @@ def reconcile_based_on_filters(doc: None | str = None) -> None: else: reconcile_job_name = f"process_{doc}_reconcile" if not is_job_running(reconcile_job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.reconcile", queue="long", timeout="3600", @@ -350,7 +348,7 @@ def fetch_and_allocate(doc: str) -> None: reconcile_job_name = f"process_{doc}_reconcile" if not is_job_running(reconcile_job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.reconcile", queue="long", timeout="3600", @@ -391,7 +389,6 @@ def reconcile(doc: None | str = None) -> None: # If Payment Entry, update details only for newly linked references # This is for performance if allocations[0].reference_type == "Payment Entry": - references = [(x.invoice_type, x.invoice_number) for x in allocations] pe = frappe.get_doc(allocations[0].reference_type, allocations[0].reference_name) pe.flags.ignore_validate_update_after_submit = True @@ -405,13 +402,14 @@ def reconcile(doc: None | str = None) -> None: # Update reconciled count reconciled_count = frappe.db.count( - "Process Payment Reconciliation Log Allocations", filters={"parent": log, "reconciled": True} + "Process Payment Reconciliation Log Allocations", + filters={"parent": log, "reconciled": True}, ) frappe.db.set_value( "Process Payment Reconciliation Log", log, "reconciled_entries", reconciled_count ) - except Exception as err: + except Exception: # Update the parent doc about the exception frappe.db.rollback() @@ -449,20 +447,19 @@ def reconcile(doc: None | str = None) -> None: frappe.db.set_value("Process Payment Reconciliation Log", log, "reconciled", True) frappe.db.set_value("Process Payment Reconciliation", doc, "status", "Completed") else: - - if not (frappe.db.get_value("Process Payment Reconciliation", doc, "status") == "Paused"): + if not ( + frappe.db.get_value("Process Payment Reconciliation", doc, "status") == "Paused" + ): # trigger next batch in job # generate reconcile job name allocation = get_next_allocation(log) if allocation: - reconcile_job_name = ( - f"process_{doc}_reconcile_allocation_{allocation[0].idx}_{allocation[-1].idx}" - ) + reconcile_job_name = f"process_{doc}_reconcile_allocation_{allocation[0].idx}_{allocation[-1].idx}" else: reconcile_job_name = f"process_{doc}_reconcile" if not is_job_running(reconcile_job_name): - job = frappe.enqueue( + frappe.enqueue( method="erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.reconcile", queue="long", timeout="3600", 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 9c0bedd243fa..0c266ce79472 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 @@ -423,9 +423,7 @@ def send_emails(document_name, from_scheduler=False, posting_date=None): else: new_to_date = add_months(new_to_date, 1 if doc.frequency == "Monthly" else 3) new_from_date = add_months(new_to_date, -1 * doc.filter_duration) - doc.add_comment( - "Comment", "Emails sent on: " + frappe.utils.format_datetime(frappe.utils.now()) - ) + doc.add_comment("Comment", "Emails sent on: " + frappe.utils.format_datetime(frappe.utils.now())) if doc.report == "General Ledger": doc.db_set("to_date", new_to_date, commit=True) doc.db_set("from_date", new_from_date, commit=True) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py index a3a74df40291..92dbb5ef273d 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py @@ -1,7 +1,6 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.tests.utils import FrappeTestCase diff --git a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py index 4d28d1066045..e3278098f1a1 100644 --- a/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py +++ b/erpnext/accounts/doctype/promotional_scheme/promotional_scheme.py @@ -100,9 +100,7 @@ def validate_pricing_rules(self): docnames = frappe.get_all("Pricing Rule", filters={"promotional_scheme": self.name}) for docname in docnames: - if frappe.db.exists( - "Pricing Rule Detail", {"pricing_rule": docname.name, "docstatus": ("<", 2)} - ): + if frappe.db.exists("Pricing Rule Detail", {"pricing_rule": docname.name, "docstatus": ("<", 2)}): raise_for_transaction_exists(self.name) if docnames and not transaction_exists: @@ -177,7 +175,7 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None): args = get_args_for_pricing_rule(doc) applicable_for = frappe.scrub(doc.get("applicable_for")) - for idx, d in enumerate(doc.get(child_doc)): + for _idx, d in enumerate(doc.get(child_doc)): if d.name in rules: if not args.get(applicable_for): docname = get_pricing_rule_docname(d) @@ -187,7 +185,14 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None): for applicable_for_value in args.get(applicable_for): docname = get_pricing_rule_docname(d, applicable_for, applicable_for_value) pr = prepare_pricing_rule( - args, doc, child_doc, discount_fields, d, docname, applicable_for, applicable_for_value + args, + doc, + child_doc, + discount_fields, + d, + docname, + applicable_for, + applicable_for_value, ) new_doc.append(pr) @@ -213,7 +218,7 @@ def _get_pricing_rules(doc, child_doc, discount_fields, rules=None): def get_pricing_rule_docname( - row: dict, applicable_for: str = None, applicable_for_value: str = None + row: dict, applicable_for: str | None = None, applicable_for_value: str | None = None ) -> str: fields = ["promotional_scheme_id", "name"] filters = {"promotional_scheme_id": row.name} diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index f54787de717e..b53627a682f4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -55,7 +55,7 @@ class WarehouseMissingError(frappe.ValidationError): class PurchaseInvoice(BuyingController): def __init__(self, *args, **kwargs): - super(PurchaseInvoice, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "source_dt": "Purchase Invoice Item", @@ -72,7 +72,7 @@ def __init__(self, *args, **kwargs): ] def onload(self): - super(PurchaseInvoice, self).onload() + super().onload() supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category") self.set_onload("supplier_tds", supplier_tds) @@ -92,7 +92,7 @@ def validate(self): self.validate_posting_time() - super(PurchaseInvoice, self).validate() + super().validate() if not self.is_return: self.po_required() @@ -155,7 +155,6 @@ def validate_cash(self): if flt(self.paid_amount) + flt(self.write_off_amount) - flt( self.get("rounded_total") or self.grand_total ) > 1 / (10 ** (self.precision("base_grand_total") + 1)): - frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total""")) def create_remarks(self): @@ -184,7 +183,7 @@ def set_missing_values(self, for_validate=False): self.tax_withholding_category = tds_category self.set_onload("supplier_tds", tds_category) - super(PurchaseInvoice, self).set_missing_values(for_validate) + super().set_missing_values(for_validate) def validate_credit_to_acc(self): if not self.credit_to: @@ -218,12 +217,12 @@ def check_on_hold_or_closed_status(self): check_list = [] for d in self.get("items"): - if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt: + if d.purchase_order and d.purchase_order not in check_list and not d.purchase_receipt: check_list.append(d.purchase_order) check_on_hold_or_closed_status("Purchase Order", d.purchase_order) def validate_with_previous_doc(self): - super(PurchaseInvoice, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Purchase Order": { "ref_dn_field": "purchase_order", @@ -271,7 +270,7 @@ def validate_warehouse(self, for_validate=True): exc=WarehouseMissingError, ) - super(PurchaseInvoice, self).validate_warehouse() + super().validate_warehouse() def validate_item_code(self): for d in self.get("items"): @@ -307,7 +306,6 @@ def set_expense_account(self, for_validate=False): or not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier") ) ): - if self.update_stock and item.warehouse and (not item.from_warehouse): if ( for_validate @@ -335,12 +333,16 @@ def set_expense_account(self, for_validate=False): if negative_expense_booked_in_pr: if ( - for_validate and item.expense_account and item.expense_account != stock_not_billed_account + for_validate + and item.expense_account + and item.expense_account != stock_not_billed_account ): msg = _( "Row {0}: Expense Head changed to {1} because expense is booked against this account in Purchase Receipt {2}" ).format( - item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.purchase_receipt) + item.idx, + frappe.bold(stock_not_billed_account), + frappe.bold(item.purchase_receipt), ) frappe.msgprint(msg, title=_("Expense Head Changed")) @@ -349,7 +351,9 @@ def set_expense_account(self, for_validate=False): # If no purchase receipt present then book expense in 'Stock Received But Not Billed' # This is done in cases when Purchase Invoice is created before Purchase Receipt if ( - for_validate and item.expense_account and item.expense_account != stock_not_billed_account + for_validate + and item.expense_account + and item.expense_account != stock_not_billed_account ): msg = _( "Row {0}: Expense Head changed to {1} as no Purchase Receipt is created against Item {2}." @@ -400,7 +404,6 @@ def set_against_expense_account(self): def po_required(self): if frappe.db.get_value("Buying Settings", None, "po_required") == "Yes": - if frappe.get_value( "Supplier", self.supplier, "allow_purchase_invoice_creation_without_purchase_order" ): @@ -410,7 +413,9 @@ def po_required(self): if not d.purchase_order: msg = _("Purchase Order Required for item {}").format(frappe.bold(d.item_code)) msg += "

" - msg += _("To submit the invoice without purchase order please set {0} as {1} in {2}").format( + msg += _( + "To submit the invoice without purchase order please set {0} as {1} in {2}" + ).format( frappe.bold(_("Purchase Order Required")), frappe.bold("No"), get_link_to_form("Buying Settings", "Buying Settings", "Buying Settings"), @@ -420,7 +425,6 @@ def po_required(self): def pr_required(self): stock_items = self.get_stock_items() if frappe.db.get_value("Buying Settings", None, "pr_required") == "Yes": - if frappe.get_value( "Supplier", self.supplier, "allow_purchase_invoice_creation_without_purchase_receipt" ): @@ -453,7 +457,8 @@ def check_prev_docstatus(self): frappe.throw(_("Purchase Order {0} is not submitted").format(d.purchase_order)) if d.purchase_receipt: submitted = frappe.db.sql( - "select name from `tabPurchase Receipt` where docstatus = 1 and name = %s", d.purchase_receipt + "select name from `tabPurchase Receipt` where docstatus = 1 and name = %s", + d.purchase_receipt, ) if not submitted: frappe.throw(_("Purchase Receipt {0} is not submitted").format(d.purchase_receipt)) @@ -501,7 +506,9 @@ def validate_purchase_receipt_if_update_stock(self): for item in self.get("items"): if item.purchase_receipt: frappe.throw( - _("Stock cannot be updated against Purchase Receipt {0}").format(item.purchase_receipt) + _("Stock cannot be updated against Purchase Receipt {0}").format( + item.purchase_receipt + ) ) def validate_for_repost(self): @@ -511,7 +518,7 @@ def validate_for_repost(self): validate_docs_for_deferred_accounting([], [self.name]) def on_submit(self): - super(PurchaseInvoice, self).on_submit() + super().on_submit() self.check_prev_docstatus() @@ -551,9 +558,7 @@ def on_submit(self): if self.update_stock == 1: self.repost_future_sle_and_gle() - if ( - frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction" - ): + 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) @@ -733,9 +738,7 @@ def make_item_gl_entries(self, gl_entries): exchange_rate_map, net_rate_map = get_purchase_document_details(self) provisional_accounting_for_non_stock_items = cint( - frappe.db.get_value( - "Company", self.company, "enable_provisional_accounting_for_non_stock_items" - ) + frappe.db.get_value("Company", self.company, "enable_provisional_accounting_for_non_stock_items") ) if provisional_accounting_for_non_stock_items: self.get_provisional_accounts() @@ -744,7 +747,7 @@ def make_item_gl_entries(self, gl_entries): if flt(item.base_net_amount): account_currency = get_account_currency(item.expense_account) if item.item_code: - asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") + frappe.get_cached_value("Item", item.item_code, "asset_category") if ( self.update_stock @@ -849,7 +852,9 @@ def make_item_gl_entries(self, gl_entries): if flt(item.rm_supp_cost): supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["account"] if not supplier_warehouse_account: - frappe.throw(_("Please set account in Warehouse {0}").format(self.supplier_warehouse)) + frappe.throw( + _("Please set account in Warehouse {0}").format(self.supplier_warehouse) + ) gl_entries.append( self.get_gl_dict( { @@ -899,10 +904,9 @@ def make_item_gl_entries(self, gl_entries): and self.conversion_rate != exchange_rate_map[item.purchase_receipt] and item.net_rate == net_rate_map[item.pr_detail] ): - - discrepancy_caused_by_exchange_rate_difference = (item.qty * item.net_rate) * ( - exchange_rate_map[item.purchase_receipt] - self.conversion_rate - ) + discrepancy_caused_by_exchange_rate_difference = ( + item.qty * item.net_rate + ) * (exchange_rate_map[item.purchase_receipt] - self.conversion_rate) gl_entries.append( self.get_gl_dict( @@ -983,7 +987,9 @@ def get_provisional_accounts(self): default_provisional_account = self.get_company_default("default_provisional_account") provisional_accounts = set( [ - d.provisional_expense_account if d.provisional_expense_account else default_provisional_account + d.provisional_expense_account + if d.provisional_expense_account + else default_provisional_account for d in pr_items ] ) @@ -1040,9 +1046,7 @@ def update_gross_purchase_amount_for_linked_assets(self, item): }, ) - def make_stock_adjustment_entry( - self, gl_entries, item, voucher_wise_stock_value, account_currency - ): + def make_stock_adjustment_entry(self, gl_entries, item, voucher_wise_stock_value, account_currency): net_amt_precision = item.precision("base_net_amount") val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9 @@ -1058,7 +1062,6 @@ def make_stock_adjustment_entry( and warehouse_debit_amount != flt(voucher_wise_stock_value.get((item.name, item.warehouse)), net_amt_precision) ): - cost_of_goods_sold_account = self.get_company_default("default_expense_account") stock_amount = flt(voucher_wise_stock_value.get((item.name, item.warehouse)), net_amt_precision) stock_adjustment_amt = warehouse_debit_amount - stock_amount @@ -1281,9 +1284,7 @@ def make_gle_for_rounding_adjustment(self, gl_entries): # base_rounding_adjustment may become zero due to small precision # eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2 # then base_rounding_adjustment becomes zero and error is thrown in GL Entry - if ( - not self.is_internal_transfer() and self.rounding_adjustment and self.base_rounding_adjustment - ): + if not self.is_internal_transfer() and self.rounding_adjustment and self.base_rounding_adjustment: round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center ) @@ -1306,7 +1307,7 @@ def make_gle_for_rounding_adjustment(self, gl_entries): def on_cancel(self): check_if_return_invoice_linked_with_payment_entry(self) - super(PurchaseInvoice, self).on_cancel() + super().on_cancel() self.check_on_hold_or_closed_status() @@ -1337,9 +1338,7 @@ def on_cancel(self): if self.update_stock == 1: self.repost_future_sle_and_gle() - if ( - frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction" - ): + if frappe.db.get_single_value("Buying Settings", "project_update_frequency") == "Each Transaction": self.update_project() self.db_set("status", "Cancelled") @@ -1370,9 +1369,7 @@ def update_project(self): 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() - ) + 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) @@ -1640,9 +1637,7 @@ def get_purchase_document_details(doc): ) net_rate_map = frappe._dict( - frappe.get_all( - child_doctype, filters={"name": ("in", items)}, fields=["name", "net_rate"], as_list=1 - ) + frappe.get_all(child_doctype, filters={"name": ("in", items)}, fields=["name", "net_rate"], as_list=1) ) return exchange_rate_map, net_rate_map diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index ba97fc685a39..109b2e8ea62d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -2,8 +2,6 @@ # License: GNU General Public License v3. See license.txt -import unittest - import frappe from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, cint, flt, getdate, nowdate, today @@ -252,7 +250,6 @@ def test_purchase_invoice_explicit_block(self): self.assertEqual(pi.on_hold, 0) def test_gl_entries_with_perpetual_inventory_against_pr(self): - pr = make_purchase_receipt( company="_Test Company with perpetual inventory", supplier_warehouse="Work In Progress - TCP1", @@ -303,7 +300,7 @@ def check_gle_for_pi(self, pi): ] ) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][0], gle.account) self.assertEqual(expected_values[gle.account][1], gle.debit) self.assertEqual(expected_values[gle.account][2], gle.credit) @@ -327,9 +324,7 @@ def test_purchase_invoice_with_exchange_rate_difference(self): pi.submit() # Get exchnage gain and loss account - exchange_gain_loss_account = frappe.db.get_value( - "Company", pi.company, "exchange_gain_loss_account" - ) + exchange_gain_loss_account = frappe.db.get_value("Company", pi.company, "exchange_gain_loss_account") # fetching the latest GL Entry with exchange gain and loss account account amount = frappe.db.get_value( @@ -545,12 +540,10 @@ def test_total_purchase_cost_for_project(self): project = frappe.get_doc("Project", {"project_name": "_Test Project for Purchase"}) existing_purchase_cost = frappe.db.sql( - """select sum(base_net_amount) + f"""select sum(base_net_amount) from `tabPurchase Invoice Item` - where project = '{0}' - and docstatus=1""".format( - project.name - ) + where project = '{project.name}' + and docstatus=1""" ) existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0 @@ -725,7 +718,7 @@ def test_multi_currency_gle(self): "credit", "credit_in_account_currency", ): - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][field], gle[field]) # Check for valid currency @@ -747,7 +740,6 @@ def test_multi_currency_gle(self): self.assertFalse(gle) def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self): - pi = make_purchase_invoice( update_stock=1, posting_date=frappe.utils.nowdate(), @@ -776,13 +768,12 @@ def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self): (d[0], d) for d in [[pi.credit_to, 0.0, 250.0], [stock_in_hand_account, 250.0, 0.0]] ) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_gl_entries[gle.account][0], gle.account) self.assertEqual(expected_gl_entries[gle.account][1], gle.debit) self.assertEqual(expected_gl_entries[gle.account][2], gle.credit) def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_inventory(self): - pi = make_purchase_invoice( update_stock=1, posting_date=frappe.utils.nowdate(), @@ -817,7 +808,7 @@ def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_i ] ) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_gl_entries[gle.account][0], gle.account) self.assertEqual(expected_gl_entries[gle.account][1], gle.debit) self.assertEqual(expected_gl_entries[gle.account][2], gle.credit) @@ -1015,12 +1006,8 @@ def test_make_pi_without_terms(self): def test_duplicate_due_date_in_terms(self): pi = make_purchase_invoice(do_not_save=1) - pi.append( - "payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50) - ) - pi.append( - "payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50) - ) + pi.append("payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50)) + pi.append("payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50)) self.assertRaises(frappe.ValidationError, pi.insert) @@ -1058,9 +1045,7 @@ def test_purchase_invoice_with_cost_center(self): cost_center = "_Test Cost Center for BS Account - _TC" create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company") - pi = make_purchase_invoice_against_cost_center( - cost_center=cost_center, credit_to="Creditors - _TC" - ) + pi = make_purchase_invoice_against_cost_center(cost_center=cost_center, credit_to="Creditors - _TC") self.assertEqual(pi.cost_center, cost_center) expected_values = { @@ -1522,9 +1507,7 @@ def test_purchase_invoice_advance_taxes(self): def test_provisional_accounting_entry(self): setup_provisional_accounting() - pr = make_purchase_receipt( - item_code="_Test Non Stock Item", posting_date=add_days(nowdate(), -2) - ) + pr = make_purchase_receipt(item_code="_Test Non Stock Item", posting_date=add_days(nowdate(), -2)) pi = create_purchase_invoice_from_receipt(pr.name) pi.set_posting_time = 1 @@ -1533,7 +1516,7 @@ def test_provisional_accounting_entry(self): pi.save() pi.submit() - self.assertEquals(pr.items[0].provisional_expense_account, "Provision Account - _TC") + self.assertEqual(pr.items[0].provisional_expense_account, "Provision Account - _TC") # Check GLE for Purchase Invoice expected_gle = [ @@ -1560,9 +1543,7 @@ def test_provisional_accounting_entry(self): ["_Test Account Cost for Goods Sold - _TC", 250, 0, pi.posting_date], ] - check_gl_entries( - self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date - ) + check_gl_entries(self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date) toggle_provisional_accounting_setting() @@ -1611,9 +1592,7 @@ def test_provisional_accounting_entry_for_over_billing(self): ["_Test Account Cost for Goods Sold - _TC", 5000, 0, pi.posting_date], ] - check_gl_entries( - self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date - ) + check_gl_entries(self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date) toggle_provisional_accounting_setting() @@ -1659,9 +1638,7 @@ def test_provisional_accounting_entry_for_partial_billing(self): def test_adjust_incoming_rate(self): frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) - frappe.db.set_single_value( - "Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1 - ) + frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1) # Increase the cost of the item @@ -1713,9 +1690,7 @@ def test_adjust_incoming_rate(self): ) self.assertEqual(stock_value_difference, 50) - frappe.db.set_single_value( - "Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0 - ) + frappe.db.set_single_value("Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0) # Don't adjust incoming rate @@ -1745,7 +1720,6 @@ def test_adjust_incoming_rate(self): frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1) def test_item_less_defaults(self): - pi = frappe.new_doc("Purchase Invoice") pi.supplier = "_Test Supplier" pi.company = "_Test Company" @@ -2178,9 +2152,7 @@ def setup_provisional_accounting(**args): parent_account=args.parent_account or "Current Liabilities - _TC", company=company, ) - toggle_provisional_accounting_setting( - enable=1, company=company, provisional_account=provisional_account - ) + toggle_provisional_accounting_setting(enable=1, company=company, provisional_account=provisional_account) def toggle_provisional_accounting_setting(**args): 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 70d29bfda25f..7c54b53120af 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 @@ -17,4 +17,4 @@ def validate(self): def autoname(self): if self.company and self.title: abbr = frappe.get_cached_value("Company", self.company, "abbr") - self.name = "{0} - {1}".format(self.title, abbr) + self.name = f"{self.title} - {abbr}" 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 28355964cfa1..15478ab86338 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py @@ -9,7 +9,7 @@ class RepostAccountingLedger(Document): def __init__(self, *args, **kwargs): - super(RepostAccountingLedger, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._allowed_types = get_allowed_types_from_settings() def validate(self): @@ -136,7 +136,9 @@ def start_repost(account_repost_doc=str) -> None: doc = frappe.get_doc(x.voucher_type, x.voucher_no) if repost_doc.delete_cancelled_entries: - frappe.db.delete("GL Entry", filters={"voucher_type": doc.doctype, "voucher_no": doc.name}) + frappe.db.delete( + "GL Entry", filters={"voucher_type": doc.doctype, "voucher_no": doc.name} + ) frappe.db.delete( "Payment Ledger Entry", filters={"voucher_type": doc.doctype, "voucher_no": doc.name} ) @@ -182,7 +184,9 @@ def validate_docs_for_deferred_accounting(sales_docs, purchase_docs): if docs_with_deferred_revenue or docs_with_deferred_expense: frappe.throw( _("Documents: {0} have deferred revenue/expense enabled for them. Cannot repost.").format( - frappe.bold(comma_and([x[0] for x in docs_with_deferred_expense + docs_with_deferred_revenue])) + frappe.bold( + comma_and([x[0] for x in docs_with_deferred_expense + docs_with_deferred_revenue]) + ) ) ) diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py index d6f7096132f7..f631ef437d61 100644 --- a/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py +++ b/erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py @@ -9,7 +9,6 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request -from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import start_repost from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.test.accounts_mixin import AccountsTestMixin from erpnext.accounts.utils import get_fiscal_year 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 d603635ac5ae..d383b870b2ce 100644 --- a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py +++ b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py @@ -40,7 +40,7 @@ def start_payment_ledger_repost(docname=None): frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_error_log", "") frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_status", "Completed") - except Exception as e: + except Exception: frappe.db.rollback() traceback = frappe.get_traceback(with_context=True) @@ -53,7 +53,7 @@ def start_payment_ledger_repost(docname=None): class RepostPaymentLedger(Document): def __init__(self, *args, **kwargs): - super(RepostPaymentLedger, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.vouchers = [] def before_validate(self): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6a1a5f3a7c99..3ea4b91641cb 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -50,7 +50,7 @@ class SalesInvoice(SellingController): def __init__(self, *args, **kwargs): - super(SalesInvoice, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "source_dt": "Sales Invoice Item", @@ -87,7 +87,7 @@ def set_indicator(self): self.indicator_title = _("Paid") def validate(self): - super(SalesInvoice, self).validate() + super().validate() self.validate_auto_set_posting_time() if not (self.is_pos or self.is_debit_note): @@ -293,9 +293,7 @@ def on_submit(self): self.update_time_sheet(self.name) - if ( - frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction" - ): + if frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction": update_company_current_month_sales(self.company) self.update_project() update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference) @@ -308,9 +306,7 @@ def on_submit(self): and not self.dont_create_loyalty_points ): self.make_loyalty_point_entry() - elif ( - self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program - ): + elif self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program: against_si_doc = frappe.get_doc("Sales Invoice", self.return_against) against_si_doc.delete_loyalty_point_entry() against_si_doc.make_loyalty_point_entry() @@ -339,11 +335,11 @@ def validate_pos_paid_amount(self): def check_if_consolidated_invoice(self): # since POS Invoice extends Sales Invoice, we explicitly check if doctype is Sales Invoice if self.doctype == "Sales Invoice" and self.is_consolidated: - invoice_or_credit_note = ( - "consolidated_credit_note" if self.is_return else "consolidated_invoice" - ) + invoice_or_credit_note = "consolidated_credit_note" if self.is_return else "consolidated_invoice" pos_closing_entry = frappe.get_all( - "POS Invoice Merge Log", filters={invoice_or_credit_note: self.name}, pluck="pos_closing_entry" + "POS Invoice Merge Log", + filters={invoice_or_credit_note: self.name}, + pluck="pos_closing_entry", ) if pos_closing_entry and pos_closing_entry[0]: msg = _("To cancel a {} you need to cancel the POS Closing Entry {}.").format( @@ -355,13 +351,13 @@ def check_if_consolidated_invoice(self): def before_cancel(self): self.check_if_consolidated_invoice() - super(SalesInvoice, self).before_cancel() + super().before_cancel() self.update_time_sheet(None) def on_cancel(self): check_if_return_invoice_linked_with_payment_entry(self) - super(SalesInvoice, self).on_cancel() + super().on_cancel() self.check_sales_order_on_hold_or_close("sales_order") @@ -391,16 +387,12 @@ def on_cancel(self): self.db_set("status", "Cancelled") self.db_set("repost_required", 0) - if ( - frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction" - ): + if frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction": update_company_current_month_sales(self.company) self.update_project() if not self.is_return and not self.is_consolidated and self.loyalty_program: self.delete_loyalty_point_entry() - elif ( - self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program - ): + elif self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program: against_si_doc = frappe.get_doc("Sales Invoice", self.return_against) against_si_doc.delete_loyalty_point_entry() against_si_doc.make_loyalty_point_entry() @@ -504,7 +496,7 @@ def set_missing_values(self, for_validate=False): if not self.due_date and self.customer: self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company) - super(SalesInvoice, self).set_missing_values(for_validate) + super().set_missing_values(for_validate) print_format = pos.get("print_format") if pos else None if not print_format and not cint(frappe.db.get_value("Print Format", "POS Invoice", "disabled")): @@ -694,7 +686,8 @@ def validate_debit_to_acc(self): if account.report_type != "Balance Sheet": msg = ( - _("Please ensure {} account is a Balance Sheet account.").format(frappe.bold("Debit To")) + " " + _("Please ensure {} account is a Balance Sheet account.").format(frappe.bold("Debit To")) + + " " ) msg += _( "You can change the parent account to a Balance Sheet account or select a different account." @@ -723,11 +716,16 @@ def clear_unallocated_mode_of_payments(self): ) def validate_with_previous_doc(self): - super(SalesInvoice, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Sales Order": { "ref_dn_field": "sales_order", - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]], + "compare_fields": [ + ["customer", "="], + ["company", "="], + ["project", "="], + ["currency", "="], + ], }, "Sales Order Item": { "ref_dn_field": "so_detail", @@ -737,7 +735,12 @@ def validate_with_previous_doc(self): }, "Delivery Note": { "ref_dn_field": "delivery_note", - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]], + "compare_fields": [ + ["customer", "="], + ["company", "="], + ["project", "="], + ["currency", "="], + ], }, "Delivery Note Item": { "ref_dn_field": "dn_detail", @@ -792,13 +795,14 @@ def so_dn_required(self): } for key, value in prev_doc_field_map.items(): if frappe.db.get_single_value("Selling Settings", value[0]) == "Yes": - if frappe.get_value("Customer", self.customer, value[0]): continue for d in self.get("items"): if d.item_code and not d.get(key.lower().replace(" ", "_")) and not self.get(value[1]): - msgprint(_("{0} is mandatory for Item {1}").format(key, d.item_code), raise_exception=1) + msgprint( + _("{0} is mandatory for Item {1}").format(key, d.item_code), raise_exception=1 + ) def validate_proj_cust(self): """check for does customer belong to same project as entered..""" @@ -825,7 +829,7 @@ def validate_item_code(self): msgprint(_("Item Code required at Row No {0}").format(d.idx), raise_exception=True) def validate_warehouse(self): - super(SalesInvoice, self).validate_warehouse() + super().validate_warehouse() for d in self.get_item_list(): if ( @@ -1154,7 +1158,9 @@ def make_item_gl_entries(self, gl_entries): asset.db_set("disposal_date", None) if asset.calculate_depreciation: - posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date") + posting_date = frappe.db.get_value( + "Sales Invoice", self.return_against, "posting_date" + ) reverse_depreciation_entry_made_after_disposal(asset, posting_date) reset_depreciation_schedule(asset, self.posting_date) @@ -1188,7 +1194,9 @@ def make_item_gl_entries(self, gl_entries): else item.deferred_revenue_account ) - amount, base_amount = self.get_amount_and_base_amount(item, enable_discount_accounting) + amount, base_amount = self.get_amount_and_base_amount( + item, enable_discount_accounting + ) account_currency = get_account_currency(income_account) gl_entries.append( @@ -1212,7 +1220,7 @@ def make_item_gl_entries(self, gl_entries): # expense account gl entries if cint(self.update_stock) and erpnext.is_perpetual_inventory_enabled(self.company): - gl_entries += super(SalesInvoice, self).get_gl_entries() + gl_entries += super().get_gl_entries() def get_asset(self, item): if item.get("asset"): @@ -1275,7 +1283,6 @@ def make_loyalty_point_redemption_gle(self, gl_entries): def make_pos_gl_entries(self, gl_entries): if cint(self.is_pos): - skip_change_gl_entries = not cint( frappe.db.get_single_value("Accounts Settings", "post_change_gl_entries") ) @@ -1434,7 +1441,9 @@ def make_gle_for_rounding_adjustment(self, gl_entries): "credit_in_account_currency": flt( self.rounding_adjustment, self.precision("rounding_adjustment") ), - "credit": flt(self.base_rounding_adjustment, self.precision("base_rounding_adjustment")), + "credit": flt( + self.base_rounding_adjustment, self.precision("base_rounding_adjustment") + ), "cost_center": round_off_cost_center if self.use_company_roundoff_cost_center else (self.cost_center or round_off_cost_center), @@ -1456,7 +1465,11 @@ def update_billing_status_in_dn(self, update_modified=True): ) billed_amt = billed_amt and billed_amt[0][0] or 0 frappe.db.set_value( - "Delivery Note Item", d.dn_detail, "billed_amt", billed_amt, update_modified=update_modified + "Delivery Note Item", + d.dn_detail, + "billed_amt", + billed_amt, + update_modified=update_modified, ) updated_delivery_notes.append(d.delivery_note) elif d.so_detail: @@ -1564,7 +1577,6 @@ def make_loyalty_point_entry(self): and getdate(lp_details.from_date) <= getdate(self.posting_date) and (not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)) ): - collection_factor = lp_details.collection_factor if lp_details.collection_factor else 1.0 points_earned = cint(eligible_amount / collection_factor) @@ -1815,7 +1827,7 @@ def validate_inter_company_party(doctype, party, company, inter_company_referenc filters={"parenttype": partytype, "parent": party}, ) companies = [d.company for d in companies] - if not company in companies: + if company not in companies: frappe.throw( _( "{0} not allowed to transact with {1}. Please change the Company or add the Company in the 'Allowed To Transact With'-Section in the Customer record." @@ -1824,7 +1836,6 @@ def validate_inter_company_party(doctype, party, company, inter_company_referenc def update_linked_doc(doctype, name, inter_company_reference): - if doctype in ["Sales Invoice", "Purchase Invoice"]: ref_field = "inter_company_invoice_reference" else: @@ -1835,7 +1846,6 @@ def update_linked_doc(doctype, name, inter_company_reference): def unlink_inter_company_doc(doctype, name, inter_company_reference): - if doctype in ["Sales Invoice", "Purchase Invoice"]: ref_doc = "Purchase Invoice" if doctype == "Sales Invoice" else "Sales Invoice" ref_field = "inter_company_invoice_reference" @@ -2010,16 +2020,13 @@ def get_internal_party(parties, link_doctype, doc): def validate_inter_company_transaction(doc, doctype): - details = get_inter_company_details(doc, doctype) price_list = ( doc.selling_price_list if doctype in ["Sales Invoice", "Sales Order", "Delivery Note"] else doc.buying_price_list ) - valid_price_list = frappe.db.get_value( - "Price List", {"name": price_list, "buying": 1, "selling": 1} - ) + valid_price_list = frappe.db.get_value("Price List", {"name": price_list, "buying": 1, "selling": 1}) if not valid_price_list and not doc.is_internal_transfer(): frappe.throw(_("Selected Price List should have buying and selling fields checked.")) @@ -2280,9 +2287,7 @@ def update_pr_items(doc, sales_item_map, purchase_item_map, parent_child_map, wa for item in doc.get("items"): item.warehouse = warehouse_map.get(sales_item_map.get(item.delivery_note_item)) if not item.warehouse and item.get("purchase_order") and item.get("purchase_order_item"): - item.warehouse = frappe.db.get_value( - "Purchase Order Item", item.purchase_order_item, "warehouse" - ) + item.warehouse = frappe.db.get_value("Purchase Order Item", item.purchase_order_item, "warehouse") def get_delivery_note_details(internal_reference): @@ -2534,9 +2539,7 @@ def check_if_return_invoice_linked_with_payment_entry(self): # If a Return invoice is linked with payment entry along with other invoices, # the cancellation of the Return causes allocated amount to be greater than paid - if not frappe.db.get_single_value( - "Accounts Settings", "unlink_payment_on_cancellation_of_invoice" - ): + if not frappe.db.get_single_value("Accounts Settings", "unlink_payment_on_cancellation_of_invoice"): return payment_entries = [] diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 5993c81a1748..ea9f01510743 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2,7 +2,6 @@ # License: GNU General Public License v3. See license.txt import copy -import unittest import frappe from frappe.model.dynamic_links import get_dynamic_link_map @@ -901,7 +900,7 @@ def test_sales_invoice_gl_entry_without_perpetual_inventory(self): ] ) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][0], gle.account) self.assertEqual(expected_values[gle.account][1], gle.debit) self.assertEqual(expected_values[gle.account][2], gle.credit) @@ -927,7 +926,7 @@ def test_pos_gl_entry_with_perpetual_inventory(self): write_off_account="_Test Write Off - TCP1", ) - pr = make_purchase_receipt( + make_purchase_receipt( company="_Test Company with perpetual inventory", item_code="_Test FG Item", warehouse="Stores - TCP1", @@ -1308,7 +1307,7 @@ def test_sales_invoice_gl_entry_with_perpetual_inventory_no_item_code(self): expected_values = dict( (d[0], d) for d in [["Debtors - TCP1", 100.0, 0.0], ["Sales - TCP1", 0.0, 100.0]] ) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][0], gle.account) self.assertEqual(expected_values[gle.account][1], gle.debit) self.assertEqual(expected_values[gle.account][2], gle.credit) @@ -1332,7 +1331,7 @@ def test_sales_invoice_gl_entry_with_perpetual_inventory_non_stock_item(self): [test_records[1]["items"][0]["income_account"], 0.0, 100.0], ] ) - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][0], gle.account) self.assertEqual(expected_values[gle.account][1], gle.debit) self.assertEqual(expected_values[gle.account][2], gle.credit) @@ -1422,9 +1421,7 @@ def test_serialized(self): si.submit() self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse")) - self.assertEqual( - frappe.db.get_value("Serial No", serial_nos[0], "delivery_document_no"), si.name - ) + self.assertEqual(frappe.db.get_value("Serial No", serial_nos[0], "delivery_document_no"), si.name) return si @@ -1752,7 +1749,7 @@ def test_multi_currency_gle(self): "credit", "credit_in_account_currency", ): - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account][field], gle[field]) # cancel @@ -2294,12 +2291,8 @@ def test_create_invoice_without_terms(self): def test_duplicate_due_date_in_terms(self): si = create_sales_invoice(do_not_save=1) - si.append( - "payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50) - ) - si.append( - "payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50) - ) + si.append("payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50)) + si.append("payment_schedule", dict(due_date="2017-01-01", invoice_portion=50.00, payment_amount=50)) self.assertRaises(frappe.ValidationError, si.insert) @@ -2493,9 +2486,7 @@ def test_fixed_deferred_revenue(self): item.no_of_months = 12 item.save() - si = create_sales_invoice( - item=item.name, posting_date="2019-01-16", rate=50000, do_not_submit=True - ) + si = create_sales_invoice(item=item.name, posting_date="2019-01-16", rate=50000, do_not_submit=True) si.items[0].enable_deferred_revenue = 1 si.items[0].service_start_date = "2019-01-16" si.items[0].service_end_date = "2019-03-31" @@ -2815,21 +2806,16 @@ def test_item_tax_net_range(self): item.save() sales_invoice = create_sales_invoice(item="T Shirt", rate=700, do_not_submit=True) - self.assertEqual( - sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 12 - _TC" - ) + self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 12 - _TC") # Apply discount sales_invoice.apply_discount_on = "Net Total" sales_invoice.discount_amount = 300 sales_invoice.save() - self.assertEqual( - sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC" - ) + self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC") @change_settings("Selling Settings", {"enable_discount_accounting": 1}) def test_sales_invoice_with_discount_accounting_enabled(self): - discount_account = create_account( account_name="Discount Account", parent_account="Indirect Expenses - _TC", @@ -2847,7 +2833,6 @@ def test_sales_invoice_with_discount_accounting_enabled(self): @change_settings("Selling Settings", {"enable_discount_accounting": 1}) def test_additional_discount_for_sales_invoice_with_discount_accounting_enabled(self): - from erpnext.accounts.doctype.repost_accounting_ledger.test_repost_accounting_ledger import ( update_repost_settings, ) @@ -2860,7 +2845,7 @@ def test_additional_discount_for_sales_invoice_with_discount_accounting_enabled( company="_Test Company", ) - tds_payable_account = create_account( + create_account( account_name="TDS Payable", account_type="Tax", parent_account="Duties and Taxes - _TC", @@ -3182,9 +3167,7 @@ def test_over_billing_case_against_delivery_note(self): """ from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note - over_billing_allowance = frappe.db.get_single_value( - "Accounts Settings", "over_billing_allowance" - ) + over_billing_allowance = frappe.db.get_single_value("Accounts Settings", "over_billing_allowance") frappe.db.set_value("Accounts Settings", None, "over_billing_allowance", 0) dn = create_delivery_note() @@ -3376,7 +3359,7 @@ def test_gain_loss_with_advance_entry(self): self.assertEqual(len(journals), 1) je_type = frappe.get_cached_value("Journal Entry", journals[0], "voucher_type") self.assertEqual(je_type, "Exchange Gain Or Loss") - ledger_outstanding = frappe.db.get_all( + frappe.db.get_all( "Payment Ledger Entry", filters={"against_voucher_no": si.name, "delinked": 0}, fields=["sum(amount), sum(amount_in_account_currency)"], 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 d9009bae4c03..1bedf2c743e6 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 @@ -22,7 +22,7 @@ def validate(self): def autoname(self): if self.company and self.title: abbr = frappe.get_cached_value("Company", self.company, "abbr") - self.name = "{0} - {1}".format(self.title, abbr) + self.name = f"{self.title} - {abbr}" def set_missing_values(self): for data in self.taxes: @@ -37,10 +37,8 @@ def valdiate_taxes_and_charges_template(doc): if doc.is_default == 1: frappe.db.sql( - """update `tab{0}` set is_default = 0 - where is_default = 1 and name != %s and company = %s""".format( - doc.doctype - ), + f"""update `tab{doc.doctype}` set is_default = 0 + where is_default = 1 and name != %s and company = %s""", (doc.name, doc.company), ) diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.py b/erpnext/accounts/doctype/share_transfer/share_transfer.py index 4f49843c1eb2..21f9b1c2595c 100644 --- a/erpnext/accounts/doctype/share_transfer/share_transfer.py +++ b/erpnext/accounts/doctype/share_transfer/share_transfer.py @@ -178,7 +178,9 @@ def share_exists(self, shareholder): doc = self.get_shareholder_doc(shareholder) for entry in doc.share_balance: if ( - entry.share_type != self.share_type or entry.from_no > self.to_no or entry.to_no < self.from_no + entry.share_type != self.share_type + or entry.from_no > self.to_no + or entry.to_no < self.from_no ): continue # since query lies outside bounds elif entry.from_no <= self.from_no and entry.to_no >= self.to_no: # both inside @@ -230,7 +232,9 @@ def remove_shares(self, shareholder): for entry in current_entries: # use spaceage logic here if ( - entry.share_type != self.share_type or entry.from_no > self.to_no or entry.to_no < self.from_no + entry.share_type != self.share_type + or entry.from_no > self.to_no + or entry.to_no < self.from_no ): new_entries.append(entry) continue # since query lies outside bounds @@ -240,7 +244,9 @@ def remove_shares(self, shareholder): if entry.to_no == self.to_no: pass # nothing to append else: - new_entries.append(self.return_share_balance_entry(self.to_no + 1, entry.to_no, entry.rate)) + new_entries.append( + self.return_share_balance_entry(self.to_no + 1, entry.to_no, entry.rate) + ) else: if entry.to_no == self.to_no: new_entries.append( @@ -250,7 +256,9 @@ def remove_shares(self, shareholder): new_entries.append( self.return_share_balance_entry(entry.from_no, self.from_no - 1, entry.rate) ) - new_entries.append(self.return_share_balance_entry(self.to_no + 1, entry.to_no, entry.rate)) + new_entries.append( + self.return_share_balance_entry(self.to_no + 1, entry.to_no, entry.rate) + ) elif entry.from_no >= self.from_no and entry.to_no <= self.to_no: # split and check pass # nothing to append @@ -282,7 +290,7 @@ def return_share_balance_entry(self, from_no, to_no, rate): def get_shareholder_doc(self, shareholder): # Get Shareholder doc based on the Shareholder name if shareholder: - query_filters = {"name": shareholder} + pass name = frappe.db.get_value("Shareholder", {"name": shareholder}, "name") diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py index 1d79503a05ef..2c6d5eb5f115 100644 --- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py @@ -44,7 +44,8 @@ def validate_from_to_values(self): zero_to_values.append(d) elif d.from_value >= d.to_value: throw( - _("From value must be less than to value in row {0}").format(d.idx), FromGreaterThanToError + _("From value must be less than to value in row {0}").format(d.idx), + FromGreaterThanToError, ) # check if more than two or more rows has To Value = 0 @@ -87,9 +88,7 @@ def apply(self, doc): def get_shipping_amount_from_rules(self, value): for condition in self.get("conditions"): - if not condition.to_value or ( - flt(condition.from_value) <= flt(value) <= flt(condition.to_value) - ): + if not condition.to_value or (flt(condition.from_value) <= flt(value) <= flt(condition.to_value)): return condition.shipping_amount return 0.0 @@ -104,7 +103,9 @@ def validate_countries(self, doc): ) if shipping_country not in [d.country for d in self.countries]: frappe.throw( - _("Shipping rule not applicable for country {0} in Shipping Address").format(shipping_country) + _("Shipping rule not applicable for country {0} in Shipping Address").format( + shipping_country + ) ) def add_shipping_rule_to_tax_table(self, doc, shipping_amount): @@ -172,11 +173,9 @@ def overlap_exists_between(num_range1, num_range2): messages = [] for d1, d2 in overlaps: messages.append( - "%s-%s = %s " - % (d1.from_value, d1.to_value, fmt_money(d1.shipping_amount, currency=company_currency)) + f"{d1.from_value}-{d1.to_value} = {fmt_money(d1.shipping_amount, currency=company_currency)} " + _("and") - + " %s-%s = %s" - % (d2.from_value, d2.to_value, fmt_money(d2.shipping_amount, currency=company_currency)) + + f" {d2.from_value}-{d2.to_value} = {fmt_money(d2.shipping_amount, currency=company_currency)}" ) msgprint("\n".join(messages), raise_exception=OverlappingConditionError) diff --git a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py index a24e834c5720..a5a0ada8ba56 100644 --- a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py @@ -45,7 +45,6 @@ def test_overlapping_conditions(self): def create_shipping_rule(shipping_rule_type, shipping_rule_name): - if frappe.db.exists("Shipping Rule", shipping_rule_name): return frappe.get_doc("Shipping Rule", shipping_rule_name) diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 6e5ccb9ee8d5..fea2ae9bf8ed 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -357,9 +357,7 @@ def create_invoice(self, prorate): invoice.company = company invoice.set_posting_time = 1 invoice.posting_date = ( - self.current_invoice_start - if self.generate_invoice_at_period_start - else self.current_invoice_end + self.current_invoice_start if self.generate_invoice_at_period_start else self.current_invoice_end ) invoice.cost_center = self.cost_center @@ -561,10 +559,9 @@ def process_for_active(self): 3. Change the `Subscription` status to 'Cancelled' """ - if not self.is_current_invoice_generated( - self.current_invoice_start, self.current_invoice_end - ) and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()): - + if not self.is_current_invoice_generated(self.current_invoice_start, self.current_invoice_end) and ( + self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice() + ): prorate = frappe.db.get_single_value("Subscription Settings", "prorate") self.generate_invoice(prorate) @@ -609,10 +606,11 @@ def process_for_past_due_date(self): # Generate invoices periodically even if current invoice are unpaid if ( self.generate_new_invoices_past_due_date - and not self.is_current_invoice_generated(self.current_invoice_start, self.current_invoice_end) + and not self.is_current_invoice_generated( + self.current_invoice_start, self.current_invoice_end + ) and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()) ): - prorate = frappe.db.get_single_value("Subscription Settings", "prorate") self.generate_invoice(prorate) @@ -628,7 +626,7 @@ def has_outstanding_invoice(self): Returns `True` if the most recent invoice for the `Subscription` is not paid """ doctype = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice" - current_invoice = self.get_current_invoice() + self.get_current_invoice() invoice_list = [d.invoice for d in self.invoices] outstanding_invoices = frappe.get_all( diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py index 89ba0c8055e6..2f0b87e9ea21 100644 --- a/erpnext/accounts/doctype/subscription/test_subscription.py +++ b/erpnext/accounts/doctype/subscription/test_subscription.py @@ -1,7 +1,6 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.tests.utils import FrappeTestCase @@ -85,9 +84,7 @@ def create_parties(): customer = frappe.new_doc("Customer") customer.customer_name = "_Test Subscription Customer" customer.billing_currency = "USD" - customer.append( - "accounts", {"company": "_Test Company", "account": "_Test Receivable USD - _TC"} - ) + customer.append("accounts", {"company": "_Test Company", "account": "_Test Receivable USD - _TC"}) customer.insert() @@ -358,9 +355,7 @@ def test_subscription_cancellation_invoices(self): invoice = subscription.get_current_invoice() diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) - plan_days = flt( - date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1 - ) + plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff / plan_days) self.assertEqual( @@ -417,9 +412,7 @@ def test_subscription_cancellation_invoices_with_prorata_true(self): invoice = subscription.get_current_invoice() diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1) - plan_days = flt( - date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1 - ) + plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1) prorate_factor = flt(diff / plan_days) self.assertEqual(flt(invoice.grand_total, 2), flt(prorate_factor * 900, 2)) diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index 75223c2ccca2..4c4a812dd77e 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -21,9 +21,7 @@ def validate_interval_count(self): @frappe.whitelist() -def get_plan_rate( - plan, quantity=1, customer=None, start_date=None, end_date=None, prorate_factor=1 -): +def get_plan_rate(plan, quantity=1, customer=None, start_date=None, end_date=None, prorate_factor=1): plan = frappe.get_doc("Subscription Plan", plan) if plan.price_determination == "Fixed Rate": return plan.cost * prorate_factor diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 4d201292ed2a..959c3b574566 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -82,27 +82,23 @@ def validate_filters(self): for d in filters: if conds: conds += " and " - conds += """ifnull({0}, '') = {1}""".format(d, frappe.db.escape(cstr(filters[d]))) + conds += f"""ifnull({d}, '') = {frappe.db.escape(cstr(filters[d]))}""" if self.from_date and self.to_date: - conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or - (to_date > '{from_date}' and to_date < '{to_date}') or - ('{from_date}' > from_date and '{from_date}' < to_date) or - ('{from_date}' = from_date and '{to_date}' = to_date))""".format( - from_date=self.from_date, to_date=self.to_date - ) + conds += f""" and ((from_date > '{self.from_date}' and from_date < '{self.to_date}') or + (to_date > '{self.from_date}' and to_date < '{self.to_date}') or + ('{self.from_date}' > from_date and '{self.from_date}' < to_date) or + ('{self.from_date}' = from_date and '{self.to_date}' = to_date))""" elif self.from_date and not self.to_date: - conds += """ and to_date > '{from_date}'""".format(from_date=self.from_date) + conds += f""" and to_date > '{self.from_date}'""" elif self.to_date and not self.from_date: - conds += """ and from_date < '{to_date}'""".format(to_date=self.to_date) + conds += f""" and from_date < '{self.to_date}'""" tax_rule = frappe.db.sql( - "select name, priority \ - from `tabTax Rule` where {0} and name != '{1}'".format( - conds, self.name - ), + f"select name, priority \ + from `tabTax Rule` where {conds} and name != '{self.name}'", as_dict=1, ) @@ -117,7 +113,6 @@ def validate_use_for_shopping_cart(self): and cint(frappe.db.get_single_value("E Commerce Settings", "enabled")) and not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1, "name": ["!=", self.name]}) ): - self.use_for_shopping_cart = 1 frappe.msgprint( _( @@ -174,27 +169,25 @@ def get_tax_template(posting_date, args): conditions.append("(from_date is null) and (to_date is null)") conditions.append( - "ifnull(tax_category, '') = {0}".format(frappe.db.escape(cstr(args.get("tax_category")))) + "ifnull(tax_category, '') = {}".format(frappe.db.escape(cstr(args.get("tax_category")))) ) if "tax_category" in args.keys(): del args["tax_category"] for key, value in args.items(): if key == "use_for_shopping_cart": - conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0)) + conditions.append(f"use_for_shopping_cart = {1 if value else 0}") elif key == "customer_group": if not value: value = get_root_of("Customer Group") customer_group_condition = get_customer_group_condition(value) - conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition)) + conditions.append(f"ifnull({key}, '') in ('', {customer_group_condition})") else: - conditions.append("ifnull({0}, '') in ('', {1})".format(key, frappe.db.escape(cstr(value)))) + conditions.append(f"ifnull({key}, '') in ('', {frappe.db.escape(cstr(value))})") tax_rule = frappe.db.sql( """select * from `tabTax Rule` - where {0}""".format( - " and ".join(conditions) - ), + where {}""".format(" and ".join(conditions)), as_dict=True, ) @@ -219,7 +212,7 @@ def cmp(a, b): )[0] tax_template = rule.sales_tax_template or rule.purchase_tax_template - doctype = "{0} Taxes and Charges Template".format(rule.tax_type) + doctype = f"{rule.tax_type} Taxes and Charges Template" if frappe.db.get_value(doctype, tax_template, "disabled") == 1: return None @@ -229,9 +222,7 @@ def cmp(a, b): def get_customer_group_condition(customer_group): condition = "" - customer_groups = [ - "%s" % (frappe.db.escape(d.name)) for d in get_parent_customer_groups(customer_group) - ] + customer_groups = ["%s" % (frappe.db.escape(d.name)) for d in get_parent_customer_groups(customer_group)] if customer_groups: condition = ",".join(["%s"] * len(customer_groups)) % (tuple(customer_groups)) return condition 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 1d1955e3d51a..58ce2840b4b6 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -36,13 +36,11 @@ def validate_accounts(self): def validate_thresholds(self): for d in self.get("rates"): - if ( - d.cumulative_threshold and d.single_threshold and d.cumulative_threshold < d.single_threshold - ): + if d.cumulative_threshold and d.single_threshold and d.cumulative_threshold < d.single_threshold: frappe.throw( - _("Row #{0}: Cumulative threshold cannot be less than Single Transaction threshold").format( - d.idx - ) + _( + "Row #{0}: Cumulative threshold cannot be less than Single Transaction threshold" + ).format(d.idx) ) @@ -295,9 +293,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"): doctype = "Purchase Invoice" if party_type == "Supplier" else "Sales Invoice" field = ( - "base_tax_withholding_net_total as base_net_total" - if party_type == "Supplier" - else "base_net_total" + "base_tax_withholding_net_total as base_net_total" if party_type == "Supplier" else "base_net_total" ) voucher_wise_amount = {} vouchers = [] @@ -351,9 +347,7 @@ def get_invoice_vouchers(parties, tax_details, company, party_type="Supplier"): return vouchers, voucher_wise_amount -def get_advance_vouchers( - parties, company=None, from_date=None, to_date=None, party_type="Supplier" -): +def get_advance_vouchers(parties, company=None, from_date=None, to_date=None, party_type="Supplier"): """ Use Payment Ledger to fetch unallocated Advance Payments """ @@ -374,9 +368,7 @@ def get_advance_vouchers( if from_date and to_date: conditions.append(ple.posting_date[from_date:to_date]) - advances = ( - qb.from_(ple).select(ple.voucher_no).distinct().where(Criterion.all(conditions)).run(as_list=1) - ) + advances = qb.from_(ple).select(ple.voucher_no).distinct().where(Criterion.all(conditions)).run(as_list=1) if advances: advances = [x[0] for x in advances] @@ -542,9 +534,7 @@ def get_tcs_amount(parties, inv, tax_details, vouchers, adv_vouchers): conditions.append(ple.voucher_no == ple.against_voucher_no) conditions.append(ple.company == inv.company) - advances = ( - qb.from_(ple).select(Abs(Sum(ple.amount))).where(Criterion.all(conditions)).run(as_list=1) - ) + (qb.from_(ple).select(Abs(Sum(ple.amount))).where(Criterion.all(conditions)).run(as_list=1)) advance_amt = ( qb.from_(ple).select(Abs(Sum(ple.amount))).where(Criterion.all(conditions)).run()[0][0] or 0.0 @@ -603,9 +593,7 @@ def get_limit_consumed(ldc, parties): return limit_consumed -def get_lower_deduction_amount( - current_amount, limit_consumed, certificate_limit, rate, tax_details -): +def get_lower_deduction_amount(current_amount, limit_consumed, certificate_limit, rate, tax_details): if certificate_limit - flt(limit_consumed) - flt(current_amount) >= 0: return current_amount * rate / 100 else: @@ -617,9 +605,7 @@ def get_lower_deduction_amount( def is_valid_certificate(ldc, posting_date, limit_consumed): available_amount = flt(ldc.certificate_limit) - flt(limit_consumed) - if ( - getdate(ldc.valid_from) <= getdate(posting_date) <= getdate(ldc.valid_upto) - ) and available_amount > 0: + if (getdate(ldc.valid_from) <= getdate(posting_date) <= getdate(ldc.valid_upto)) and available_amount > 0: return True return False diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py index 0a749f966520..a5509619583d 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py @@ -96,9 +96,7 @@ def test_single_threshold_tds(self): def test_tax_withholding_category_checks(self): invoices = [] - frappe.db.set_value( - "Supplier", "Test TDS Supplier3", "tax_withholding_category", "New TDS Category" - ) + frappe.db.set_value("Supplier", "Test TDS Supplier3", "tax_withholding_category", "New TDS Category") # First Invoice with no tds check pi = create_purchase_invoice(supplier="Test TDS Supplier3", rate=20000, do_not_save=True) @@ -453,7 +451,7 @@ def test_tax_withholding_via_payment_entry_for_advances(self): pe3.save() pe3.submit() - self.assertEquals(pe3.get("taxes")[0].tax_amount, 1200) + self.assertEqual(pe3.get("taxes")[0].tax_amount, 1200) pe1.cancel() pe2.cancel() pe3.cancel() @@ -850,9 +848,7 @@ def create_tax_withholding_category( ).insert() -def create_lower_deduction_certificate( - supplier, tax_withholding_category, tax_rate, certificate_no, limit -): +def create_lower_deduction_certificate(supplier, tax_withholding_category, tax_rate, certificate_no, limit): fiscal_year = get_fiscal_year(today(), company="_Test Company") if not frappe.db.exists("Lower Deduction Certificate", certificate_no): frappe.get_doc( diff --git a/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py b/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py index 57f66dd21dba..882dd1d6dabf 100644 --- a/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py +++ b/erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py @@ -93,7 +93,7 @@ def test_01_unreconcile_invoice(self): unreconcile.add_references() self.assertEqual(len(unreconcile.allocations), 2) allocations = [x.reference_name for x in unreconcile.allocations] - self.assertEquals([si1.name, si2.name], allocations) + self.assertEqual([si1.name, si2.name], allocations) # unreconcile si1 for x in unreconcile.allocations: if x.reference_name != si1.name: @@ -158,7 +158,7 @@ def test_02_unreconcile_one_payment_from_multi_payments(self): unreconcile.add_references() self.assertEqual(len(unreconcile.allocations), 2) allocations = [x.reference_name for x in unreconcile.allocations] - self.assertEquals([si1.name, si2.name], allocations) + self.assertEqual([si1.name, si2.name], allocations) # unreconcile si1 from pe2 for x in unreconcile.allocations: if x.reference_name != si1.name: @@ -216,7 +216,7 @@ def test_03_unreconciliation_on_multi_currency_invoice(self): unreconcile.add_references() self.assertEqual(len(unreconcile.allocations), 2) allocations = [x.reference_name for x in unreconcile.allocations] - self.assertEquals([si1.name, si2.name], allocations) + self.assertEqual([si1.name, si2.name], allocations) # unreconcile si1 from pe for x in unreconcile.allocations: if x.reference_name != si1.name: @@ -301,7 +301,7 @@ def test_04_unreconciliation_on_multi_currency_invoice(self): unreconcile.add_references() self.assertEqual(len(unreconcile.allocations), 2) allocations = [x.reference_name for x in unreconcile.allocations] - self.assertEquals([si1.name, si2.name], allocations) + self.assertEqual([si1.name, si2.name], allocations) # unreconcile si1 from pe2 for x in unreconcile.allocations: if x.reference_name != si1.name: @@ -353,7 +353,7 @@ def test_05_unreconcile_order(self): unreconcile.add_references() self.assertEqual(len(unreconcile.allocations), 1) allocations = [x.reference_name for x in unreconcile.allocations] - self.assertEquals([so.name], allocations) + self.assertEqual([so.name], allocations) # unreconcile so unreconcile.save().submit() diff --git a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py index dd714573b1b2..091bccf5099e 100644 --- a/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py +++ b/erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py @@ -18,7 +18,7 @@ class UnreconcilePayment(Document): def validate(self): self.supported_types = ["Payment Entry", "Journal Entry"] - if not self.voucher_type in self.supported_types: + if self.voucher_type not in self.supported_types: frappe.throw(_("Only {0} are supported").format(comma_and(self.supported_types))) @frappe.whitelist() @@ -70,7 +70,7 @@ def on_submit(self): @frappe.whitelist() -def doc_has_references(doctype: str = None, docname: str = None): +def doc_has_references(doctype: str | None = None, docname: str | None = None): if doctype in ["Sales Invoice", "Purchase Invoice"]: return frappe.db.count( "Payment Ledger Entry", @@ -85,7 +85,7 @@ def doc_has_references(doctype: str = None, docname: str = None): @frappe.whitelist() def get_linked_payments_for_doc( - company: str = None, doctype: str = None, docname: str = None + company: str | None = None, doctype: str | None = None, docname: str | None = None ) -> list: if company and doctype and docname: _dt = doctype diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 432abc250b12..58601f3b08d2 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -78,7 +78,7 @@ def make_acc_dimensions_offsetting_entry(gl_map): "credit": credit, "debit_in_account_currency": debit, "credit_in_account_currency": credit, - "remarks": _("Offsetting for Accounting Dimension") + " - {0}".format(dimension.name), + "remarks": _("Offsetting for Accounting Dimension") + f" - {dimension.name}", "against_voucher": None, } ) @@ -179,9 +179,7 @@ def process_gl_map(gl_map, merge_entries=True, precision=None): def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None): - cost_center_allocation = get_cost_center_allocation_data( - gl_map[0]["company"], gl_map[0]["posting_date"] - ) + cost_center_allocation = get_cost_center_allocation_data(gl_map[0]["company"], gl_map[0]["posting_date"]) if not cost_center_allocation: return gl_map @@ -190,9 +188,7 @@ def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None): cost_center = d.get("cost_center") # Validate budget against main cost center - validate_expense_against_budget( - d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision) - ) + validate_expense_against_budget(d, expense_amount=flt(d.debit, precision) - flt(d.credit, precision)) if cost_center and cost_center_allocation.get(cost_center): for sub_cost_center, percentage in cost_center_allocation.get(cost_center, {}).items(): @@ -224,9 +220,7 @@ def get_cost_center_allocation_data(company, posting_date): cc_allocation = frappe._dict() for d in records: - cc_allocation.setdefault(d.main_cost_center, frappe._dict()).setdefault( - d.cost_center, d.percentage - ) + cc_allocation.setdefault(d.main_cost_center, frappe._dict()).setdefault(d.cost_center, d.percentage) return cc_allocation @@ -540,9 +534,7 @@ def update_accounting_dimensions(round_off_gle): round_off_gle[dimension] = dimension_values.get(dimension) -def get_round_off_account_and_cost_center( - company, voucher_type, voucher_no, use_company_default=False -): +def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use_company_default=False): round_off_account, round_off_cost_center = frappe.get_cached_value( "Company", company, ["round_off_account", "round_off_cost_center"] ) or [None, None] @@ -650,9 +642,7 @@ def check_freezing_date(posting_date, adv_adj=False): def validate_against_pcv(is_opening, posting_date, company): - if is_opening and frappe.db.exists( - "Period Closing Voucher", {"docstatus": 1, "company": company} - ): + if is_opening and frappe.db.exists("Period Closing Voucher", {"docstatus": 1, "company": company}): frappe.throw( _("Opening Entry can not be created after Period Closing Voucher is created."), title=_("Invalid Opening Entry"), @@ -663,9 +653,7 @@ def validate_against_pcv(is_opening, posting_date, company): ) if last_pcv_date and getdate(posting_date) <= getdate(last_pcv_date): - message = _("Books have been closed till the period ending on {0}").format( - formatdate(last_pcv_date) - ) + message = _("Books have been closed till the period ending on {0}").format(formatdate(last_pcv_date)) message += "
" message += _("You cannot create/amend any accounting entries till this date.") frappe.throw(message, title=_("Period Closed")) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 8f8b9a81f8a0..2b95e16f3564 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -2,8 +2,6 @@ # License: GNU General Public License v3. See license.txt -from typing import Optional - import frappe from frappe import _, msgprint, qb, scrub from frappe.contacts.doctype.address.address import get_company_address, get_default_address @@ -69,7 +67,6 @@ def get_party_details( shipping_address=None, pos_profile=None, ): - if not party: return {} if not frappe.db.exists(party_type, party): @@ -153,9 +150,7 @@ def _get_party_details( party_details["taxes_and_charges"] = tax_template if cint(fetch_payment_terms_template): - party_details["payment_terms_template"] = get_payment_terms_template( - party.name, party_type, company - ) + party_details["payment_terms_template"] = get_payment_terms_template(party.name, party_type, company) if not party_details.get("currency"): party_details["currency"] = currency @@ -173,9 +168,7 @@ def _get_party_details( # supplier tax withholding category if party_type == "Supplier" and party: - party_details["supplier_tds"] = frappe.get_value( - party_type, party.name, "tax_withholding_category" - ) + party_details["supplier_tds"] = frappe.get_value(party_type, party.name, "tax_withholding_category") if not party_details.get("tax_category") and pos_profile: party_details["tax_category"] = frappe.get_value("POS Profile", pos_profile, "tax_category") @@ -195,12 +188,8 @@ def set_address_details( *, ignore_permissions=False, ): - billing_address_field = ( - "customer_address" if party_type == "Lead" else party_type.lower() + "_address" - ) - party_details[billing_address_field] = party_address or get_default_address( - party_type, party.name - ) + billing_address_field = "customer_address" if party_type == "Lead" else party_type.lower() + "_address" + party_details[billing_address_field] = party_address or get_default_address(party_type, party.name) if doctype: party_details.update( get_fetch_values(doctype, billing_address_field, party_details[billing_address_field]) @@ -310,9 +299,7 @@ def set_contact_details(party_details, party, party_type): "department as contact_department", ] - contact_details = frappe.db.get_value( - "Contact", party_details.contact_person, fields, as_dict=True - ) + contact_details = frappe.db.get_value("Contact", party_details.contact_person, fields, as_dict=True) contact_details.contact_display = " ".join( filter( @@ -338,9 +325,7 @@ def set_other_values(party_details, party, party_type): party_details[f] = party.get(f) # fields prepended with default in Customer doctype - for f in ["currency"] + ( - ["sales_partner", "commission_rate"] if party_type == "Customer" else [] - ): + for f in ["currency"] + (["sales_partner", "commission_rate"] if party_type == "Customer" else []): if party.get("default_" + f): party_details[f] = party.get("default_" + f) @@ -377,14 +362,10 @@ def set_price_list(party_details, party, party_type, given_price_list, pos=None) "Price List", price_list, "currency", cache=True ) - party_details[ - "selling_price_list" if party.doctype == "Customer" else "buying_price_list" - ] = price_list + party_details["selling_price_list" if party.doctype == "Customer" else "buying_price_list"] = price_list -def set_account_and_due_date( - party, account, party_type, company, posting_date, bill_date, doctype -): +def set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype): if doctype not in ["POS Invoice", "Sales Invoice", "Purchase Invoice"]: # not an invoice return {party_type.lower(): party} @@ -449,9 +430,7 @@ def get_party_account(party_type, party=None, company=None): @frappe.whitelist() def get_party_bank_account(party_type, party): - return frappe.db.get_value( - "Bank Account", {"party_type": party_type, "party": party, "is_default": 1} - ) + return frappe.db.get_value("Bank Account", {"party_type": party_type, "party": party, "is_default": 1}) def get_party_account_currency(party_type, party, company): @@ -573,9 +552,7 @@ def get_due_date(posting_date, party_type, party, company=None, bill_date=None): template_name = get_payment_terms_template(party, party_type, company) if template_name: - due_date = get_due_date_from_template(template_name, posting_date, bill_date).strftime( - "%Y-%m-%d" - ) + due_date = get_due_date_from_template(template_name, posting_date, bill_date).strftime("%Y-%m-%d") else: if party_type == "Supplier": supplier_group = frappe.get_cached_value(party_type, party, "supplier_group") @@ -735,7 +712,6 @@ def get_payment_terms_template(party_name, party_type, company=None): def validate_party_frozen_disabled(party_type, party_name): - if frappe.flags.ignore_party_validation: return @@ -748,7 +724,7 @@ def validate_party_frozen_disabled(party_type, party_name): frozen_accounts_modifier = frappe.db.get_single_value( "Accounts Settings", "frozen_accounts_modifier" ) - if not frozen_accounts_modifier in frappe.get_roles(): + if frozen_accounts_modifier not in frappe.get_roles(): frappe.throw(_("{0} {1} is frozen").format(party_type, party_name), PartyFrozen) elif party_type == "Employee": @@ -871,9 +847,7 @@ def get_dashboard_info(party_type, party, loyalty_program=None): party_account_currency = get_party_account_currency(party_type, party, d.company) if party_account_currency == company_default_currency: - billing_this_year = flt( - company_wise_billing_this_year.get(d.company, {}).get("base_grand_total") - ) + billing_this_year = flt(company_wise_billing_this_year.get(d.company, {}).get("base_grand_total")) else: billing_this_year = flt(company_wise_billing_this_year.get(d.company, {}).get("grand_total")) @@ -899,7 +873,7 @@ def get_dashboard_info(party_type, party, loyalty_program=None): return company_wise_info -def get_party_shipping_address(doctype: str, name: str) -> Optional[str]: +def get_party_shipping_address(doctype: str, name: str) -> str | None: """ Returns an Address name (best guess) for the given doctype and name for which `address_type == 'Shipping'` is true. and/or `is_shipping_address = 1`. @@ -965,7 +939,7 @@ def get_partywise_advanced_payment_amount( return frappe._dict(data) -def get_default_contact(doctype: str, name: str) -> Optional[str]: +def get_default_contact(doctype: str, name: str) -> str | None: """ Returns contact name only if there is a primary contact for given doctype and name. diff --git a/erpnext/accounts/report/account_balance/account_balance.py b/erpnext/accounts/report/account_balance/account_balance.py index 824a965cdcf3..6f9f7ebcb8da 100644 --- a/erpnext/accounts/report/account_balance/account_balance.py +++ b/erpnext/accounts/report/account_balance/account_balance.py @@ -61,7 +61,6 @@ def get_conditions(filters): def get_data(filters): - data = [] conditions = get_conditions(filters) accounts = frappe.db.get_all( diff --git a/erpnext/accounts/report/accounts_payable/test_accounts_payable.py b/erpnext/accounts/report/accounts_payable/test_accounts_payable.py index b4cb25ff1b8c..f5c9d16073e2 100644 --- a/erpnext/accounts/report/accounts_payable/test_accounts_payable.py +++ b/erpnext/accounts/report/accounts_payable/test_accounts_payable.py @@ -1,16 +1,10 @@ -import unittest - import frappe -from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import add_days, flt, getdate, today +from frappe.tests.utils import FrappeTestCase +from frappe.utils import today -from erpnext import get_default_cost_center -from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice -from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.report.accounts_payable.accounts_payable import execute from erpnext.accounts.test.accounts_mixin import AccountsTestMixin -from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase): diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 609a4abe66f6..dcfd85afddb3 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -40,24 +40,20 @@ def execute(filters=None): return ReceivablePayableReport(filters).run(args) -class ReceivablePayableReport(object): +class ReceivablePayableReport: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) self.qb_selection_filter = [] self.ple = qb.DocType("Payment Ledger Entry") self.filters.report_date = getdate(self.filters.report_date or nowdate()) self.age_as_on = ( - getdate(nowdate()) - if self.filters.report_date > getdate(nowdate()) - else self.filters.report_date + getdate(nowdate()) if self.filters.report_date > getdate(nowdate()) else self.filters.report_date ) def run(self, args): self.filters.update(args) self.set_defaults() - self.party_naming_by = frappe.db.get_value( - args.get("naming_by")[0], None, args.get("naming_by")[1] - ) + self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1]) self.get_columns() self.get_data() self.get_chart_data() @@ -72,9 +68,7 @@ def set_defaults(self): self.currency_precision = get_currency_precision() or 2 self.dr_or_cr = "debit" if self.filters.account_type == "Receivable" else "credit" self.account_type = self.filters.account_type - self.party_type = frappe.db.get_all( - "Party Type", {"account_type": self.account_type}, pluck="name" - ) + self.party_type = frappe.db.get_all("Party Type", {"account_type": self.account_type}, pluck="name") self.party_details = {} self.invoices = set() self.skip_total_row = 0 @@ -128,7 +122,7 @@ def init_voucher_balance(self): else: key = (ple.account, ple.voucher_type, ple.voucher_no, ple.party) - if not key in self.voucher_balance: + if key not in self.voucher_balance: self.voucher_balance[key] = frappe._dict( voucher_type=ple.voucher_type, voucher_no=ple.voucher_no, @@ -281,7 +275,7 @@ def append_subtotal_row(self, party): def build_data(self): # set outstanding for all the accumulated balances # as we can use this to filter out invoices without outstanding - for key, row in self.voucher_balance.items(): + for _key, row in self.voucher_balance.items(): row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision) row.outstanding_in_account_currency = flt( row.invoiced_in_account_currency @@ -295,7 +289,7 @@ def build_data(self): must_consider = False if self.filters.get("for_revaluation_journals"): if (abs(row.outstanding) > 0.0 / 10**self.currency_precision) or ( - (abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision) + abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision ): must_consider = True else: @@ -481,19 +475,17 @@ def allocate_outstanding_based_on_payment_terms(self, row): def get_payment_terms(self, row): # build payment_terms for row payment_terms_details = frappe.db.sql( - """ + f""" select si.name, si.party_account_currency, si.currency, si.conversion_rate, si.total_advance, ps.due_date, ps.payment_term, ps.payment_amount, ps.base_payment_amount, ps.description, ps.paid_amount, ps.discounted_amount - from `tab{0}` si, `tabPayment Schedule` ps + from `tab{row.voucher_type}` si, `tabPayment Schedule` ps where si.name = ps.parent and si.name = %s order by ps.paid_amount desc, due_date - """.format( - row.voucher_type - ), + """, row.voucher_no, as_dict=1, ) @@ -737,9 +729,7 @@ def get_ageing_data(self, entry_date, row): row.age = (getdate(self.age_as_on) - getdate(entry_date)).days or 0 index = None - if not ( - self.filters.range1 and self.filters.range2 and self.filters.range3 and self.filters.range4 - ): + if not (self.filters.range1 and self.filters.range2 and self.filters.range3 and self.filters.range4): self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4 = ( 30, 60, @@ -765,12 +755,10 @@ def get_ple_entries(self): if self.filters.show_future_payments: self.qb_selection_filter.append( - ( - self.ple.posting_date.lte(self.filters.report_date) - | ( - (self.ple.voucher_no == self.ple.against_voucher_no) - & (Date(self.ple.creation).lte(self.filters.report_date)) - ) + self.ple.posting_date.lte(self.filters.report_date) + | ( + (self.ple.voucher_no == self.ple.against_voucher_no) + & (Date(self.ple.creation).lte(self.filters.report_date)) ) ) else: @@ -838,7 +826,7 @@ def prepare_conditions(self): self.qb_selection_filter = [] self.or_filters = [] - for party_type in self.party_type: + for _party_type in self.party_type: self.add_common_filters() if self.account_type == "Receivable": @@ -975,7 +963,7 @@ def is_invoice(self, ple): return True def get_party_details(self, party): - if not party in self.party_details: + if party not in self.party_details: if self.account_type == "Receivable": fields = ["customer_name", "territory", "customer_group", "customer_primary_contact"] diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index 01129824bca6..a65e424173c2 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -1,11 +1,8 @@ -import unittest - import frappe from frappe import qb from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, flt, getdate, today -from erpnext import get_default_cost_center from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.report.accounts_receivable.accounts_receivable import execute @@ -126,7 +123,6 @@ def test_accounts_receivable(self): # check invoice grand total and invoiced column's value for 3 payment terms si = self.create_sales_invoice() - name = si.name report = execute(filters) @@ -218,7 +214,7 @@ def test_cr_note_flag_to_update_self(self): [0, 0, 100.0, 0.0, -100.0, cr_note.name], ] self.assertEqual(len(report[1]), 2) - si_row = [ + si_row = next( [ row.invoice_grand_total, row.invoiced, @@ -229,9 +225,9 @@ def test_cr_note_flag_to_update_self(self): ] for row in report[1] if row.voucher_no == si.name - ][0] + ) - cr_note_row = [ + cr_note_row = next( [ row.invoice_grand_total, row.invoiced, @@ -242,7 +238,7 @@ def test_cr_note_flag_to_update_self(self): ] for row in report[1] if row.voucher_no == cr_note.name - ][0] + ) self.assertEqual(expected_data_after_credit_note[0], si_row) self.assertEqual(expected_data_after_credit_note[1], cr_note_row) @@ -317,9 +313,7 @@ def test_exchange_revaluation_for_party(self): err.extend("accounts", accounts) err.accounts[0].new_exchange_rate = 85 row = err.accounts[0] - row.new_balance_in_base_currency = flt( - row.new_exchange_rate * flt(row.balance_in_account_currency) - ) + row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency)) row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency) err.set_total_gain_loss() err = err.save().submit() @@ -340,7 +334,7 @@ def test_exchange_revaluation_for_party(self): report = execute(filters) expected_data_for_err = [0, -500, 0, 500] - row = [x for x in report[1] if x.voucher_type == je.doctype and x.voucher_no == je.name][0] + row = next(x for x in report[1] if x.voucher_type == je.doctype and x.voucher_no == je.name) self.assertEqual( expected_data_for_err, [ @@ -575,7 +569,7 @@ def test_sales_person(self): self.assertEqual(expected_data, [row.invoiced, row.outstanding, row.sales_person]) def test_cost_center_filter(self): - si = self.create_sales_invoice() + self.create_sales_invoice() filters = { "company": self.company, "report_date": today(), @@ -592,7 +586,7 @@ def test_cost_center_filter(self): self.assertEqual(expected_data, [row.invoiced, row.outstanding, row.cost_center]) def test_customer_group_filter(self): - si = self.create_sales_invoice() + self.create_sales_invoice() cus_group = frappe.db.get_value("Customer", self.customer, "customer_group") filters = { "company": self.company, @@ -614,7 +608,7 @@ def test_customer_group_filter(self): self.assertEqual(len(report), 0) def test_multi_customer_group_filter(self): - si = self.create_sales_invoice() + self.create_sales_invoice() cus_group = frappe.db.get_value("Customer", self.customer, "customer_group") # Create a list of customer groups, e.g., ["Group1", "Group2"] cus_groups_list = [cus_group, "_Test Customer Group 1"] @@ -727,7 +721,6 @@ def test_usd_customer_filter(self): si.conversion_rate = 80 si.debit_to = self.debtors_usd si.save().submit() - name = si.name # check invoice grand total and invoiced column's value for 3 payment terms report = execute(filters) @@ -787,9 +780,7 @@ def test_multi_select_party_filter(self): def test_report_output_if_party_is_missing(self): acc_name = "Additional Debtors" - if not frappe.db.get_value( - "Account", filters={"account_name": acc_name, "company": self.company} - ): + if not frappe.db.get_value("Account", filters={"account_name": acc_name, "company": self.company}): additional_receivable_acc = frappe.get_doc( { "doctype": "Account", 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 a92f960fdf0e..b1c02b384525 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -23,12 +23,8 @@ def execute(filters=None): class AccountsReceivableSummary(ReceivablePayableReport): def run(self, args): self.account_type = args.get("account_type") - self.party_type = frappe.db.get_all( - "Party Type", {"account_type": self.account_type}, pluck="name" - ) - self.party_naming_by = frappe.db.get_value( - args.get("naming_by")[0], None, args.get("naming_by")[1] - ) + self.party_type = frappe.db.get_all("Party Type", {"account_type": self.account_type}, pluck="name") + self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1]) self.get_columns() self.get_data(args) return self.columns, self.data diff --git a/erpnext/accounts/report/accounts_receivable_summary/test_accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/test_accounts_receivable_summary.py index 3ee35a114d15..4ef607bab286 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/test_accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/test_accounts_receivable_summary.py @@ -1,5 +1,3 @@ -import unittest - import frappe from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import today diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py index bdc8d8504f87..1754780e3460 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py @@ -62,7 +62,7 @@ def get_asset_categories(filters): if filters.get("asset_category"): condition += " and asset_category = %(asset_category)s" return frappe.db.sql( - """ + f""" SELECT asset_category, ifnull(sum(case when purchase_date < %(from_date)s then case when ifnull(disposal_date, 0) = 0 or disposal_date >= %(from_date)s then @@ -101,11 +101,9 @@ def get_asset_categories(filters): 0 end), 0) as cost_of_scrapped_asset from `tabAsset` - where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s {} + where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s {condition} group by asset_category - """.format( - condition - ), + """, { "to_date": filters.to_date, "from_date": filters.from_date, @@ -170,9 +168,7 @@ def get_assets(filters): where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {0} group by a.asset_category) as results group by results.asset_category - """.format( - condition - ), + """.format(condition), {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1, ) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index 5d6ca23a6b2e..2106451bd1a0 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -180,7 +180,6 @@ def get_report_summary( filters, consolidated=False, ): - net_asset, net_liability, net_equity, net_provisional_profit_loss = 0.0, 0.0, 0.0, 0.0 if filters.get("accumulated_values"): diff --git a/erpnext/accounts/report/balance_sheet/test_balance_sheet.py b/erpnext/accounts/report/balance_sheet/test_balance_sheet.py index 3cb6efebee35..ca357ece1d1f 100644 --- a/erpnext/accounts/report/balance_sheet/test_balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/test_balance_sheet.py @@ -13,15 +13,13 @@ def test_balance_sheet(self): from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import ( create_sales_invoice, - make_sales_invoice, ) - from erpnext.accounts.utils import get_fiscal_year frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company 6'") frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") - pi = make_purchase_invoice( + make_purchase_invoice( company="_Test Company 6", warehouse="Finished Goods - _TC6", expense_account="Cost of Goods Sold - _TC6", @@ -29,7 +27,7 @@ def test_balance_sheet(self): qty=10, rate=100, ) - si = create_sales_invoice( + create_sales_invoice( company="_Test Company 6", debit_to="Debtors - _TC6", income_account="Sales - _TC6", diff --git a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py index cb7445546f1e..ab8bdd7afbd0 100644 --- a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py +++ b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py @@ -63,31 +63,27 @@ def get_conditions(filters): def get_entries(filters): conditions = get_conditions(filters) journal_entries = frappe.db.sql( - """SELECT + f"""SELECT "Journal Entry", jv.name, jv.posting_date, jv.cheque_no, jv.clearance_date, jvd.against_account, jvd.debit - jvd.credit FROM `tabJournal Entry Account` jvd, `tabJournal Entry` jv WHERE - jvd.parent = jv.name and jv.docstatus=1 and jvd.account = %(account)s {0} - order by posting_date DESC, jv.name DESC""".format( - conditions - ), + jvd.parent = jv.name and jv.docstatus=1 and jvd.account = %(account)s {conditions} + order by posting_date DESC, jv.name DESC""", filters, as_list=1, ) payment_entries = frappe.db.sql( - """SELECT + f"""SELECT "Payment Entry", name, posting_date, reference_no, clearance_date, party, if(paid_from=%(account)s, ((paid_amount * -1) - total_taxes_and_charges) , received_amount) FROM `tabPayment Entry` WHERE - docstatus=1 and (paid_from = %(account)s or paid_to = %(account)s) {0} - order by posting_date DESC, name DESC""".format( - conditions - ), + docstatus=1 and (paid_from = %(account)s or paid_to = %(account)s) {conditions} + order by posting_date DESC, name DESC""", filters, as_list=1, ) diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py index fbc1a69ddc59..7c2389d8dd5f 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -35,10 +35,7 @@ def execute(filters=None): amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters) bank_bal = ( - flt(balance_as_per_system) - - flt(total_debit) - + flt(total_credit) - + amounts_not_reflected_in_system + flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system ) data += [ @@ -220,7 +217,7 @@ def get_loan_entries(filters): ) if doctype == "Loan Repayment" and frappe.db.has_column("Loan Repayment", "repay_from_salary"): - query = query.where((loan_doc.repay_from_salary == 0)) + query = query.where(loan_doc.repay_from_salary == 0) entries = query.run(as_dict=1) loan_docs.extend(entries) @@ -282,7 +279,7 @@ def get_loan_amount(filters): ) if doctype == "Loan Repayment" and frappe.db.has_column("Loan Repayment", "repay_from_salary"): - query = query.where((loan_doc.repay_from_salary == 0)) + query = query.where(loan_doc.repay_from_salary == 0) amount = query.run()[0][0] total_amount += flt(amount) diff --git a/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py b/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py index 62bee82590b2..f6efc8a685c3 100644 --- a/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py +++ b/erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.py @@ -30,9 +30,7 @@ def get_report_filters(report_filters): ] if report_filters.get("purchase_invoice"): - filters.append( - ["Purchase Invoice", "per_received", "in", [report_filters.get("purchase_invoice")]] - ) + filters.append(["Purchase Invoice", "per_received", "in", [report_filters.get("purchase_invoice")]]) return filters @@ -40,10 +38,10 @@ def get_report_filters(report_filters): def get_report_fields(): fields = [] for p_field in ["name", "supplier", "company", "posting_date", "currency"]: - fields.append("`tabPurchase Invoice`.`{}`".format(p_field)) + fields.append(f"`tabPurchase Invoice`.`{p_field}`") for c_field in ["item_code", "item_name", "uom", "qty", "received_qty", "rate", "amount"]: - fields.append("`tabPurchase Invoice Item`.`{}`".format(c_field)) + fields.append(f"`tabPurchase Invoice Item`.`{c_field}`") return fields diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py index 96cfab9f11f5..e540aa9993c8 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py @@ -112,7 +112,9 @@ def get_columns(filters): ]: if group_months: label = label % ( - formatdate(from_date, format_string="MMM") + "-" + formatdate(to_date, format_string="MMM") + formatdate(from_date, format_string="MMM") + + "-" + + formatdate(to_date, format_string="MMM") ) else: label = label % formatdate(from_date, format_string="MMM") @@ -147,9 +149,7 @@ def get_cost_centers(filters): where company = %s {order_by} - """.format( - tab=filters.get("budget_against"), order_by=order_by - ), + """.format(tab=filters.get("budget_against"), order_by=order_by), filters.get("company"), ) else: @@ -159,9 +159,7 @@ def get_cost_centers(filters): name from `tab{tab}` - """.format( - tab=filters.get("budget_against") - ) + """.format(tab=filters.get("budget_against")) ) # nosec @@ -170,12 +168,12 @@ def get_dimension_target_details(filters): budget_against = frappe.scrub(filters.get("budget_against")) cond = "" if filters.get("budget_against_filter"): - cond += """ and b.{budget_against} in (%s)""".format(budget_against=budget_against) % ", ".join( + cond += f""" and b.{budget_against} in (%s)""" % ", ".join( ["%s"] * len(filters.get("budget_against_filter")) ) return frappe.db.sql( - """ + f""" select b.{budget_against} as budget_against, b.monthly_distribution, @@ -194,10 +192,7 @@ def get_dimension_target_details(filters): {cond} order by b.fiscal_year - """.format( - budget_against=budget_against, - cond=cond, - ), + """, tuple( [ filters.from_fiscal_year, @@ -244,15 +239,13 @@ def get_actual_details(name, filters): if filters.get("budget_against") == "Cost Center": cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"]) - cond = """ - and lft >= "{lft}" - and rgt <= "{rgt}" - """.format( - lft=cc_lft, rgt=cc_rgt - ) + cond = f""" + and lft >= "{cc_lft}" + and rgt <= "{cc_rgt}" + """ ac_details = frappe.db.sql( - """ + f""" select gl.account, gl.debit, @@ -275,7 +268,7 @@ def get_actual_details(name, filters): select name from - `tab{tab}` + `tab{filters.budget_against}` where name = gl.{budget_against} {cond} @@ -283,9 +276,7 @@ def get_actual_details(name, filters): group by gl.name order by gl.fiscal_year - """.format( - tab=filters.budget_against, budget_against=budget_against, cond=cond - ), + """, (filters.from_fiscal_year, filters.to_fiscal_year, name), as_dict=1, ) @@ -314,7 +305,9 @@ def get_dimension_account_month_map(filters): tav_dict = cam_map[ccd.budget_against][ccd.account][ccd.fiscal_year][month] month_percentage = ( - tdd.get(ccd.monthly_distribution, {}).get(month, 0) if ccd.monthly_distribution else 100.0 / 12 + tdd.get(ccd.monthly_distribution, {}).get(month, 0) + if ccd.monthly_distribution + else 100.0 / 12 ) tav_dict.target = flt(ccd.budget_amount) * month_percentage / 100 @@ -327,7 +320,6 @@ def get_dimension_account_month_map(filters): def get_fiscal_years(filters): - fiscal_year = frappe.db.sql( """ select @@ -344,7 +336,6 @@ def get_fiscal_years(filters): def get_chart_data(filters, columns, data): - if not data: return None @@ -360,7 +351,9 @@ def get_chart_data(filters, columns, data): else: if group_months: label = ( - formatdate(from_date, format_string="MMM") + "-" + formatdate(to_date, format_string="MMM") + formatdate(from_date, format_string="MMM") + + "-" + + formatdate(to_date, format_string="MMM") ) labels.append(label) else: diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index af706811ab27..87bde218dae4 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -114,9 +114,7 @@ def execute(filters=None): add_total_row_account( data, data, _("Net Change in Cash"), period_list, company_currency, summary_data, filters ) - columns = get_columns( - filters.periodicity, period_list, filters.accumulated_values, filters.company - ) + columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) chart = get_chart_data(columns, data) @@ -183,8 +181,8 @@ def get_account_type_based_gl_data(company, filters=None): if filters.include_default_book_entries: company_fb = frappe.db.get_value("Company", company, "default_finance_book") - cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL) - """ % ( + cond = """ AND (finance_book in ({}, {}, '') OR finance_book IS NULL) + """.format( frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb), ) @@ -198,15 +196,13 @@ def get_account_type_based_gl_data(company, filters=None): cond += " and cost_center in %(cost_center)s" gl_sum = frappe.db.sql_list( - """ + f""" select sum(credit) - sum(debit) from `tabGL Entry` where company=%(company)s and posting_date >= %(start_date)s and posting_date <= %(end_date)s and voucher_type != 'Period Closing Voucher' and account in ( SELECT name FROM tabAccount WHERE account_type = %(account_type)s) {cond} - """.format( - cond=cond - ), + """, filters, ) @@ -224,9 +220,7 @@ def get_start_date(period, accumulated_values, company): return start_date -def add_total_row_account( - out, data, label, period_list, currency, summary_data, filters, consolidated=False -): +def add_total_row_account(out, data, label, period_list, currency, summary_data, filters, consolidated=False): total_row = { "account_name": "'" + _("{0}").format(label) + "'", "account": "'" + _("{0}").format(label) + "'", @@ -258,9 +252,7 @@ def get_report_summary(summary_data, currency): report_summary = [] for label, value in summary_data.items(): - report_summary.append( - {"value": value, "label": label, "datatype": "Currency", "currency": currency} - ) + report_summary.append({"value": value, "label": label, "datatype": "Currency", "currency": currency}) return report_summary @@ -273,7 +265,7 @@ def get_chart_data(columns, data): "values": [account.get(d.get("fieldname")) for d in columns[2:]], } for account in data - if account.get("parent_account") == None and account.get("currency") + if account.get("parent_account") is None and account.get("currency") ] datasets = datasets[:-1] diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py index 24e585e07f60..2e227609b0ee 100644 --- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py +++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py @@ -131,7 +131,12 @@ def setup_mappers(mappers): account_types_labels = sorted( set( - (d["label"], d["is_working_capital"], d["is_income_tax_liability"], d["is_income_tax_expense"]) + ( + d["label"], + d["is_working_capital"], + d["is_income_tax_liability"], + d["is_income_tax_expense"], + ) for d in account_types ), key=lambda x: x[1], @@ -319,14 +324,10 @@ def add_data_for_operating_activities( data.append(interest_paid) section_data.append(interest_paid) - _add_total_row_account( - data, section_data, mapper["section_footer"], period_list, company_currency - ) + _add_total_row_account(data, section_data, mapper["section_footer"], period_list, company_currency) -def calculate_adjustment( - filters, non_expense_mapper, expense_mapper, use_accumulated_values, period_list -): +def calculate_adjustment(filters, non_expense_mapper, expense_mapper, use_accumulated_values, period_list): liability_accounts = [d["names"] for d in non_expense_mapper] expense_accounts = [d["names"] for d in expense_mapper] @@ -388,9 +389,7 @@ def add_data_for_other_activities( data.append(account_data) section_data.append(account_data) - _add_total_row_account( - data, section_data, mapper["section_footer"], period_list, company_currency - ) + _add_total_row_account(data, section_data, mapper["section_footer"], period_list, company_currency) def compute_data(filters, company_currency, profit_data, period_list, light_mappers, full_mapper): @@ -465,21 +464,15 @@ def execute(filters=None): company_currency = frappe.get_cached_value("Company", filters.company, "default_currency") - data = compute_data( - filters, company_currency, net_profit_loss, period_list, mappers, cash_flow_accounts - ) + data = compute_data(filters, company_currency, net_profit_loss, period_list, mappers, cash_flow_accounts) _add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency) - columns = get_columns( - filters.periodicity, period_list, filters.accumulated_values, filters.company - ) + columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) return columns, data -def _get_account_type_based_data( - filters, account_names, period_list, accumulated_values, opening_balances=0 -): +def _get_account_type_based_data(filters, account_names, period_list, accumulated_values, opening_balances=0): if not account_names or not account_names[0] or not type(account_names[0]) == str: # only proceed if account_names is a list of account names return {} diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index fe4b6c71ebc3..794721b6c92b 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -55,9 +55,7 @@ def execute(filters=None): fiscal_year, companies, columns, filters ) elif filters.get("report") == "Profit and Loss Statement": - data, message, chart, report_summary = get_profit_loss_data( - fiscal_year, companies, columns, filters - ) + data, message, chart, report_summary = get_profit_loss_data(fiscal_year, companies, columns, filters) else: if cint(frappe.db.get_single_value("Accounts Settings", "use_custom_cash_flow")): from erpnext.accounts.report.cash_flow.custom_cash_flow import execute as execute_custom @@ -86,9 +84,7 @@ def get_balance_sheet_data(fiscal_year, companies, columns, filters): asset, liability, equity, companies, filters.get("company"), company_currency, True ) - message, opening_balance = prepare_companywise_opening_balance( - asset, liability, equity, companies - ) + message, opening_balance = prepare_companywise_opening_balance(asset, liability, equity, companies) if opening_balance: unclosed = { @@ -197,9 +193,7 @@ def get_income_expense_data(companies, fiscal_year, filters): expense = get_data(companies, "Expense", "Debit", fiscal_year, filters, True) - net_profit_loss = get_net_profit_loss( - income, expense, companies, filters.company, company_currency, True - ) + net_profit_loss = get_net_profit_loss(income, expense, companies, filters.company, company_currency, True) return income, expense, net_profit_loss @@ -328,9 +322,7 @@ def get_columns(companies, filters): return columns -def get_data( - companies, root_type, balance_must_be, fiscal_year, filters=None, ignore_closing_entries=False -): +def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, ignore_closing_entries=False): accounts, accounts_by_name, parent_children_map = get_account_heads(root_type, companies, filters) if not accounts: @@ -354,7 +346,6 @@ def get_data( root_type, as_dict=1, ): - set_gl_entries_by_account( start_date, end_date, @@ -371,9 +362,7 @@ def get_data( calculate_values(accounts_by_name, gl_entries_by_account, companies, filters, fiscal_year) accumulate_values_into_parents(accounts, accounts_by_name, companies) - out = prepare_data( - accounts, start_date, end_date, balance_must_be, companies, company_currency, filters - ) + out = prepare_data(accounts, start_date, end_date, balance_must_be, companies, company_currency, filters) out = filter_out_zero_value_rows( out, parent_children_map, show_zero_values=filters.get("show_zero_values") @@ -393,9 +382,7 @@ def get_company_currency(filters=None): def calculate_values(accounts_by_name, gl_entries_by_account, companies, filters, fiscal_year): start_date = ( - fiscal_year.year_start_date - if filters.filter_based_on == "Fiscal Year" - else filters.period_start_date + fiscal_year.year_start_date if filters.filter_based_on == "Fiscal Year" else filters.period_start_date ) for entries in gl_entries_by_account.values(): @@ -427,8 +414,12 @@ def calculate_values(accounts_by_name, gl_entries_by_account, companies, filters and parent_company_currency != child_company_currency and filters.get("accumulated_in_group_company") ): - debit = convert(debit, parent_company_currency, child_company_currency, filters.end_date) - credit = convert(credit, parent_company_currency, child_company_currency, filters.end_date) + debit = convert( + debit, parent_company_currency, child_company_currency, filters.end_date + ) + credit = convert( + credit, parent_company_currency, child_company_currency, filters.end_date + ) d[company] = d.get(company, 0.0) + flt(debit) - flt(credit) @@ -512,10 +503,8 @@ def get_subsidiary_companies(company): lft, rgt = frappe.get_cached_value("Company", company, ["lft", "rgt"]) return frappe.db.sql_list( - """select name from `tabCompany` - where lft >= {0} and rgt <= {1} order by lft, rgt""".format( - lft, rgt - ) + f"""select name from `tabCompany` + where lft >= {lft} and rgt <= {rgt} order by lft, rgt""" ) @@ -552,9 +541,7 @@ def get_accounts(root_type, companies): return accounts -def prepare_data( - accounts, start_date, end_date, balance_must_be, companies, company_currency, filters -): +def prepare_data(accounts, start_date, end_date, balance_must_be, companies, company_currency, filters): data = [] for d in accounts: @@ -564,9 +551,7 @@ def prepare_data( row = frappe._dict( { "account_name": ( - "%s - %s" % (_(d.account_number), _(d.account_name)) - if d.account_number - else _(d.account_name) + f"{_(d.account_number)} - {_(d.account_name)}" if d.account_number else _(d.account_name) ), "account": _(d.name), "parent_account": _(d.parent_account), @@ -614,9 +599,7 @@ def set_gl_entries_by_account( ): """Returns a dict like { "account": [gl entries], ... }""" - company_lft, company_rgt = frappe.get_cached_value( - "Company", filters.get("company"), ["lft", "rgt"] - ) + company_lft, company_rgt = frappe.get_cached_value("Company", filters.get("company"), ["lft", "rgt"]) companies = frappe.db.sql( """ select name, default_currency from `tabCompany` @@ -744,7 +727,7 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters, d): additional_conditions = [] if ignore_closing_entries: - additional_conditions.append((gle.voucher_type != "Period Closing Voucher")) + additional_conditions.append(gle.voucher_type != "Period Closing Voucher") if from_date: additional_conditions.append(gle.posting_date >= from_date) @@ -807,7 +790,7 @@ def filter_accounts(accounts, depth=10): def add_to_list(parent, level): if level < depth: children = parent_children_map.get(parent) or [] - sort_accounts(children, is_root=True if parent == None else False) + sort_accounts(children, is_root=True if parent is None else False) for child in children: child.indent = level diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index 2da6d18f0052..108f9f617df1 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -7,7 +7,7 @@ from frappe.utils import getdate, nowdate -class PartyLedgerSummaryReport(object): +class PartyLedgerSummaryReport: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) self.filters.from_date = getdate(self.filters.from_date or nowdate()) @@ -21,9 +21,7 @@ def run(self, args): frappe.throw(_("From Date must be before To Date")) self.filters.party_type = args.get("party_type") - self.party_naming_by = frappe.db.get_value( - args.get("naming_by")[0], None, args.get("naming_by")[1] - ) + self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1]) self.get_gl_entries() self.get_additional_columns() @@ -49,7 +47,7 @@ def get_additional_columns(self): .select( customer.name, customer.territory, customer.customer_group, customer.default_sales_partner ) - .where((customer.disabled == 0)) + .where(customer.disabled == 0) .run(as_dict=True) ) @@ -62,7 +60,7 @@ def get_additional_columns(self): result = ( frappe.qb.from_(supplier) .select(supplier.name, supplier.supplier_group) - .where((supplier.disabled == 0)) + .where(supplier.disabled == 0) .run(as_dict=True) ) @@ -184,9 +182,7 @@ def get_columns(self): return columns def get_data(self): - company_currency = frappe.get_cached_value( - "Company", self.filters.get("company"), "default_currency" - ) + company_currency = frappe.get_cached_value("Company", self.filters.get("company"), "default_currency") invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit" reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit" @@ -260,7 +256,7 @@ def get_gl_entries(self): join = "left join `tabSupplier` p on gle.party = p.name" self.gl_entries = frappe.db.sql( - """ + f""" select gle.posting_date, gle.party, gle.voucher_type, gle.voucher_no, gle.against_voucher_type, gle.against_voucher, gle.debit, gle.credit, gle.is_opening {join_field} @@ -270,9 +266,7 @@ def get_gl_entries(self): gle.docstatus < 2 and gle.is_cancelled = 0 and gle.party_type=%(party_type)s and ifnull(gle.party, '') != '' and gle.posting_date <= %(to_date)s {conditions} order by gle.posting_date - """.format( - join=join, join_field=join_field, conditions=conditions - ), + """, self.filters, as_dict=True, ) @@ -296,22 +290,18 @@ def prepare_conditions(self): ) conditions.append( - """party in (select name from tabCustomer - where exists(select name from `tabCustomer Group` where lft >= {0} and rgt <= {1} - and name=tabCustomer.customer_group))""".format( - lft, rgt - ) + f"""party in (select name from tabCustomer + where exists(select name from `tabCustomer Group` where lft >= {lft} and rgt <= {rgt} + and name=tabCustomer.customer_group))""" ) if self.filters.get("territory"): lft, rgt = frappe.db.get_value("Territory", self.filters.get("territory"), ["lft", "rgt"]) conditions.append( - """party in (select name from tabCustomer - where exists(select name from `tabTerritory` where lft >= {0} and rgt <= {1} - and name=tabCustomer.territory))""".format( - lft, rgt - ) + f"""party in (select name from tabCustomer + where exists(select name from `tabTerritory` where lft >= {lft} and rgt <= {rgt} + and name=tabCustomer.territory))""" ) if self.filters.get("payment_terms_template"): @@ -331,12 +321,10 @@ def prepare_conditions(self): conditions.append( """exists(select name from `tabSales Team` steam where - steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1}) + steam.sales_person in (select name from `tabSales Person` where lft >= {} and rgt <= {}) and ((steam.parent = voucher_no and steam.parenttype = voucher_type) or (steam.parent = against_voucher and steam.parenttype = against_voucher_type) - or (steam.parent = party and steam.parenttype = 'Customer')))""".format( - lft, rgt - ) + or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt) ) if self.filters.party_type == "Supplier": @@ -392,7 +380,7 @@ def get_party_adjustment_amounts(self): ) gl_entries = frappe.db.sql( - """ + f""" select posting_date, account, party, voucher_type, voucher_no, debit, credit from @@ -406,10 +394,7 @@ def get_party_adjustment_amounts(self): where gle.party_type=%(party_type)s and ifnull(party, '') != '' and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2 {conditions} ) - """.format( - accounts_query=accounts_query, - conditions=conditions, - ), + """, self.filters, as_dict=True, ) @@ -440,14 +425,14 @@ def get_party_adjustment_amounts(self): if parties and accounts: if len(parties) == 1: - party = list(parties.keys())[0] + party = next(iter(parties.keys())) for account, amount in accounts.items(): self.party_adjustment_accounts.add(account) self.party_adjustment_details.setdefault(party, {}) self.party_adjustment_details[party].setdefault(account, 0) self.party_adjustment_details[party][account] += amount elif len(accounts) == 1 and not has_irrelevant_entry: - account = list(accounts.keys())[0] + account = next(iter(accounts.keys())) self.party_adjustment_accounts.add(account) for party, amount in parties.items(): self.party_adjustment_details.setdefault(party, {}) diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py index cad5325c6e98..303305d20c58 100644 --- a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py +++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py @@ -10,7 +10,7 @@ from erpnext.accounts.utils import get_fiscal_year -class Deferred_Item(object): +class Deferred_Item: """ Helper class for processing items with deferred revenue/expense """ @@ -152,13 +152,11 @@ def calculate_item_revenue_expense_for_period(self): if posting.posted == "posted": actual += self.get_amount(posting) - self.period_total.append( - frappe._dict({"key": period.key, "total": period_sum, "actual": actual}) - ) + self.period_total.append(frappe._dict({"key": period.key, "total": period_sum, "actual": actual})) return self.period_total -class Deferred_Invoice(object): +class Deferred_Invoice: def __init__(self, invoice, items, filters, period_list): """ Helper class for processing invoices with deferred revenue/expense items @@ -219,7 +217,7 @@ def report_data(self): return ret_data -class Deferred_Revenue_and_Expense_Report(object): +class Deferred_Revenue_and_Expense_Report: def __init__(self, filters=None): """ Initialize deferred revenue/expense report with user provided filters or system defaults, if none is provided diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py b/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py index 7b1a9027780e..f8a965b699cb 100644 --- a/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py +++ b/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py @@ -1,5 +1,3 @@ -import unittest - import frappe from frappe import qb from frappe.tests.utils import FrappeTestCase, change_settings @@ -13,8 +11,6 @@ ) from erpnext.accounts.test.accounts_mixin import AccountsTestMixin from erpnext.accounts.utils import get_fiscal_year -from erpnext.buying.doctype.supplier.test_supplier import create_supplier -from erpnext.stock.doctype.item.test_item import create_item class TestDeferredRevenueAndExpense(FrappeTestCase, AccountsTestMixin): diff --git a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py index ecad9f104fa5..6c1e73d5edc3 100644 --- a/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py +++ b/erpnext/accounts/report/dimension_wise_accounts_balance_report/dimension_wise_accounts_balance_report.py @@ -15,7 +15,6 @@ def execute(filters=None): - validate_filters(filters) dimension_list = get_dimensions(filters) @@ -90,9 +89,7 @@ def set_gl_entries_by_account(dimension_list, filters, account, gl_entries_by_ac gl_filters["dimensions"] = set(dimension_list) if filters.get("include_default_book_entries"): - gl_filters["company_fb"] = frappe.db.get_value( - "Company", filters.company, "default_finance_book" - ) + gl_filters["company_fb"] = frappe.db.get_value("Company", filters.company, "default_finance_book") gl_entries = frappe.db.sql( """ @@ -119,7 +116,6 @@ def set_gl_entries_by_account(dimension_list, filters, account, gl_entries_by_ac def format_gl_entries(gl_entries_by_account, accounts_by_name, dimension_list, dimension_type): - for entries in gl_entries_by_account.values(): for entry in entries: d = accounts_by_name.get(entry.account) @@ -151,7 +147,7 @@ def prepare_data(accounts, filters, company_currency, dimension_list): "to_date": filters.to_date, "currency": company_currency, "account_name": ( - "{} - {}".format(d.account_number, d.account_name) if d.account_number else d.account_name + f"{d.account_number} - {d.account_name}" if d.account_number else d.account_name ), } @@ -183,7 +179,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name, dimension_list): def get_condition(dimension): conditions = [] - conditions.append("{0} in %(dimensions)s".format(frappe.scrub(dimension))) + conditions.append(f"{frappe.scrub(dimension)} in %(dimensions)s") return " and {}".format(" and ".join(conditions)) if conditions else "" diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 096bb107069a..56f3bd1caa40 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -162,7 +162,6 @@ def get_data( ignore_accumulated_values_for_fy=False, total=True, ): - accounts = get_accounts(company, root_type) if not accounts: return None @@ -178,7 +177,6 @@ def get_data( root_type, as_dict=1, ): - set_gl_entries_by_account( company, period_list[0]["year_start_date"] if only_current_fiscal_year else None, @@ -236,7 +234,8 @@ def calculate_values( if entry.posting_date <= period.to_date: if (accumulated_values or entry.posting_date >= period.from_date) and ( - not ignore_accumulated_values_for_fy or entry.fiscal_year == period.to_date_fiscal_year + not ignore_accumulated_values_for_fy + or entry.fiscal_year == period.to_date_fiscal_year ): d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit) @@ -280,9 +279,7 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency): "is_group": d.is_group, "opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be == "Debit" else -1), "account_name": ( - "%s - %s" % (_(d.account_number), _(d.account_name)) - if d.account_number - else _(d.account_name) + f"{_(d.account_number)} - {_(d.account_name)}" if d.account_number else _(d.account_name) ), } ) @@ -370,7 +367,7 @@ def filter_accounts(accounts, depth=20): def add_to_list(parent, level): if level < depth: children = parent_children_map.get(parent) or [] - sort_accounts(children, is_root=True if parent == None else False) + sort_accounts(children, is_root=True if parent is None else False) for child in children: child.indent = level @@ -561,7 +558,9 @@ def apply_additional_conditions(doctype, query, from_date, ignore_closing_entrie company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book") if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb): - frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'")) + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default FB Entries'") + ) query = query.where( (gl_entry.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""])) diff --git a/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py b/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py index 696a03b0a700..89cf7e504f0c 100644 --- a/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py +++ b/erpnext/accounts/report/general_and_payment_ledger_comparison/general_and_payment_ledger_comparison.py @@ -7,7 +7,7 @@ from frappe.query_builder.functions import Sum -class General_Payment_Ledger_Comparison(object): +class General_Payment_Ledger_Comparison: """ A Utility report to compare Voucher-wise balance between General and Payment Ledger """ @@ -58,10 +58,9 @@ def get_gle(self): for acc_type, val in self.account_types.items(): if val.accounts: - filter_criterion = [] if self.filters.voucher_no: - filter_criterion.append((gle.voucher_no == self.filters.voucher_no)) + filter_criterion.append(gle.voucher_no == self.filters.voucher_no) if self.filters.period_start_date: filter_criterion.append(gle.posting_date.gte(self.filters.period_start_date)) @@ -102,10 +101,9 @@ def get_ple(self): for acc_type, val in self.account_types.items(): if val.accounts: - filter_criterion = [] if self.filters.voucher_no: - filter_criterion.append((ple.voucher_no == self.filters.voucher_no)) + filter_criterion.append(ple.voucher_no == self.filters.voucher_no) if self.filters.period_start_date: filter_criterion.append(ple.posting_date.gte(self.filters.period_start_date)) @@ -141,7 +139,7 @@ def compare(self): self.ple_balances = set() # consolidate both receivable and payable balances in one set - for acc_type, val in self.account_types.items(): + for _acc_type, val in self.account_types.items(): self.gle_balances = set(val.gle) | self.gle_balances self.ple_balances = set(val.ple) | self.ple_balances @@ -177,7 +175,6 @@ def generate_data(self): def get_columns(self): self.columns = [] - options = None self.columns.append( dict( label=_("Company"), diff --git a/erpnext/accounts/report/general_and_payment_ledger_comparison/test_general_and_payment_ledger_comparison.py b/erpnext/accounts/report/general_and_payment_ledger_comparison/test_general_and_payment_ledger_comparison.py index 59e906ba3321..afa81b83cfc6 100644 --- a/erpnext/accounts/report/general_and_payment_ledger_comparison/test_general_and_payment_ledger_comparison.py +++ b/erpnext/accounts/report/general_and_payment_ledger_comparison/test_general_and_payment_ledger_comparison.py @@ -1,5 +1,3 @@ -import unittest - import frappe from frappe import qb from frappe.tests.utils import FrappeTestCase @@ -40,9 +38,7 @@ def test_01_basic_report_functionality(self): ) # manually edit the payment ledger entry - ple = frappe.db.get_all( - "Payment Ledger Entry", filters={"voucher_no": sinv.name, "delinked": 0} - )[0] + ple = frappe.db.get_all("Payment Ledger Entry", filters={"voucher_no": sinv.name, "delinked": 0})[0] frappe.db.set_value("Payment Ledger Entry", ple.name, "amount", sinv.grand_total - 1) filters = frappe._dict({"company": self.company}) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 269d25b99db0..685797abd195 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -102,9 +102,7 @@ def validate_party(filters): def set_account_currency(filters): if filters.get("account") or (filters.get("party") and len(filters.party) == 1): - filters["company_currency"] = frappe.get_cached_value( - "Company", filters.company, "default_currency" - ) + filters["company_currency"] = frappe.get_cached_value("Company", filters.company, "default_currency") account_currency = None if filters.get("account"): @@ -164,9 +162,7 @@ def get_gl_entries(filters, accounting_dimensions): credit_in_account_currency """ if filters.get("show_remarks"): - if remarks_length := frappe.db.get_single_value( - "Accounts Settings", "general_ledger_remarks_length" - ): + 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""" @@ -182,16 +178,14 @@ def get_gl_entries(filters, accounting_dimensions): order_by_statement = "order by account, posting_date, creation" if filters.get("include_default_book_entries"): - filters["company_fb"] = frappe.db.get_value( - "Company", filters.get("company"), "default_finance_book" - ) + filters["company_fb"] = frappe.db.get_value("Company", filters.get("company"), "default_finance_book") dimension_fields = "" if accounting_dimensions: dimension_fields = ", ".join(accounting_dimensions) + "," gl_entries = frappe.db.sql( - """ + f""" select name as gl_entry, posting_date, account, party_type, party, voucher_type, voucher_no, {dimension_fields} @@ -199,14 +193,9 @@ def get_gl_entries(filters, accounting_dimensions): against_voucher_type, against_voucher, account_currency, against, is_opening, creation {select_fields} from `tabGL Entry` - where company=%(company)s {conditions} + where company=%(company)s {get_conditions(filters)} {order_by_statement} - """.format( - dimension_fields=dimension_fields, - select_fields=select_fields, - conditions=get_conditions(filters), - order_by_statement=order_by_statement, - ), + """, filters, as_dict=1, ) @@ -273,7 +262,9 @@ def get_conditions(filters): if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr( filters.get("company_fb") ): - frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'")) + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default FB Entries'") + ) else: conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") else: @@ -305,9 +296,9 @@ def get_conditions(filters): filters[dimension.fieldname] = get_dimension_with_children( dimension.document_type, filters.get(dimension.fieldname) ) - conditions.append("{0} in %({0})s".format(dimension.fieldname)) + conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") else: - conditions.append("{0} in %({0})s".format(dimension.fieldname)) + conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") return "and {}".format(" and ".join(conditions)) if conditions else "" @@ -339,7 +330,7 @@ def get_data_with_opening_closing(filters, account_details, accounting_dimension data.append(totals.opening) if filters.get("group_by") != "Group by Voucher (Consolidated)": - for acc, acc_dict in gle_map.items(): + for _acc, acc_dict in gle_map.items(): # acc if acc_dict.entries: # opening @@ -371,7 +362,7 @@ def get_data_with_opening_closing(filters, account_details, accounting_dimension def get_totals_dict(): def _get_debit_credit_dict(label): return _dict( - account="'{0}'".format(label), + account=f"'{label}'", debit=0.0, credit=0.0, debit_in_account_currency=0.0, @@ -420,9 +411,10 @@ def update_value_in_dict(data, key, gle): data[key].debit_in_account_currency += gle.debit_in_account_currency data[key].credit_in_account_currency += gle.credit_in_account_currency - if filters.get("show_net_values_in_party_account") and account_type_map.get( - data[key].account - ) in ("Receivable", "Payable"): + if filters.get("show_net_values_in_party_account") and account_type_map.get(data[key].account) in ( + "Receivable", + "Payable", + ): net_value = data[key].debit - data[key].credit net_value_in_account_currency = ( data[key].debit_in_account_currency - data[key].credit_in_account_currency @@ -495,21 +487,19 @@ def update_value_in_dict(data, key, gle): def get_account_type_map(company): account_type_map = frappe._dict( - frappe.get_all( - "Account", fields=["name", "account_type"], filters={"company": company}, as_list=1 - ) + frappe.get_all("Account", fields=["name", "account_type"], filters={"company": company}, as_list=1) ) return account_type_map def get_result_as_list(data, filters): - balance, balance_in_account_currency = 0, 0 + balance, _balance_in_account_currency = 0, 0 inv_details = get_supplier_invoice_details() for d in data: if not d.get("posting_date"): - balance, balance_in_account_currency = 0, 0 + balance, _balance_in_account_currency = 0, 0 balance = get_balance(d, balance, "debit", "credit") d["balance"] = balance diff --git a/erpnext/accounts/report/general_ledger/test_general_ledger.py b/erpnext/accounts/report/general_ledger/test_general_ledger.py index 75f94309bccd..33b356feb330 100644 --- a/erpnext/accounts/report/general_ledger/test_general_ledger.py +++ b/erpnext/accounts/report/general_ledger/test_general_ledger.py @@ -203,9 +203,7 @@ def test_ignore_exchange_rate_journals_filter(self): revaluation.extend("accounts", accounts) row = revaluation.accounts[0] row.new_exchange_rate = 83 - row.new_balance_in_base_currency = flt( - row.new_exchange_rate * flt(row.balance_in_account_currency) - ) + row.new_balance_in_base_currency = flt(row.new_exchange_rate * flt(row.balance_in_account_currency)) row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency) revaluation.set_total_gain_loss() revaluation = revaluation.save().submit() diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py index 5ccd4f0f16fe..b90e2e44bf3e 100644 --- a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py @@ -49,9 +49,7 @@ def execute(filters=None): total=False, ) - columns = get_columns( - filters.periodicity, period_list, filters.accumulated_values, filters.company - ) + columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) gross_income = get_revenue(income, period_list) gross_expense = get_revenue(expense, period_list) @@ -119,9 +117,7 @@ def execute(filters=None): def get_revenue(data, period_list, include_in_gross=1): - revenue = [ - item for item in data if item["include_in_gross"] == include_in_gross or item["is_group"] == 1 - ] + revenue = [item for item in data if item["include_in_gross"] == include_in_gross or item["is_group"] == 1] data_to_be_removed = True while data_to_be_removed: diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 187a154a6513..0d61a33e0648 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -158,9 +158,7 @@ def execute(filters=None): return columns, data -def get_data_when_grouped_by_invoice( - columns, gross_profit_data, filters, group_wise_columns, data -): +def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_wise_columns, data): column_names = get_column_names() # to display item as Item Code: Item Name @@ -395,7 +393,7 @@ def get_column_names(): ) -class GrossProfitGenerator(object): +class GrossProfitGenerator: def __init__(self, filters=None): self.sle = {} self.data = [] @@ -499,7 +497,8 @@ def get_average_rate_based_on_group_by(self): for i, row in enumerate(self.grouped[key]): if row.indent == 1.0: if ( - row.parent in self.returned_invoices and row.item_code in self.returned_invoices[row.parent] + row.parent in self.returned_invoices + and row.item_code in self.returned_invoices[row.parent] ): returned_item_rows = self.returned_invoices[row.parent][row.item_code] for returned_item_row in returned_item_rows: @@ -512,7 +511,9 @@ def get_average_rate_based_on_group_by(self): row.qty = 0 returned_item_row.qty += row.qty row.base_amount += flt(returned_item_row.base_amount, self.currency_precision) - row.buying_amount = flt(flt(row.qty) * flt(row.buying_rate), self.currency_precision) + row.buying_amount = flt( + flt(row.qty) * flt(row.buying_rate), self.currency_precision + ) if flt(row.qty) or row.base_amount: row = self.set_average_rate(row) self.grouped_data.append(row) @@ -567,9 +568,7 @@ def set_average_rate(self, new_row): new_row.buying_rate = ( flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0 ) - new_row.base_rate = ( - flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0 - ) + new_row.base_rate = flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0 return new_row def set_average_gross_profit(self, new_row): @@ -656,7 +655,7 @@ def get_buying_amount(self, row, item_code): elif self.delivery_notes.get((row.parent, row.item_code), None): # check if Invoice has delivery notes dn = self.delivery_notes.get((row.parent, row.item_code)) - parenttype, parent, item_row, warehouse = ( + parenttype, parent, item_row, _warehouse = ( "Delivery Note", dn["delivery_note"], dn["item_row"], @@ -695,7 +694,7 @@ def get_buying_amount_from_so_dn(self, sales_order, so_detail, item_code): def get_average_buying_rate(self, row, item_code): args = row - if not item_code in self.average_buying_rate: + if item_code not in self.average_buying_rate: args.update( { "voucher_type": row.parenttype, @@ -748,7 +747,7 @@ def load_invoice_items(self): conditions += " and (is_return = 0 or (is_return=1 and return_against is null))" if self.filters.item_group: - conditions += " and {0}".format(get_item_group_condition(self.filters.item_group)) + conditions += f" and {get_item_group_condition(self.filters.item_group)}" if self.filters.sales_person: conditions += """ @@ -767,12 +766,10 @@ def load_invoice_items(self): if self.filters.group_by == "Payment Term": payment_term_cols = """,if(`tabSales Invoice`.is_return = 1, - '{0}', - coalesce(schedule.payment_term, '{1}')) as payment_term, + '{}', + coalesce(schedule.payment_term, '{}')) as payment_term, schedule.invoice_portion, - schedule.payment_amount """.format( - _("Sales Return"), _("No Terms") - ) + schedule.payment_amount """.format(_("Sales Return"), _("No Terms")) payment_term_table = """ left join `tabPayment Schedule` schedule on schedule.parent = `tabSales Invoice`.name and `tabSales Invoice`.is_return = 0 """ else: @@ -939,9 +936,7 @@ def get_bundle_item_row(self, product_bundle, item): ) def get_bundle_item_details(self, item_code): - return frappe.db.get_value( - "Item", item_code, ["item_name", "description", "item_group", "brand"] - ) + return frappe.db.get_value("Item", item_code, ["item_name", "description", "item_group", "brand"]) def get_stock_ledger_entries(self, item_code, warehouse): if item_code and warehouse: diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index aa820aa4c731..8d15900741e9 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -1,7 +1,7 @@ import frappe from frappe import qb from frappe.tests.utils import FrappeTestCase -from frappe.utils import add_days, flt, nowdate +from frappe.utils import flt, nowdate from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py index 230b18c293fc..df3fc48f9e18 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py @@ -92,7 +92,6 @@ def get_data(filters): def get_sales_details(filters): - data = [] item_details_map = {} date_field = "s.transaction_date" if filters["based_on"] == "Sales Order" else "s.posting_date" @@ -116,7 +115,6 @@ def get_sales_details(filters): def get_territories(filters): - filter_dict = {} if filters.get("territory"): filter_dict.update({"name": filters["territory"]}) 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 b5dd66f75fe2..2f87b5be836d 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 @@ -140,7 +140,6 @@ def _execute(filters=None, additional_table_columns=None): def get_columns(additional_table_columns, filters): - columns = [] if filters.get("group_by") != ("Item"): @@ -194,7 +193,12 @@ def get_columns(additional_table_columns, filters): "options": "Supplier", "width": 120, }, - {"label": _("Supplier Name"), "fieldname": "supplier_name", "fieldtype": "Data", "width": 120}, + { + "label": _("Supplier Name"), + "fieldname": "supplier_name", + "fieldtype": "Data", + "width": 120, + }, ] ) @@ -326,14 +330,12 @@ def get_items(filters, additional_query_columns): `tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`, `tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`, `tabPurchase Invoice Item`.`stock_uom`, `tabPurchase Invoice Item`.`base_net_amount`, - `tabPurchase Invoice`.`supplier_name`, `tabPurchase Invoice`.`mode_of_payment` {0} + `tabPurchase Invoice`.`supplier_name`, `tabPurchase Invoice`.`mode_of_payment` {} from `tabPurchase Invoice`, `tabPurchase Invoice Item`, `tabItem` where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and `tabItem`.name = `tabPurchase Invoice Item`.`item_code` and - `tabPurchase Invoice`.docstatus = 1 {1} - """.format( - additional_query_columns, conditions - ), + `tabPurchase Invoice`.docstatus = 1 {} + """.format(additional_query_columns, conditions), filters, as_dict=1, ) diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 94457d599810..c78197319304 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -217,7 +217,12 @@ def get_columns(additional_table_columns, filters): "options": "Customer", "width": 120, }, - {"label": _("Customer Name"), "fieldname": "customer_name", "fieldtype": "Data", "width": 120}, + { + "label": _("Customer Name"), + "fieldname": "customer_name", + "fieldtype": "Data", + "width": 120, + }, ] ) @@ -365,9 +370,7 @@ def get_conditions(filters, additional_conditions=None): conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s""" if not filters.get("group_by"): - conditions += ( - "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc" - ) + conditions += "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc" else: conditions += get_group_by_conditions(filters, "Sales Invoice") @@ -376,13 +379,13 @@ def get_conditions(filters, additional_conditions=None): def get_group_by_conditions(filters, doctype): if filters.get("group_by") == "Invoice": - return "ORDER BY `tab{0} Item`.parent desc".format(doctype) + return f"ORDER BY `tab{doctype} Item`.parent desc" elif filters.get("group_by") == "Item": - return "ORDER BY `tab{0} Item`.`item_code`".format(doctype) + return f"ORDER BY `tab{doctype} Item`.`item_code`" elif filters.get("group_by") == "Item Group": - return "ORDER BY `tab{0} Item`.{1}".format(doctype, frappe.scrub(filters.get("group_by"))) + return "ORDER BY `tab{} Item`.{}".format(doctype, frappe.scrub(filters.get("group_by"))) elif filters.get("group_by") in ("Customer", "Customer Group", "Territory", "Supplier"): - return "ORDER BY `tab{0}`.{1}".format(doctype, frappe.scrub(filters.get("group_by"))) + return "ORDER BY `tab{}`.{}".format(doctype, frappe.scrub(filters.get("group_by"))) def get_items(filters, additional_query_columns, additional_conditions=None): @@ -408,14 +411,12 @@ def get_items(filters, additional_query_columns, additional_conditions=None): `tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount, `tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail, - `tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0} + `tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {} from `tabSales Invoice`, `tabSales Invoice Item`, `tabItem` where `tabSales Invoice`.name = `tabSales Invoice Item`.parent and `tabItem`.name = `tabSales Invoice Item`.`item_code` and - `tabSales Invoice`.docstatus = 1 {1} - """.format( - additional_query_columns, conditions - ), + `tabSales Invoice`.docstatus = 1 {} + """.format(additional_query_columns, conditions), filters, as_dict=1, ) # nosec @@ -445,20 +446,15 @@ def get_delivery_notes_against_sales_order(item_list): def get_grand_total(filters, doctype): - return frappe.db.sql( - """ SELECT - SUM(`tab{0}`.base_grand_total) - FROM `tab{0}` - WHERE `tab{0}`.docstatus = 1 + f""" SELECT + SUM(`tab{doctype}`.base_grand_total) + FROM `tab{doctype}` + WHERE `tab{doctype}`.docstatus = 1 and posting_date between %s and %s - """.format( - doctype - ), + """, (filters.get("from_date"), filters.get("to_date")), - )[0][ - 0 - ] # nosec + )[0][0] # nosec def get_tax_accounts( @@ -477,9 +473,7 @@ def get_tax_accounts( add_deduct_tax = "charge_type" tax_amount_precision = ( - get_field_precision( - frappe.get_meta(tax_doctype).get_field("tax_amount"), currency=company_currency - ) + get_field_precision(frappe.get_meta(tax_doctype).get_field("tax_amount"), currency=company_currency) or 2 ) @@ -489,11 +483,13 @@ def get_tax_accounts( conditions = "" if doctype == "Purchase Invoice": - conditions = " and category in ('Total', 'Valuation and Total') and base_tax_amount_after_discount_amount != 0" + conditions = ( + " and category in ('Total', 'Valuation and Total') and base_tax_amount_after_discount_amount != 0" + ) add_deduct_tax = "add_deduct_tax" tax_details = frappe.db.sql( - """ + f""" select name, parent, description, item_wise_tax_detail, account_head, charge_type, {add_deduct_tax}, base_tax_amount_after_discount_amount @@ -504,11 +500,9 @@ def get_tax_accounts( and parent in (%s) %s order by description - """.format( - add_deduct_tax=add_deduct_tax - ) + """ % (tax_doctype, "%s", ", ".join(["%s"] * len(invoice_item_row)), conditions), - tuple([doctype] + list(invoice_item_row)), + tuple([doctype, *list(invoice_item_row)]), ) account_doctype = frappe.qb.DocType("Account") @@ -516,13 +510,13 @@ def get_tax_accounts( query = ( frappe.qb.from_(account_doctype) .select(account_doctype.name) - .where((account_doctype.account_type == "Tax")) + .where(account_doctype.account_type == "Tax") ) tax_accounts = query.run() for ( - name, + _name, parent, description, item_wise_tax_detail, @@ -583,7 +577,9 @@ def get_tax_accounts( itemised_tax.setdefault(d.name, {})[description] = frappe._dict( { "tax_rate": "NA", - "tax_amount": flt((tax_amount * d.base_net_amount) / d.base_net_total, tax_amount_precision), + "tax_amount": flt( + (tax_amount * d.base_net_amount) / d.base_net_total, tax_amount_precision + ), } ) diff --git a/erpnext/accounts/report/payment_ledger/payment_ledger.py b/erpnext/accounts/report/payment_ledger/payment_ledger.py index 8875d2743fe2..9852c6e7ab99 100644 --- a/erpnext/accounts/report/payment_ledger/payment_ledger.py +++ b/erpnext/accounts/report/payment_ledger/payment_ledger.py @@ -8,7 +8,7 @@ from frappe.query_builder import Criterion -class PaymentLedger(object): +class PaymentLedger: def __init__(self, filters=None): self.filters = filters self.columns, self.data = [], [] diff --git a/erpnext/accounts/report/payment_ledger/test_payment_ledger.py b/erpnext/accounts/report/payment_ledger/test_payment_ledger.py index 5ae9b87cde9f..c982f3166e74 100644 --- a/erpnext/accounts/report/payment_ledger/test_payment_ledger.py +++ b/erpnext/accounts/report/payment_ledger/test_payment_ledger.py @@ -1,5 +1,3 @@ -import unittest - import frappe from frappe import qb from frappe.tests.utils import FrappeTestCase @@ -57,7 +55,7 @@ def test_unpaid_invoice_outstanding(self): income_account=self.income_account, warehouse=self.warehouse, ) - pe = get_payment_entry(sinv.doctype, sinv.name).save().submit() + get_payment_entry(sinv.doctype, sinv.name).save().submit() filters = frappe._dict({"company": self.company}) columns, data = execute(filters=filters) diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py index eaeaa62d9a28..834eb5f519cb 100644 --- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py +++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py @@ -163,10 +163,8 @@ def get_entries(filters): """select voucher_type, voucher_no, party_type, party, posting_date, debit, credit, remarks, against_voucher from `tabGL Entry` - where company=%(company)s and voucher_type in ('Journal Entry', 'Payment Entry') and is_cancelled = 0 {0} - """.format( - get_conditions(filters) - ), + where company=%(company)s and voucher_type in ('Journal Entry', 'Payment Entry') and is_cancelled = 0 {} + """.format(get_conditions(filters)), filters, as_dict=1, ) @@ -175,7 +173,7 @@ def get_entries(filters): def get_invoice_posting_date_map(filters): invoice_details = {} dt = "Sales Invoice" if filters.get("payment_type") == _("Incoming") else "Purchase Invoice" - for t in frappe.db.sql("select name, posting_date, due_date from `tab{0}`".format(dt), as_dict=1): + for t in frappe.db.sql(f"select name, posting_date, due_date from `tab{dt}`", as_dict=1): invoice_details[t.name] = t return invoice_details diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py index 3c687d0b48e3..2248f6eca659 100644 --- a/erpnext/accounts/report/pos_register/pos_register.py +++ b/erpnext/accounts/report/pos_register/pos_register.py @@ -50,18 +50,20 @@ def get_pos_entries(filters, group_by_field): order_by = "p.posting_date" select_mop_field, from_sales_invoice_payment, group_by_mop_condition = "", "", "" if group_by_field == "mode_of_payment": - select_mop_field = ", sip.mode_of_payment, sip.base_amount - IF(sip.type='Cash', p.change_amount, 0) as paid_amount" + select_mop_field = ( + ", sip.mode_of_payment, sip.base_amount - IF(sip.type='Cash', p.change_amount, 0) as paid_amount" + ) from_sales_invoice_payment = ", `tabSales Invoice Payment` sip" group_by_mop_condition = "sip.parent = p.name AND ifnull(sip.base_amount - IF(sip.type='Cash', p.change_amount, 0), 0) != 0 AND" order_by += ", sip.mode_of_payment" elif group_by_field: - order_by += ", p.{}".format(group_by_field) + order_by += f", p.{group_by_field}" select_mop_field = ", p.base_paid_amount - p.change_amount as paid_amount " # nosemgrep return frappe.db.sql( - """ + f""" SELECT p.posting_date, p.name as pos_invoice, p.pos_profile, p.company, p.owner, p.customer, p.is_return, p.base_grand_total as grand_total {select_mop_field} @@ -73,13 +75,7 @@ def get_pos_entries(filters, group_by_field): {conditions} ORDER BY {order_by} - """.format( - select_mop_field=select_mop_field, - from_sales_invoice_payment=from_sales_invoice_payment, - group_by_mop_condition=group_by_mop_condition, - conditions=conditions, - order_by=order_by, - ), + """, filters, as_dict=1, ) @@ -132,9 +128,7 @@ def validate_filters(filters): def get_conditions(filters): - conditions = ( - "company = %(company)s AND posting_date >= %(from_date)s AND posting_date <= %(to_date)s" - ) + conditions = "company = %(company)s AND posting_date >= %(from_date)s AND posting_date <= %(to_date)s" if filters.get("pos_profile"): conditions += " AND pos_profile = %(pos_profile)s" diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 002c05c9e3f6..4571c4b26a07 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -57,9 +57,7 @@ def execute(filters=None): if net_profit_loss: data.append(net_profit_loss) - columns = get_columns( - filters.periodicity, period_list, filters.accumulated_values, filters.company - ) + columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) chart = get_chart_data(filters, columns, income, expense, net_profit_loss) diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index f745c87a00aa..92d91a4cc469 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -316,16 +316,12 @@ def get_account_columns(invoice_list, include_payments): tuple([inv.name for inv in invoice_list]), ) - purchase_taxes_query = get_taxes_query( - invoice_list, "Purchase Taxes and Charges", "Purchase Invoice" - ) + purchase_taxes_query = get_taxes_query(invoice_list, "Purchase Taxes and Charges", "Purchase Invoice") purchase_tax_accounts = purchase_taxes_query.run(as_dict=True, pluck="account_head") tax_accounts = purchase_tax_accounts if include_payments: - advance_taxes_query = get_taxes_query( - invoice_list, "Advance Taxes and Charges", "Payment Entry" - ) + advance_taxes_query = get_taxes_query(invoice_list, "Advance Taxes and Charges", "Payment Entry") advance_tax_accounts = advance_taxes_query.run(as_dict=True, pluck="account_head") tax_accounts = set(tax_accounts + advance_tax_accounts) @@ -399,7 +395,7 @@ def get_invoices(filters, additional_query_columns): pi.outstanding_amount, pi.mode_of_payment, ) - .where((pi.docstatus == 1)) + .where(pi.docstatus == 1) .orderby(pi.posting_date, pi.name, order=Order.desc) ) @@ -481,9 +477,7 @@ def get_internal_invoice_map(invoice_list): return internal_invoice_map -def get_invoice_tax_map( - invoice_list, invoice_expense_map, expense_accounts, include_payments=False -): +def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts, include_payments=False): tax_details = frappe.db.sql( """ select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount) @@ -548,9 +542,7 @@ def get_invoice_po_pr_map(invoice_list): invoice_po_pr_map.setdefault(d.parent, frappe._dict()).setdefault("purchase_receipt", pr_list) if d.project: - invoice_po_pr_map.setdefault(d.parent, frappe._dict()).setdefault("project", []).append( - d.project - ) + invoice_po_pr_map.setdefault(d.parent, frappe._dict()).setdefault("project", []).append(d.project) return invoice_po_pr_map diff --git a/erpnext/accounts/report/purchase_register/test_purchase_register.py b/erpnext/accounts/report/purchase_register/test_purchase_register.py index 6903662e6873..a7a5c07152bd 100644 --- a/erpnext/accounts/report/purchase_register/test_purchase_register.py +++ b/erpnext/accounts/report/purchase_register/test_purchase_register.py @@ -3,7 +3,7 @@ import frappe from frappe.tests.utils import FrappeTestCase -from frappe.utils import add_months, getdate, today +from frappe.utils import add_months, today from erpnext.accounts.report.purchase_register.purchase_register import execute @@ -13,9 +13,7 @@ def test_purchase_register(self): frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") - filters = frappe._dict( - company="_Test Company 6", from_date=add_months(today(), -1), to_date=today() - ) + filters = frappe._dict(company="_Test Company 6", from_date=add_months(today(), -1), to_date=today()) pi = make_purchase_invoice() @@ -40,7 +38,7 @@ def test_purchase_register_ledger_view(self): supplier="_Test Supplier", ) - pi = make_purchase_invoice() + make_purchase_invoice() pe = make_payment_entry() report_results = execute(filters) @@ -58,7 +56,7 @@ def make_purchase_invoice(): from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse - gst_acc = create_account( + create_account( account_name="GST", account_type="Tax", parent_account="Duties and Taxes - _TC6", diff --git a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py index 057721479e3b..7c2bf7ee18cc 100644 --- a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py +++ b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py @@ -144,9 +144,9 @@ def get_pos_invoice_data(filters): "ON (" "t1.parent = a.name and t1.base_total = a.base_total) " "WHERE a.docstatus = 1" - " AND {conditions} " + f" AND {conditions} " "GROUP BY " - "owner, posting_date, warehouse".format(conditions=conditions), + "owner, posting_date, warehouse", filters, as_dict=1, ) @@ -156,7 +156,7 @@ def get_pos_invoice_data(filters): def get_sales_invoice_data(filters): conditions = get_conditions(filters) return frappe.db.sql( - """ + f""" select a.posting_date, a.owner, sum(a.net_total) as "net_total", @@ -168,9 +168,7 @@ def get_sales_invoice_data(filters): and {conditions} group by a.owner, a.posting_date - """.format( - conditions=conditions - ), + """, filters, as_dict=1, ) @@ -182,7 +180,7 @@ def get_mode_of_payments(filters): invoice_list_names = ",".join("'" + invoice["name"] + "'" for invoice in invoice_list) if invoice_list: inv_mop = frappe.db.sql( - """select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment + f"""select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment from `tabSales Invoice` a, `tabSales Invoice Payment` b where a.name = b.parent and a.docstatus = 1 @@ -202,9 +200,7 @@ def get_mode_of_payments(filters): and a.docstatus = 1 and b.reference_type = 'Sales Invoice' and b.reference_name in ({invoice_list_names}) - """.format( - invoice_list_names=invoice_list_names - ), + """, as_dict=1, ) for d in inv_mop: @@ -215,11 +211,9 @@ def get_mode_of_payments(filters): def get_invoices(filters): conditions = get_conditions(filters) return frappe.db.sql( - """select a.name + f"""select a.name from `tabSales Invoice` a - where a.docstatus = 1 and {conditions}""".format( - conditions=conditions - ), + where a.docstatus = 1 and {conditions}""", filters, as_dict=1, ) @@ -231,7 +225,7 @@ def get_mode_of_payment_details(filters): invoice_list_names = ",".join("'" + invoice["name"] + "'" for invoice in invoice_list) if invoice_list: inv_mop_detail = frappe.db.sql( - """ + f""" select t.owner, t.posting_date, t.mode_of_payment, @@ -264,23 +258,19 @@ def get_mode_of_payment_details(filters): group by a.owner, a.posting_date, mode_of_payment ) t group by t.owner, t.posting_date, t.mode_of_payment - """.format( - invoice_list_names=invoice_list_names - ), + """, as_dict=1, ) inv_change_amount = frappe.db.sql( - """select a.owner, a.posting_date, + f"""select a.owner, a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment, sum(a.base_change_amount) as change_amount from `tabSales Invoice` a, `tabSales Invoice Payment` b where a.name = b.parent and a.name in ({invoice_list_names}) and b.type = 'Cash' and a.base_change_amount > 0 - group by a.owner, a.posting_date, mode_of_payment""".format( - invoice_list_names=invoice_list_names - ), + group by a.owner, a.posting_date, mode_of_payment""", as_dict=1, ) diff --git a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py index 3ad0ff2ce267..3be96c6de934 100644 --- a/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py +++ b/erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py @@ -33,7 +33,7 @@ def setUpClass(self): def test_get_mode_of_payments(self): filters = get_filters() - for dummy in range(2): + for _dummy in range(2): si = create_sales_invoice_record() si.insert() si.submit() @@ -53,8 +53,8 @@ def test_get_mode_of_payments(self): pe.submit() mop = get_mode_of_payments(filters) - self.assertTrue("Credit Card" in list(mop.values())[0]) - self.assertTrue("Cash" in list(mop.values())[0]) + self.assertTrue("Credit Card" in next(iter(mop.values()))) + self.assertTrue("Cash" in next(iter(mop.values()))) # Cancel all Cash payment entry and check if this mode of payment is still fetched. payment_entries = frappe.get_all( @@ -67,13 +67,13 @@ def test_get_mode_of_payments(self): pe.cancel() mop = get_mode_of_payments(filters) - self.assertTrue("Credit Card" in list(mop.values())[0]) - self.assertTrue("Cash" not in list(mop.values())[0]) + self.assertTrue("Credit Card" in next(iter(mop.values()))) + self.assertTrue("Cash" not in next(iter(mop.values()))) def test_get_mode_of_payments_details(self): filters = get_filters() - for dummy in range(2): + for _dummy in range(2): si = create_sales_invoice_record() si.insert() si.submit() @@ -94,7 +94,7 @@ def test_get_mode_of_payments_details(self): mopd = get_mode_of_payment_details(filters) - mopd_values = list(mopd.values())[0] + mopd_values = next(iter(mopd.values())) for mopd_value in mopd_values: if mopd_value[0] == "Credit Card": cc_init_amount = mopd_value[1] @@ -110,7 +110,7 @@ def test_get_mode_of_payments_details(self): pe.cancel() mopd = get_mode_of_payment_details(filters) - mopd_values = list(mopd.values())[0] + mopd_values = next(iter(mopd.values())) for mopd_value in mopd_values: if mopd_value[0] == "Credit Card": cc_final_amount = mopd_value[1] diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py index 1cb72f8d2d6f..3e7ac1a818d1 100644 --- a/erpnext/accounts/report/sales_register/sales_register.py +++ b/erpnext/accounts/report/sales_register/sales_register.py @@ -129,7 +129,8 @@ def _execute(filters, additional_table_columns=None): if tax_acc not in income_accounts: tax_amount_precision = ( get_field_precision( - frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), currency=company_currency + frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), + currency=company_currency, ) or 2 ) @@ -357,9 +358,7 @@ def get_account_columns(invoice_list, include_payments): tax_accounts = sales_tax_accounts if include_payments: - advance_taxes_query = get_taxes_query( - invoice_list, "Advance Taxes and Charges", "Payment Entry" - ) + advance_taxes_query = get_taxes_query(invoice_list, "Advance Taxes and Charges", "Payment Entry") advance_tax_accounts = advance_taxes_query.run(as_dict=True, pluck="account_head") tax_accounts = set(tax_accounts + advance_tax_accounts) @@ -438,7 +437,7 @@ def get_invoices(filters, additional_query_columns): si.represents_company, si.company, ) - .where((si.docstatus == 1)) + .where(si.docstatus == 1) .orderby(si.posting_date, si.name, order=Order.desc) ) diff --git a/erpnext/accounts/report/share_balance/share_balance.py b/erpnext/accounts/report/share_balance/share_balance.py index d02f53b0d2b5..1d02a996b76a 100644 --- a/erpnext/accounts/report/share_balance/share_balance.py +++ b/erpnext/accounts/report/share_balance/share_balance.py @@ -15,7 +15,7 @@ def execute(filters=None): columns = get_columns(filters) - date = filters.get("date") + filters.get("date") data = [] diff --git a/erpnext/accounts/report/share_ledger/share_ledger.py b/erpnext/accounts/report/share_ledger/share_ledger.py index 629528e5cc71..ed65687a2ede 100644 --- a/erpnext/accounts/report/share_ledger/share_ledger.py +++ b/erpnext/accounts/report/share_ledger/share_ledger.py @@ -26,9 +26,9 @@ def execute(filters=None): for transfer in transfers: if transfer.transfer_type == "Transfer": if transfer.from_shareholder == filters.get("shareholder"): - transfer.transfer_type += " to {}".format(transfer.to_shareholder) + transfer.transfer_type += f" to {transfer.to_shareholder}" else: - transfer.transfer_type += " from {}".format(transfer.from_shareholder) + transfer.transfer_type += f" from {transfer.from_shareholder}" row = [ filters.get("shareholder"), transfer.date, @@ -66,13 +66,11 @@ def get_all_transfers(date, shareholder): # if company: # condition = 'AND company = %(company)s ' return frappe.db.sql( - """SELECT * FROM `tabShare Transfer` + f"""SELECT * FROM `tabShare Transfer` WHERE ((DATE(date) <= %(date)s AND from_shareholder = %(shareholder)s {condition}) OR (DATE(date) <= %(date)s AND to_shareholder = %(shareholder)s {condition})) AND docstatus = 1 - ORDER BY date""".format( - condition=condition - ), + ORDER BY date""", {"date": date, "shareholder": shareholder}, as_dict=1, ) diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py index ba733c2d185d..47b92dd13b06 100644 --- a/erpnext/accounts/report/tax_detail/tax_detail.py +++ b/erpnext/accounts/report/tax_detail/tax_detail.py @@ -34,7 +34,7 @@ def execute(filters=None): fieldstr = get_fieldstr(fieldlist) gl_entries = frappe.db.sql( - """ + f""" select {fieldstr} from `tabGL Entry` ge inner join `tabAccount` a on @@ -52,9 +52,7 @@ def execute(filters=None): ge.posting_date>=%(from_date)s and ge.posting_date<=%(to_date)s order by ge.posting_date, ge.voucher_no - """.format( - fieldstr=fieldstr - ), + """, filters, as_dict=1, ) @@ -94,7 +92,9 @@ def run_report(report_name, data): report[section_name]["subtotal"] += row["amount"] if component["type"] == "section": if component_name == section_name: - frappe.throw(_("A report component cannot refer to its parent section") + ": " + section_name) + frappe.throw( + _("A report component cannot refer to its parent section") + ": " + section_name + ) try: report[section_name]["rows"] += report[component_name]["rows"] report[section_name]["subtotal"] += report[component_name]["subtotal"] diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py index 869f24502182..55ae32a2c6a7 100644 --- a/erpnext/accounts/report/tax_detail/test_tax_detail.py +++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py @@ -21,7 +21,7 @@ def load_testdocs(self): from erpnext.accounts.utils import FiscalYearError, get_fiscal_year datapath, _ = os.path.splitext(os.path.realpath(__file__)) - with open(datapath + ".json", "r") as fp: + with open(datapath + ".json") as fp: docs = json.load(fp) now = getdate() @@ -45,8 +45,9 @@ def load_testdocs(self): "year": "_Test Fiscal", "year_end_date": get_year_ending(now), "year_start_date": get_year_start(now), - } - ] + docs + }, + *docs, + ] docs = [ { @@ -56,8 +57,9 @@ def load_testdocs(self): "default_currency": "GBP", "doctype": "Company", "name": "_T", - } - ] + docs + }, + *docs, + ] for doc in docs: try: @@ -109,9 +111,14 @@ def test_report(self): "Box5": {"Box3": {"type": "section"}, "Box4": {"type": "section"}}, "Box6": {"Filter0": {"type": "filter", "filters": {"3": "!=Tax", "4": "Sales"}}}, "Box7": {"Filter0": {"type": "filter", "filters": {"2": "Expense", "3": "!=Tax"}}}, - "Box8": {"Filter0": {"type": "filter", "filters": {"3": "!=Tax", "4": "Sales", "12": "EU"}}}, + "Box8": { + "Filter0": {"type": "filter", "filters": {"3": "!=Tax", "4": "Sales", "12": "EU"}} + }, "Box9": { - "Filter0": {"type": "filter", "filters": {"2": "Expense", "3": "!=Tax", "12": "EU"}} + "Filter0": { + "type": "filter", + "filters": {"2": "Expense", "3": "!=Tax", "12": "EU"}, + } }, }, "show_detail": 1, 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 82f97f189418..d876d6d14d24 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -67,13 +67,13 @@ def group_by_party_and_category(data, filters): }, ) - party_category_wise_map.get((row.get("party"), row.get("section_code")))[ - "total_amount" - ] += row.get("total_amount", 0.0) + party_category_wise_map.get((row.get("party"), row.get("section_code")))["total_amount"] += row.get( + "total_amount", 0.0 + ) - party_category_wise_map.get((row.get("party"), row.get("section_code")))[ - "tax_amount" - ] += row.get("tax_amount", 0.0) + party_category_wise_map.get((row.get("party"), row.get("section_code")))["tax_amount"] += row.get( + "tax_amount", 0.0 + ) final_result = get_final_result(party_category_wise_map) @@ -82,7 +82,7 @@ def group_by_party_and_category(data, filters): def get_final_result(party_category_wise_map): out = [] - for key, value in party_category_wise_map.items(): + for _key, value in party_category_wise_map.items(): out.append(value) return out diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index c0963150b1fd..fc5e8452e1d1 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -37,9 +37,7 @@ def validate_filters(filters): frappe.throw(_("From Date must be before To Date")) -def get_result( - filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, net_total_map -): +def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, net_total_map): party_map = get_party_pan_map(filters.get("party_type")) tax_rate_map = get_tax_rate_map(filters) gle_map = get_gle_map(tds_docs) @@ -92,9 +90,9 @@ def get_result( party_type = "customer_type" row = { - "pan" - if frappe.db.has_column(filters.party_type, "pan") - else "tax_id": party_map.get(party, {}).get("pan"), + "pan" if frappe.db.has_column(filters.party_type, "pan") else "tax_id": party_map.get( + party, {} + ).get("pan"), "party": party_map.get(party, {}).get("name"), } @@ -157,7 +155,7 @@ def get_gle_map(documents): ) for d in gle: - if not d.voucher_no in gle_map: + if d.voucher_no not in gle_map: gle_map[d.voucher_no] = [d] else: gle_map[d.voucher_no].append(d) @@ -281,7 +279,7 @@ def get_tds_docs(filters): journal_entries = [] tax_category_map = frappe._dict() net_total_map = frappe._dict() - or_filters = frappe._dict() + frappe._dict() journal_entry_party_map = frappe._dict() bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name") @@ -344,7 +342,7 @@ def get_tds_docs_query(filters, bank_accounts, tds_accounts): query = ( frappe.qb.from_(gle) .select("voucher_no", "voucher_type", "against", "party") - .where((gle.is_cancelled == 0)) + .where(gle.is_cancelled == 0) ) if filters.get("from_date"): diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 8b7f0bbc006e..e65f479f0560 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -120,9 +120,7 @@ def get_data(filters): ignore_opening_entries=True, ) - calculate_values( - accounts, gl_entries_by_account, opening_balances, filters.get("show_net_values") - ) + calculate_values(accounts, gl_entries_by_account, opening_balances, filters.get("show_net_values")) accumulate_values_into_parents(accounts, accounts_by_name) data = prepare_data(accounts, filters, parent_children_map, company_currency) @@ -170,9 +168,7 @@ def get_rootwise_opening_balances(filters, report_type): ) # Report getting generate from the mid of a fiscal year - if getdate(last_period_closing_voucher[0].posting_date) < getdate( - add_days(filters.from_date, -1) - ): + if getdate(last_period_closing_voucher[0].posting_date) < getdate(add_days(filters.from_date, -1)): start_date = add_days(last_period_closing_voucher[0].posting_date, 1) gle += get_opening_balance( "GL Entry", filters, report_type, accounting_dimensions, start_date=start_date @@ -253,9 +249,7 @@ def get_opening_balance( if doctype == "Account Closing Balance": opening_balance = opening_balance.where(closing_balance.is_period_closing_voucher_entry == 0) else: - opening_balance = opening_balance.where( - closing_balance.voucher_type != "Period Closing Voucher" - ) + opening_balance = opening_balance.where(closing_balance.voucher_type != "Period Closing Voucher") if filters.cost_center: lft, rgt = frappe.db.get_value("Cost Center", filters.cost_center, ["lft", "rgt"]) @@ -388,7 +382,7 @@ def prepare_data(accounts, filters, parent_children_map, company_currency): "to_date": filters.to_date, "currency": company_currency, "account_name": ( - "{} - {}".format(d.account_number, d.account_name) if d.account_number else d.account_name + f"{d.account_number} - {d.account_name}" if d.account_number else d.account_name ), } diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py index ee223484d478..dd1a12514e20 100644 --- a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py +++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py @@ -22,7 +22,7 @@ def execute(filters=None): def get_data(filters, show_party_name): if filters.get("party_type") in ("Customer", "Supplier", "Employee", "Member"): - party_name_field = "{0}_name".format(frappe.scrub(filters.get("party_type"))) + party_name_field = "{}_name".format(frappe.scrub(filters.get("party_type"))) elif filters.get("party_type") == "Shareholder": party_name_field = "title" else: @@ -65,9 +65,7 @@ def get_data(filters, show_party_name): row.update({"debit": debit, "credit": credit}) # closing - closing_debit, closing_credit = toggle_debit_credit( - opening_debit + debit, opening_credit + credit - ) + closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit) row.update({"closing_debit": closing_debit, "closing_credit": closing_credit}) # totals @@ -92,13 +90,12 @@ def get_data(filters, show_party_name): def get_opening_balances(filters): - account_filter = "" if filters.get("account"): account_filter = "and account = %s" % (frappe.db.escape(filters.get("account"))) gle = frappe.db.sql( - """ + f""" select party, sum(debit) as opening_debit, sum(credit) as opening_credit from `tabGL Entry` where company=%(company)s @@ -106,9 +103,7 @@ def get_opening_balances(filters): and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != '' and (posting_date < %(from_date)s or (ifnull(is_opening, 'No') = 'Yes' and posting_date <= %(to_date)s)) {account_filter} - group by party""".format( - account_filter=account_filter - ), + group by party""", { "company": filters.company, "from_date": filters.from_date, @@ -127,13 +122,12 @@ def get_opening_balances(filters): def get_balances_within_period(filters): - account_filter = "" if filters.get("account"): account_filter = "and account = %s" % (frappe.db.escape(filters.get("account"))) gle = frappe.db.sql( - """ + f""" select party, sum(debit) as debit, sum(credit) as credit from `tabGL Entry` where company=%(company)s @@ -142,9 +136,7 @@ def get_balances_within_period(filters): and posting_date >= %(from_date)s and posting_date <= %(to_date)s and ifnull(is_opening, 'No') = 'No' {account_filter} - group by party""".format( - account_filter=account_filter - ), + group by party""", { "company": filters.company, "from_date": filters.from_date, diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index 795cab900c11..3fa62b583a12 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -78,10 +78,10 @@ def get_rate_as_at(date, from_currency, to_currency): :return: Retrieved exchange rate """ - rate = __exchange_rates.get("{0}-{1}@{2}".format(from_currency, to_currency, date)) + rate = __exchange_rates.get(f"{from_currency}-{to_currency}@{date}") if not rate: rate = get_exchange_rate(from_currency, to_currency, date) or 1 - __exchange_rates["{0}-{1}@{2}".format(from_currency, to_currency, date)] = rate + __exchange_rates[f"{from_currency}-{to_currency}@{date}"] = rate return rate @@ -136,9 +136,7 @@ def get_appropriate_company(filters): @frappe.whitelist() -def get_invoiced_item_gross_margin( - sales_invoice=None, item_code=None, company=None, with_item_data=False -): +def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=None, with_item_data=False): from erpnext.accounts.report.gross_profit.gross_profit import GrossProfitGenerator sales_invoice = sales_invoice or frappe.form_dict.get("sales_invoice") diff --git a/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.py b/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.py index bd9e9fccadce..1918165c6db0 100644 --- a/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.py +++ b/erpnext/accounts/report/voucher_wise_balance/voucher_wise_balance.py @@ -43,9 +43,7 @@ def get_data(filters): gle = frappe.qb.DocType("GL Entry") query = ( frappe.qb.from_(gle) - .select( - gle.voucher_type, gle.voucher_no, Sum(gle.debit).as_("debit"), Sum(gle.credit).as_("credit") - ) + .select(gle.voucher_type, gle.voucher_no, Sum(gle.debit).as_("debit"), Sum(gle.credit).as_("credit")) .where(gle.is_cancelled == 0) .groupby(gle.voucher_no) ) diff --git a/erpnext/accounts/test/test_reports.py b/erpnext/accounts/test/test_reports.py index 3f06c30adb69..9496a1aa6643 100644 --- a/erpnext/accounts/test/test_reports.py +++ b/erpnext/accounts/test/test_reports.py @@ -1,5 +1,4 @@ import unittest -from typing import List, Tuple from erpnext.tests.utils import ReportFilters, ReportName, execute_script_report @@ -12,7 +11,7 @@ } -REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [ +REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [ ("General Ledger", {"group_by": "Group by Voucher (Consolidated)"}), ("General Ledger", {"group_by": "Group by Voucher (Consolidated)", "include_dimensions": 1}), ("Accounts Payable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}), diff --git a/erpnext/accounts/test/test_utils.py b/erpnext/accounts/test/test_utils.py index 660cb62d2c5f..59cbc11794f4 100644 --- a/erpnext/accounts/test/test_utils.py +++ b/erpnext/accounts/test/test_utils.py @@ -19,7 +19,7 @@ class TestUtils(unittest.TestCase): @classmethod def setUpClass(cls): - super(TestUtils, cls).setUpClass() + super().setUpClass() make_test_objects("Address", ADDRESS_RECORDS) @classmethod @@ -35,7 +35,6 @@ def test_get_party_shipping_address2(self): self.assertEqual(address, "_Test Shipping Address 2 Title-Shipping") def test_get_voucher_wise_gl_entry(self): - pr = make_purchase_receipt( item_code="_Test Item", posting_date="2021-02-01", @@ -143,12 +142,8 @@ def test_naming_series_variable_parsing(self): frappe.db.set_default("supp_master_name", "Auto Name") # Configure Autoname in Supplier DocType - make_property_setter( - "Supplier", None, "naming_rule", "Expression", "Data", for_doctype="Doctype" - ) - make_property_setter( - "Supplier", None, "autoname", "SUP-.FY.-.#####", "Data", for_doctype="Doctype" - ) + make_property_setter("Supplier", None, "naming_rule", "Expression", "Data", for_doctype="Doctype") + make_property_setter("Supplier", None, "autoname", "SUP-.FY.-.#####", "Data", for_doctype="Doctype") fiscal_year = get_fiscal_year(nowdate())[0] @@ -170,9 +165,7 @@ def test_naming_series_variable_parsing(self): "address_title": "_Test Billing Address Title", "city": "Lagos", "country": "Nigeria", - "links": [ - {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} - ], + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"}], }, { "doctype": "Address", @@ -181,9 +174,7 @@ def test_naming_series_variable_parsing(self): "address_title": "_Test Shipping Address 1 Title", "city": "Lagos", "country": "Nigeria", - "links": [ - {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} - ], + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"}], }, { "doctype": "Address", @@ -193,9 +184,7 @@ def test_naming_series_variable_parsing(self): "city": "Lagos", "country": "Nigeria", "is_shipping_address": "1", - "links": [ - {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} - ], + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"}], }, { "doctype": "Address", @@ -205,8 +194,6 @@ def test_naming_series_variable_parsing(self): "city": "Lagos", "country": "Nigeria", "is_shipping_address": "1", - "links": [ - {"link_doctype": "Customer", "link_name": "_Test Customer 1", "doctype": "Dynamic Link"} - ], + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer 1", "doctype": "Dynamic Link"}], }, ] diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index a32c25fbb709..d966074b2ae0 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -3,7 +3,7 @@ from json import loads -from typing import TYPE_CHECKING, List, Optional, Tuple +from typing import TYPE_CHECKING, Optional import frappe import frappe.defaults @@ -31,7 +31,7 @@ import erpnext # imported to enable erpnext.accounts.utils.get_account_currency -from erpnext.accounts.doctype.account.account import get_account_currency # noqa +from erpnext.accounts.doctype.account.account import get_account_currency from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions from erpnext.stock import get_warehouse_account_map from erpnext.stock.utils import get_stock_value_on @@ -80,9 +80,7 @@ def get_fiscal_years( FY = DocType("Fiscal Year") query = ( - frappe.qb.from_(FY) - .select(FY.name, FY.year_start_date, FY.year_end_date) - .where(FY.disabled == 0) + frappe.qb.from_(FY).select(FY.name, FY.year_start_date, FY.year_end_date).where(FY.disabled == 0) ) if fiscal_year: @@ -129,9 +127,7 @@ def get_fiscal_years( else: return ((fy.name, fy.year_start_date, fy.year_end_date),) - error_msg = _("""{0} {1} is not in any active Fiscal Year""").format( - label, formatdate(transaction_date) - ) + error_msg = _("""{0} {1} is not in any active Fiscal Year""").format(label, formatdate(transaction_date)) if company: error_msg = _("""{0} for {1}""").format(error_msg, frappe.bold(company)) @@ -207,12 +203,12 @@ def get_balance_on( acc = frappe.get_doc("Account", account) try: - year_start_date = get_fiscal_year(date, company=company, verbose=0)[1] + get_fiscal_year(date, company=company, verbose=0)[1] except FiscalYearError: if getdate(date) > getdate(nowdate()): # if fiscal year not found and the date is greater than today # get fiscal year for today's date and its corresponding year start date - year_start_date = get_fiscal_year(nowdate(), verbose=1)[1] + get_fiscal_year(nowdate(), verbose=1)[1] else: # this indicates that it is a date older than any existing fiscal year. # hence, assuming balance as 0.0 @@ -227,29 +223,26 @@ def get_balance_on( cc = frappe.get_doc("Cost Center", cost_center) if cc.is_group: cond.append( - """ exists ( + f""" exists ( select 1 from `tabCost Center` cc where cc.name = gle.cost_center - and cc.lft >= %s and cc.rgt <= %s + and cc.lft >= {cc.lft} and cc.rgt <= {cc.rgt} )""" - % (cc.lft, cc.rgt) ) else: - cond.append("""gle.cost_center = %s """ % (frappe.db.escape(cost_center, percent=False),)) + cond.append(f"""gle.cost_center = {frappe.db.escape(cost_center, percent=False)} """) if account: - if not (frappe.flags.ignore_account_permission or ignore_account_permission): acc.check_permission("read") # different filter for group and ledger - improved performance if acc.is_group: cond.append( - """exists ( + f"""exists ( select name from `tabAccount` ac where ac.name = gle.account - and ac.lft >= %s and ac.rgt <= %s + and ac.lft >= {acc.lft} and ac.rgt <= {acc.rgt} )""" - % (acc.lft, acc.rgt) ) # If group and currency same as company, @@ -257,12 +250,11 @@ def get_balance_on( if acc.account_currency == frappe.get_cached_value("Company", acc.company, "default_currency"): in_account_currency = False else: - cond.append("""gle.account = %s """ % (frappe.db.escape(account, percent=False),)) + cond.append(f"""gle.account = {frappe.db.escape(account, percent=False)} """) if party_type and party: cond.append( - """gle.party_type = %s and gle.party = %s """ - % (frappe.db.escape(party_type), frappe.db.escape(party, percent=False)) + f"""gle.party_type = {frappe.db.escape(party_type)} and gle.party = {frappe.db.escape(party, percent=False)} """ ) if company: @@ -275,11 +267,9 @@ def get_balance_on( select_field = "sum(debit) - sum(credit)" bal = frappe.db.sql( """ - SELECT {0} + SELECT {} FROM `tabGL Entry` gle - WHERE {1}""".format( - select_field, " and ".join(cond) - ) + WHERE {}""".format(select_field, " and ".join(cond)) )[0][0] # if bal is None, return 0 @@ -314,30 +304,25 @@ def get_count_on(account, fieldname, date): # for pl accounts, get balance within a fiscal year if acc.report_type == "Profit and Loss": - cond.append( - "posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" % year_start_date - ) + cond.append("posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" % year_start_date) # different filter for group and ledger - improved performance if acc.is_group: cond.append( - """exists ( + f"""exists ( select name from `tabAccount` ac where ac.name = gle.account - and ac.lft >= %s and ac.rgt <= %s + and ac.lft >= {acc.lft} and ac.rgt <= {acc.rgt} )""" - % (acc.lft, acc.rgt) ) else: - cond.append("""gle.account = %s """ % (frappe.db.escape(account, percent=False),)) + cond.append(f"""gle.account = {frappe.db.escape(account, percent=False)} """) entries = frappe.db.sql( """ SELECT name, posting_date, account, party_type, party,debit,credit, voucher_type, voucher_no, against_voucher_type, against_voucher FROM `tabGL Entry` gle - WHERE {0}""".format( - " and ".join(cond) - ), + WHERE {}""".format(" and ".join(cond)), as_dict=True, ) @@ -360,13 +345,11 @@ def get_count_on(account, fieldname, date): or (gle.against_voucher == gle.voucher_no and gle.get(dr_or_cr) > 0) ): payment_amount = frappe.db.sql( - """ - SELECT {0} + f""" + SELECT {select_fields} FROM `tabGL Entry` gle WHERE docstatus < 2 and posting_date <= %(date)s and against_voucher = %(voucher_no)s - and party = %(party)s and name != %(name)s""".format( - select_fields - ), + and party = %(party)s and name != %(name)s""", {"date": date, "voucher_no": gle.voucher_no, "party": gle.party, "name": gle.name}, )[0][0] @@ -421,7 +404,7 @@ def add_cc(args=None): args = make_tree_args(**args) if args.parent_cost_center == args.company: - args.parent_cost_center = "{0} - {1}".format( + args.parent_cost_center = "{} - {}".format( args.parent_cost_center, frappe.get_cached_value("Company", args.company, "abbr") ) @@ -437,7 +420,7 @@ def add_cc(args=None): def _build_dimensions_dict_for_exc_gain_loss( - entry: dict | object = None, active_dimensions: list = None + entry: dict | object = None, active_dimensions: list | None = None ): dimensions_dict = frappe._dict() if entry and active_dimensions: @@ -501,7 +484,11 @@ def reconcile_against_document( # 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 + entry.against_voucher_type, + entry.against_voucher, + entry.account, + entry.party_type, + entry.party, ) frappe.flags.ignore_party_validation = False @@ -525,9 +512,7 @@ def check_if_advance_entry_modified(args): and t2.party_type = %(party_type)s and t2.party = %(party)s and (t2.reference_type is null or t2.reference_type in ('', 'Sales Order', 'Purchase Order')) and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s - and t1.docstatus=1 """.format( - dr_or_cr=args.get("dr_or_cr") - ), + and t1.docstatus=1 """.format(dr_or_cr=args.get("dr_or_cr")), args, ) else: @@ -542,12 +527,10 @@ def check_if_advance_entry_modified(args): where t1.name = t2.parent and t1.docstatus = 1 and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s - and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{0} = %(account)s + and t1.party_type = %(party_type)s and t1.party = %(party)s and t1.{} = %(account)s and t2.reference_doctype in ('', 'Sales Order', 'Purchase Order') and t2.allocated_amount = %(unreconciled_amount)s - """.format( - party_account_field - ), + """.format(party_account_field), args, ) else: @@ -571,9 +554,7 @@ def check_if_advance_entry_modified(args): def validate_allocated_amount(args): - precision = args.get("precision") or frappe.db.get_single_value( - "System Settings", "currency_precision" - ) + precision = args.get("precision") or frappe.db.get_single_value("System Settings", "currency_precision") if args.get("allocated_amount") < 0: throw(_("Allocated amount cannot be negative")) elif flt(args.get("allocated_amount"), precision) > flt(args.get("unadjusted_amount"), precision): @@ -708,7 +689,7 @@ def update_reference_in_payment_entry( def cancel_exchange_gain_loss_journal( - parent_doc: dict | object, referenced_dt: str = None, referenced_dn: str = None + parent_doc: dict | object, referenced_dt: str | None = None, referenced_dn: str | None = None ) -> None: """ Cancel Exchange Gain/Loss for Sales/Purchase Invoice, if they have any. @@ -751,7 +732,7 @@ def cancel_exchange_gain_loss_journal( def update_accounting_ledgers_after_reference_removal( - ref_type: str = None, ref_no: str = None, payment_name: str = None + ref_type: str | None = None, ref_no: str | None = None, payment_name: str | None = None ): # General Ledger gle = qb.DocType("GL Entry") @@ -777,9 +758,7 @@ def update_accounting_ledgers_after_reference_removal( .set(ple.modified, now()) .set(ple.modified_by, frappe.session.user) .where( - (ple.against_voucher_type == ref_type) - & (ple.against_voucher_no == ref_no) - & (ple.delinked == 0) + (ple.against_voucher_type == ref_type) & (ple.against_voucher_no == ref_no) & (ple.delinked == 0) ) ) @@ -796,7 +775,7 @@ def remove_ref_from_advance_section(ref_doc: object = None): qb.from_(adv_type).delete().where(adv_type.parent == ref_doc.name).run() -def unlink_ref_doc_from_payment_entries(ref_doc: object = None, payment_name: str = None): +def unlink_ref_doc_from_payment_entries(ref_doc: object = None, payment_name: str | None = None): remove_ref_doc_link_from_jv(ref_doc.doctype, ref_doc.name, payment_name) remove_ref_doc_link_from_pe(ref_doc.doctype, ref_doc.name, payment_name) update_accounting_ledgers_after_reference_removal(ref_doc.doctype, ref_doc.name, payment_name) @@ -804,7 +783,7 @@ def unlink_ref_doc_from_payment_entries(ref_doc: object = None, payment_name: st def remove_ref_doc_link_from_jv( - ref_type: str = None, ref_no: str = None, payment_name: str = None + ref_type: str | None = None, ref_no: str | None = None, payment_name: str | None = None ): jea = qb.DocType("Journal Entry Account") @@ -844,7 +823,7 @@ def convert_to_list(result): def remove_ref_doc_link_from_pe( - ref_type: str = None, ref_no: str = None, payment_name: str = None + ref_type: str | None = None, ref_no: str | None = None, payment_name: str | None = None ): per = qb.DocType("Payment Entry Reference") pay = qb.DocType("Payment Entry") @@ -852,9 +831,7 @@ def remove_ref_doc_link_from_pe( linked_pe = ( qb.from_(per) .select(per.parent) - .where( - (per.reference_doctype == ref_type) & (per.reference_name == ref_no) & (per.docstatus.lt(2)) - ) + .where((per.reference_doctype == ref_type) & (per.reference_name == ref_no) & (per.docstatus.lt(2))) .run(as_list=1) ) linked_pe = convert_to_list(linked_pe) @@ -867,9 +844,7 @@ def remove_ref_doc_link_from_pe( .set(per.allocated_amount, 0) .set(per.modified, now()) .set(per.modified_by, frappe.session.user) - .where( - (per.docstatus.lt(2) & (per.reference_doctype == ref_type) & (per.reference_name == ref_no)) - ) + .where(per.docstatus.lt(2) & (per.reference_doctype == ref_type) & (per.reference_name == ref_no)) ) if payment_name: @@ -883,7 +858,7 @@ def remove_ref_doc_link_from_pe( pe_doc.set_amounts() pe_doc.clear_unallocated_reference_document_rows() pe_doc.validate_payment_type_with_outstanding() - except Exception as e: + except Exception: msg = _("There were issues unlinking payment entry {0}.").format(pe_doc.name) msg += "
" msg += _("Please cancel payment entry manually first") @@ -893,9 +868,7 @@ def remove_ref_doc_link_from_pe( pay.base_total_allocated_amount, pe_doc.base_total_allocated_amount ).set(pay.unallocated_amount, pe_doc.unallocated_amount).set(pay.modified, now()).set( pay.modified_by, frappe.session.user - ).where( - pay.name == pe - ).run() + ).where(pay.name == pe).run() frappe.msgprint(_("Payment Entries {0} are un-linked").format("\n".join(linked_pe))) @@ -929,9 +902,10 @@ def fix_total_debit_credit(): dr_or_cr = d.voucher_type == "Sales Invoice" and "credit" or "debit" frappe.db.sql( - """update `tabGL Entry` set %s = %s + %s - where voucher_type = %s and voucher_no = %s and %s > 0 limit 1""" - % (dr_or_cr, dr_or_cr, "%s", "%s", "%s", dr_or_cr), + """update `tabGL Entry` set {} = {} + {} + where voucher_type = {} and voucher_no = {} and {} > 0 limit 1""".format( + dr_or_cr, dr_or_cr, "%s", "%s", "%s", dr_or_cr + ), (d.diff, d.voucher_type, d.voucher_no), ) @@ -956,20 +930,22 @@ def get_stock_rbnb_difference(posting_date, company): """ select sum(pr_item.valuation_rate * pr_item.qty * pr_item.conversion_factor) from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr - where pr.name = pr_item.parent and pr.docstatus=1 and pr.company=%s - and pr.posting_date <= %s and pr_item.item_code in (%s)""" - % ("%s", "%s", ", ".join(["%s"] * len(stock_items))), - tuple([company, posting_date] + stock_items), + where pr.name = pr_item.parent and pr.docstatus=1 and pr.company={} + and pr.posting_date <= {} and pr_item.item_code in ({})""".format( + "%s", "%s", ", ".join(["%s"] * len(stock_items)) + ), + tuple([company, posting_date, *stock_items]), )[0][0] pi_valuation_amount = frappe.db.sql( """ select sum(pi_item.valuation_rate * pi_item.qty * pi_item.conversion_factor) from `tabPurchase Invoice Item` pi_item, `tabPurchase Invoice` pi - where pi.name = pi_item.parent and pi.docstatus=1 and pi.company=%s - and pi.posting_date <= %s and pi_item.item_code in (%s)""" - % ("%s", "%s", ", ".join(["%s"] * len(stock_items))), - tuple([company, posting_date] + stock_items), + where pi.name = pi_item.parent and pi.docstatus=1 and pi.company={} + and pi.posting_date <= {} and pi_item.item_code in ({})""".format( + "%s", "%s", ", ".join(["%s"] * len(stock_items)) + ), + tuple([company, posting_date, *stock_items]), )[0][0] # Balance should be @@ -1014,15 +990,12 @@ def get_outstanding_invoices( limit=None, # passed by reconciliation tool voucher_no=None, # filter passed by reconciliation tool ): - ple = qb.DocType("Payment Ledger Entry") outstanding_invoices = [] precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2 if account: - root_type, account_type = frappe.get_cached_value( - "Account", account, ["root_type", "account_type"] - ) + root_type, account_type = frappe.get_cached_value("Account", account, ["root_type", "account_type"]) party_account_type = "Receivable" if root_type == "Asset" else "Payable" party_account_type = account_type or party_account_type else: @@ -1076,15 +1049,11 @@ def get_outstanding_invoices( ) ) - outstanding_invoices = sorted( - outstanding_invoices, key=lambda k: k["due_date"] or getdate(nowdate()) - ) + outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k["due_date"] or getdate(nowdate())) return outstanding_invoices -def get_account_name( - account_type=None, root_type=None, is_group=None, account_currency=None, company=None -): +def get_account_name(account_type=None, root_type=None, is_group=None, account_currency=None, company=None): """return account based on matching conditions""" return frappe.db.get_value( "Account", @@ -1113,7 +1082,7 @@ def get_children(doctype, parent, company, is_root=False): fields = ["name as value", "is_group as expandable"] filters = [["docstatus", "<", 2]] - filters.append(['ifnull(`{0}`,"")'.format(parent_fieldname), "=", "" if is_root else parent]) + filters.append([f'ifnull(`{parent_fieldname}`,"")', "=", "" if is_root else parent]) if is_root: fields += ["root_type", "report_type", "account_currency"] if doctype == "Account" else [] @@ -1133,7 +1102,6 @@ def get_children(doctype, parent, company, is_root=False): @frappe.whitelist() def get_account_balances(accounts, company): - if isinstance(accounts, str): accounts = loads(accounts) @@ -1144,9 +1112,7 @@ def get_account_balances(accounts, company): for account in accounts: account["company_currency"] = company_currency - account["balance"] = flt( - get_balance_on(account["value"], in_account_currency=False, company=company) - ) + account["balance"] = flt(get_balance_on(account["value"], in_account_currency=False, company=company)) if account["account_currency"] and account["account_currency"] != company_currency: account["balance_in_account_currency"] = flt(get_balance_on(account["value"], company=company)) @@ -1296,20 +1262,17 @@ def update_gl_entries_after( warehouse_account=None, company=None, ): - stock_vouchers = get_future_stock_vouchers( - posting_date, posting_time, for_warehouses, for_items, company - ) + stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items, company) repost_gle_for_stock_vouchers(stock_vouchers, posting_date, company, warehouse_account) def repost_gle_for_stock_vouchers( - stock_vouchers: List[Tuple[str, str]], + stock_vouchers: list[tuple[str, str]], posting_date: str, - company: Optional[str] = None, + company: str | None = None, warehouse_account=None, repost_doc: Optional["RepostItemValuation"] = None, ): - from erpnext.accounts.general_ledger import toggle_debit_credit_if_negative if not stock_vouchers: @@ -1355,16 +1318,12 @@ def repost_gle_for_stock_vouchers( def _delete_pl_entries(voucher_type, voucher_no): ple = qb.DocType("Payment Ledger Entry") - qb.from_(ple).delete().where( - (ple.voucher_type == voucher_type) & (ple.voucher_no == voucher_no) - ).run() + qb.from_(ple).delete().where((ple.voucher_type == voucher_type) & (ple.voucher_no == voucher_no)).run() def _delete_gl_entries(voucher_type, voucher_no): gle = qb.DocType("GL Entry") - qb.from_(gle).delete().where( - (gle.voucher_type == voucher_type) & (gle.voucher_no == voucher_no) - ).run() + qb.from_(gle).delete().where((gle.voucher_type == voucher_type) & (gle.voucher_no == voucher_no)).run() def _delete_accounting_ledger_entries(voucher_type, voucher_no): @@ -1375,9 +1334,7 @@ def _delete_accounting_ledger_entries(voucher_type, voucher_no): _delete_pl_entries(voucher_type, voucher_no) -def sort_stock_vouchers_by_posting_date( - stock_vouchers: List[Tuple[str, str]] -) -> List[Tuple[str, str]]: +def sort_stock_vouchers_by_posting_date(stock_vouchers: list[tuple[str, str]]) -> list[tuple[str, str]]: sle = frappe.qb.DocType("Stock Ledger Entry") voucher_nos = [v[1] for v in stock_vouchers] @@ -1398,10 +1355,7 @@ def sort_stock_vouchers_by_posting_date( return sorted_vouchers -def get_future_stock_vouchers( - posting_date, posting_time, for_warehouses=None, for_items=None, company=None -): - +def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None, company=None): values = [] condition = "" if for_items: @@ -1417,16 +1371,14 @@ def get_future_stock_vouchers( values.append(company) future_stock_vouchers = frappe.db.sql( - """select distinct sle.voucher_type, sle.voucher_no + f"""select distinct sle.voucher_type, sle.voucher_no from `tabStock Ledger Entry` sle where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) and is_cancelled = 0 {condition} - order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format( - condition=condition - ), - tuple([posting_date, posting_time] + values), + order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""", + tuple([posting_date, posting_time, *values]), as_dict=True, ) @@ -1453,9 +1405,8 @@ def get_voucherwise_gl_entries(future_stock_vouchers, posting_date): select name, account, credit, debit, cost_center, project, voucher_type, voucher_no from `tabGL Entry` where - posting_date >= %s and voucher_no in (%s)""" - % ("%s", ", ".join(["%s"] * len(voucher_nos))), - tuple([posting_date] + voucher_nos), + posting_date >= {} and voucher_no in ({})""".format("%s", ", ".join(["%s"] * len(voucher_nos))), + tuple([posting_date, *voucher_nos]), as_dict=1, ) @@ -1494,16 +1445,16 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle, precision): def get_stock_accounts(company, voucher_type=None, voucher_no=None): stock_accounts = [ d.name - for d in frappe.db.get_all( - "Account", {"account_type": "Stock", "company": company, "is_group": 0} - ) + for d in frappe.db.get_all("Account", {"account_type": "Stock", "company": company, "is_group": 0}) ] if voucher_type and voucher_no: if voucher_type == "Journal Entry": stock_accounts = [ d.account for d in frappe.db.get_all( - "Journal Entry Account", {"parent": voucher_no, "account": ["in", stock_accounts]}, "account" + "Journal Entry Account", + {"parent": voucher_no, "account": ["in", stock_accounts]}, + "account", ) ] @@ -1512,7 +1463,11 @@ def get_stock_accounts(company, voucher_type=None, voucher_no=None): d.account for d in frappe.db.get_all( "GL Entry", - {"voucher_type": voucher_type, "voucher_no": voucher_no, "account": ["in", stock_accounts]}, + { + "voucher_type": voucher_type, + "voucher_no": voucher_no, + "account": ["in", stock_accounts], + }, "account", ) ] @@ -1543,9 +1498,7 @@ def get_stock_and_account_balance(account=None, posting_date=None, company=None) def get_journal_entry(account, stock_adjustment_account, amount): - db_or_cr_warehouse_account = ( - "credit_in_account_currency" if amount < 0 else "debit_in_account_currency" - ) + db_or_cr_warehouse_account = "credit_in_account_currency" if amount < 0 else "debit_in_account_currency" db_or_cr_stock_adjustment_account = ( "debit_in_account_currency" if amount < 0 else "credit_in_account_currency" ) @@ -1566,7 +1519,7 @@ def check_and_delete_linked_reports(report): frappe.delete_doc("Desktop Icon", icon) -def create_err_and_its_journals(companies: list = None) -> None: +def create_err_and_its_journals(companies: list | None = None) -> None: if companies: for company in companies: err = frappe.new_doc("Exchange Rate Revaluation") @@ -1623,9 +1576,7 @@ def get_payment_ledger_entries(gl_entries, cancel=0): accounts_with_types = ( qb.from_(account) .select(account.name, account.account_type) - .where( - (account.account_type.isin(["Receivable", "Payable"]) & (account.company.isin(companies))) - ) + .where(account.account_type.isin(["Receivable", "Payable"]) & (account.company.isin(companies))) .run(as_dict=True) ) receivable_or_payable_accounts = [y.name for y in accounts_with_types] @@ -1692,7 +1643,6 @@ def create_payment_ledger_entry( ple_map = get_payment_ledger_entries(gl_entries, cancel=cancel) for entry in ple_map: - ple = frappe.get_doc(entry) if cancel: @@ -1770,7 +1720,7 @@ def delink_original_entry(pl_entry, partial_cancel=False): query.run() -class QueryPaymentLedger(object): +class QueryPaymentLedger: """ Helper Class for Querying Payment Ledger Entry """ @@ -1938,7 +1888,8 @@ def query_for_outstanding(self): Table("outstanding").amount_in_account_currency.as_("outstanding_in_account_currency"), (Table("vouchers").amount - Table("outstanding").amount).as_("paid_amount"), ( - Table("vouchers").amount_in_account_currency - Table("outstanding").amount_in_account_currency + Table("vouchers").amount_in_account_currency + - Table("outstanding").amount_in_account_currency ).as_("paid_amount_in_account_currency"), Table("vouchers").due_date, Table("vouchers").currency, diff --git a/erpnext/assets/dashboard_fixtures.py b/erpnext/assets/dashboard_fixtures.py index fc9ba386a382..3b1d14440cfc 100644 --- a/erpnext/assets/dashboard_fixtures.py +++ b/erpnext/assets/dashboard_fixtures.py @@ -12,7 +12,6 @@ def get_data(): - fiscal_year = _get_fiscal_year(nowdate()) if not fiscal_year: @@ -168,9 +167,7 @@ def get_number_cards(fiscal_year, year_start_date, year_end_date): "is_public": 1, "show_percentage_stats": 1, "stats_time_interval": "Monthly", - "filters_json": json.dumps( - [["Asset", "creation", "between", [year_start_date, year_end_date]]] - ), + "filters_json": json.dumps([["Asset", "creation", "between", [year_start_date, year_end_date]]]), "doctype": "Number Card", }, { diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 95c627735d63..fd00a4950301 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -85,9 +85,7 @@ def validate_asset_and_reference(self): ) if self.is_existing_asset and self.purchase_invoice: - frappe.throw( - _("Purchase Invoice cannot be made against an existing asset {0}").format(self.name) - ) + frappe.throw(_("Purchase Invoice cannot be made against an existing asset {0}").format(self.name)) def prepare_depreciation_data( self, @@ -207,9 +205,9 @@ def validate_in_use_date(self): for d in self.finance_books: if d.depreciation_start_date == self.available_for_use_date: frappe.throw( - _("Row #{}: Depreciation Posting Date should not be equal to Available for Use Date.").format( - d.idx - ), + _( + "Row #{}: Depreciation Posting Date should not be equal to Available for Use Date." + ).format(d.idx), title=_("Incorrect Date"), ) @@ -218,9 +216,7 @@ def set_missing_values(self): self.asset_category = frappe.get_cached_value("Item", self.item_code, "asset_category") if self.item_code and not self.get("finance_books"): - finance_books = get_item_details( - self.item_code, self.asset_category, self.gross_purchase_amount - ) + finance_books = get_item_details(self.item_code, self.asset_category, self.gross_purchase_amount) self.set("finance_books", finance_books) def validate_finance_books(self): @@ -270,7 +266,9 @@ def validate_asset_values(self): and not frappe.db.get_value("Purchase Invoice", self.purchase_invoice, "update_stock") ): frappe.throw( - _("Update stock must be enabled for the purchase invoice {0}").format(self.purchase_invoice) + _("Update stock must be enabled for the purchase invoice {0}").format( + self.purchase_invoice + ) ) if not self.calculate_depreciation: @@ -284,9 +282,7 @@ def validate_asset_values(self): if self.is_existing_asset: return - if self.available_for_use_date and getdate(self.available_for_use_date) < getdate( - self.purchase_date - ): + if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(self.purchase_date): frappe.throw(_("Available-for-use Date should be after purchase date")) def validate_gross_and_purchase_amount(self): @@ -309,7 +305,7 @@ def make_asset_movement(self): posting_date, posting_time = frappe.db.get_value( reference_doctype, reference_docname, ["posting_date", "posting_time"] ) - transaction_date = get_datetime("{} {}".format(posting_date, posting_time)) + transaction_date = get_datetime(f"{posting_date} {posting_time}") assets = [ { "asset": self.name, @@ -347,9 +343,7 @@ def make_depreciation_schedule(self, date_of_disposal=None, value_after_deprecia start = self.clear_depreciation_schedule() for finance_book in self.get("finance_books"): - self._make_depreciation_schedule( - finance_book, start, date_of_disposal, value_after_depreciation - ) + self._make_depreciation_schedule(finance_book, start, date_of_disposal, value_after_depreciation) if len(self.get("finance_books")) > 1 and any(start): self.sort_depreciation_schedule() @@ -467,7 +461,10 @@ def _make_depreciation_schedule( from_date = get_last_day( add_months( getdate(self.available_for_use_date), - ((self.number_of_depreciations_booked - 1) * finance_book.frequency_of_depreciation), + ( + (self.number_of_depreciations_booked - 1) + * finance_book.frequency_of_depreciation + ), ) ) else: @@ -489,7 +486,8 @@ def _make_depreciation_schedule( # In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission self.to_date = add_months( self.available_for_use_date, - (n + self.number_of_depreciations_booked) * cint(finance_book.frequency_of_depreciation), + (n + self.number_of_depreciations_booked) + * cint(finance_book.frequency_of_depreciation), ) depreciation_amount_without_pro_rata = depreciation_amount @@ -519,9 +517,7 @@ def _make_depreciation_schedule( if ( n == cint(final_number_of_depreciations) - 1 and flt(value_after_depreciation) != flt(finance_book.expected_value_after_useful_life) - ) or flt(value_after_depreciation) < flt( - finance_book.expected_value_after_useful_life - ): + ) or flt(value_after_depreciation) < flt(finance_book.expected_value_after_useful_life): depreciation_amount += flt(value_after_depreciation) - flt( finance_book.expected_value_after_useful_life ) @@ -672,7 +668,8 @@ def validate_asset_finance_books(self, row): if not row.depreciation_start_date: if not self.available_for_use_date: frappe.throw( - _("Row {0}: Depreciation Start Date is required").format(row.idx), title=_("Invalid Schedule") + _("Row {0}: Depreciation Start Date is required").format(row.idx), + title=_("Invalid Schedule"), ) row.depreciation_start_date = get_last_day(self.available_for_use_date) @@ -702,9 +699,7 @@ def validate_asset_finance_books(self, row): title=_("Invalid Schedule"), ) - if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate( - self.purchase_date - ): + if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.purchase_date): frappe.throw( _("Depreciation Row {0}: Next Depreciation Date cannot be before Purchase Date").format( row.idx @@ -900,11 +895,14 @@ def get_status(self): if self.calculate_depreciation: idx = self.get_default_finance_book_idx() or 0 - expected_value_after_useful_life = self.finance_books[idx].expected_value_after_useful_life + expected_value_after_useful_life = self.finance_books[ + idx + ].expected_value_after_useful_life value_after_depreciation = self.finance_books[idx].value_after_depreciation if ( - flt(value_after_depreciation) <= expected_value_after_useful_life or self.is_fully_depreciated + flt(value_after_depreciation) <= expected_value_after_useful_life + or self.is_fully_depreciated ): status = "Fully Depreciated" elif flt(value_after_depreciation) < flt(self.gross_purchase_amount): @@ -1016,7 +1014,6 @@ def make_gl_entries(self): and self.purchase_receipt_amount and getdate(self.available_for_use_date) <= getdate() ): - gl_entries.append( self.get_gl_dict( { @@ -1055,9 +1052,7 @@ def make_gl_entries(self): @frappe.whitelist() def get_manual_depreciation_entries(self): - (_, _, depreciation_expense_account) = get_depreciation_accounts( - self.asset_category, self.company - ) + (_, _, depreciation_expense_account) = get_depreciation_accounts(self.asset_category, self.company) gle = frappe.qb.DocType("GL Entry") @@ -1084,7 +1079,8 @@ def get_depreciation_rate(self, args, on_validate=False): if args.get("depreciation_method") == "Double Declining Balance": return 200.0 / ( ( - flt(args.get("total_number_of_depreciations"), 2) * flt(args.get("frequency_of_depreciation")) + flt(args.get("total_number_of_depreciations"), 2) + * flt(args.get("frequency_of_depreciation")) ) / 12 ) @@ -1146,9 +1142,7 @@ def update_maintenance_status(): asset = frappe.get_doc("Asset", asset.name) if frappe.db.exists("Asset Repair", {"asset_name": asset.name, "repair_status": "Pending"}): asset.set_status("Out of Order") - elif frappe.db.exists( - "Asset Maintenance Task", {"parent": asset.name, "next_due_date": today()} - ): + elif frappe.db.exists("Asset Maintenance Task", {"parent": asset.name, "next_due_date": today()}): asset.set_status("In Maintenance") else: asset.set_status() @@ -1232,9 +1226,7 @@ def create_asset_capitalization(asset): @frappe.whitelist() def create_asset_value_adjustment(asset, asset_category, company): asset_value_adjustment = frappe.new_doc("Asset Value Adjustment") - asset_value_adjustment.update( - {"asset": asset, "company": company, "asset_category": asset_category} - ) + asset_value_adjustment.update({"asset": asset, "company": company, "asset_category": asset_category}) return asset_value_adjustment @@ -1291,18 +1283,14 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non ) if not asset and not account: - account = get_asset_category_account( - account_name, asset_category=asset_category, company=company - ) + account = get_asset_category_account(account_name, asset_category=asset_category, company=company) if not account: account = frappe.get_cached_value("Company", company, account_name) if not account: if not asset_category: - frappe.throw( - _("Set {0} in company {1}").format(account_name.replace("_", " ").title(), company) - ) + frappe.throw(_("Set {0} in company {1}").format(account_name.replace("_", " ").title(), company)) else: frappe.throw( _("Set {0} in asset category {1} or company {2}").format( @@ -1331,7 +1319,7 @@ def make_journal_entry(asset_name): je.voucher_type = "Depreciation Entry" je.naming_series = depreciation_series je.company = asset.company - je.remark = "Depreciation Entry against asset {0}".format(asset_name) + je.remark = f"Depreciation Entry against asset {asset_name}" je.append( "accounts", @@ -1433,9 +1421,7 @@ def get_depreciation_amount( ) -def get_straight_line_or_manual_depr_amount( - asset, row, schedule_idx, number_of_pending_depreciations -): +def get_straight_line_or_manual_depr_amount(asset, row, schedule_idx, number_of_pending_depreciations): if row.shift_based: return get_shift_depr_amount(asset, row, schedule_idx) @@ -1487,7 +1473,9 @@ def get_straight_line_or_manual_depr_amount( ) from_date = add_days( get_last_day( - add_months(row.depreciation_start_date, (schedule_idx - 1) * row.frequency_of_depreciation) + add_months( + row.depreciation_start_date, (schedule_idx - 1) * row.frequency_of_depreciation + ) ), 1, ) @@ -1500,7 +1488,6 @@ def get_straight_line_or_manual_depr_amount( # if the Depreciation Schedule is being prepared for the first time else: if row.daily_prorata_based: - amount = ( flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation) @@ -1516,7 +1503,10 @@ def get_straight_line_or_manual_depr_amount( ) ), add_days( - get_last_day(add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation)), 1 + get_last_day( + add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation) + ), + 1, ), ) + 1 @@ -1528,7 +1518,9 @@ def get_straight_line_or_manual_depr_amount( ) from_date = add_days( get_last_day( - add_months(row.depreciation_start_date, (schedule_idx - 1) * row.frequency_of_depreciation) + add_months( + row.depreciation_start_date, (schedule_idx - 1) * row.frequency_of_depreciation + ) ), 1, ) @@ -1688,9 +1680,7 @@ def update_existing_asset(asset, remaining_qty): processed_finance_books.append(int(term.finance_book_id)) depreciation_amount = flt((term.depreciation_amount * remaining_qty) / asset.asset_quantity) - frappe.db.set_value( - "Depreciation Schedule", term.name, "depreciation_amount", depreciation_amount - ) + frappe.db.set_value("Depreciation Schedule", term.name, "depreciation_amount", depreciation_amount) accumulated_depreciation += depreciation_amount frappe.db.set_value( "Depreciation Schedule", term.name, "accumulated_depreciation_amount", accumulated_depreciation diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 7953ed2fe2b9..f7417cce76cb 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -57,7 +57,10 @@ def post_depreciation_entries(date=None): ) not in credit_and_debit_accounts_for_asset_category_and_company: credit_and_debit_accounts_for_asset_category_and_company.update( { - (asset_category, asset_company): get_credit_and_debit_accounts_for_asset_category_and_company( + ( + asset_category, + asset_company, + ): get_credit_and_debit_accounts_for_asset_category_and_company( asset_category, asset_company ), } @@ -120,9 +123,7 @@ def get_acc_frozen_upto(): if not acc_frozen_upto: return - frozen_accounts_modifier = frappe.db.get_single_value( - "Accounts Settings", "frozen_accounts_modifier" - ) + frozen_accounts_modifier = frappe.db.get_single_value("Accounts Settings", "frozen_accounts_modifier") if frozen_accounts_modifier not in frappe.get_roles() or frappe.session.user == "Administrator": return getdate(acc_frozen_upto) @@ -245,9 +246,7 @@ def _make_journal_entry_for_depreciation( je.posting_date = depr_schedule.schedule_date je.company = asset.company je.finance_book = depr_schedule.finance_book - je.remark = "Depreciation Entry against {0} worth {1}".format( - asset.name, depr_schedule.depreciation_amount - ) + je.remark = f"Depreciation Entry against {asset.name} worth {depr_schedule.depreciation_amount}" credit_entry = { "account": credit_account, @@ -329,11 +328,7 @@ def get_depreciation_accounts(asset_category, company): if not depreciation_expense_account: depreciation_expense_account = accounts[1] - if ( - not fixed_asset_account - or not accumulated_depreciation_account - or not depreciation_expense_account - ): + if not fixed_asset_account or not accumulated_depreciation_account or not depreciation_expense_account: frappe.throw( _("Please set Depreciation related Accounts in Asset Category {0} or Company {1}").format( asset_category, company @@ -411,25 +406,21 @@ def scrap_asset(asset_name): if asset.docstatus != 1: frappe.throw(_("Asset {0} must be submitted").format(asset.name)) elif asset.status in ("Cancelled", "Sold", "Scrapped", "Capitalized", "Decapitalized"): - frappe.throw( - _("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status) - ) + frappe.throw(_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status)) date = today() depreciate_asset(asset, date) asset.reload() - depreciation_series = frappe.get_cached_value( - "Company", asset.company, "series_for_depreciation_entry" - ) + depreciation_series = frappe.get_cached_value("Company", asset.company, "series_for_depreciation_entry") je = frappe.new_doc("Journal Entry") je.voucher_type = "Journal Entry" je.naming_series = depreciation_series je.posting_date = date je.company = asset.company - je.remark = "Scrap Entry for asset {0}".format(asset_name) + je.remark = f"Scrap Entry for asset {asset_name}" for entry in get_gl_entries_on_asset_disposal(asset, date): entry.update({"reference_type": "Asset", "reference_name": asset_name}) @@ -523,7 +514,6 @@ def reverse_depreciation_entry_made_after_disposal(asset, date): if not disposal_was_made_on_original_schedule_date( asset, schedule, row, date ) or disposal_happens_in_the_future(date): - reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) reverse_journal_entry.posting_date = nowdate() @@ -714,7 +704,6 @@ def get_asset_details(asset, finance_book=None): def get_profit_gl_entries( asset, profit_amount, gl_entries, disposal_account, depreciation_cost_center, date=None ): - if not date: date = getdate() @@ -740,9 +729,7 @@ def get_disposal_account_and_cost_center(company): ) if not disposal_account: - frappe.throw( - _("Please set 'Gain/Loss Account on Asset Disposal' in Company {0}").format(company) - ) + frappe.throw(_("Please set 'Gain/Loss Account on Asset Disposal' in Company {0}").format(company)) if not depreciation_cost_center: frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company)) @@ -755,7 +742,7 @@ def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_ if asset_doc.available_for_use_date > getdate(disposal_date): frappe.throw( - "Disposal date {0} cannot be before available for use date {1} of the asset.".format( + "Disposal date {} cannot be before available for use date {} of the asset.".format( disposal_date, asset_doc.available_for_use_date ) ) @@ -772,9 +759,7 @@ def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_ finance_book_id = fb.idx break - asset_schedules = [ - sch for sch in asset_doc.schedules if cint(sch.finance_book_id) == finance_book_id - ] + asset_schedules = [sch for sch in asset_doc.schedules if cint(sch.finance_book_id) == finance_book_id] accumulated_depr_amount = asset_schedules[-1].accumulated_depreciation_amount return flt( diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index ea5b95aaf02e..00a53aa80d27 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -102,9 +102,7 @@ def test_validate_item(self): self.assertRaises(frappe.ValidationError, asset.save) def test_purchase_asset(self): - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name") asset = frappe.get_doc("Asset", asset_name) @@ -209,7 +207,7 @@ def test_scrap_asset(self): asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation, asset.precision("gross_purchase_amount"), ) - self.assertEquals(accumulated_depr_amount, 18000.0) + self.assertEqual(accumulated_depr_amount, 18000.0) scrap_asset(asset.name) asset.load_from_db() @@ -226,7 +224,7 @@ def test_scrap_asset(self): original_schedule_date=get_last_day(nowdate()), ) pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) - self.assertEquals( + self.assertEqual( accumulated_depr_amount, flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")), ) @@ -263,7 +261,7 @@ def test_scrap_asset(self): ) this_month_depr_amount = 9000.0 if is_last_day_of_the_month(date) else 0 - self.assertEquals(accumulated_depr_amount, 18000.0 + this_month_depr_amount) + self.assertEqual(accumulated_depr_amount, 18000.0 + this_month_depr_amount) def test_gle_made_by_asset_sale(self): date = nowdate() @@ -467,9 +465,7 @@ def test_asset_splitting(self): self.assertEqual(jv.accounts[3].reference_name, new_asset.name) def test_expense_head(self): - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=2, rate=200000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=2, rate=200000.0, location="Test Location") doc = make_invoice(pr.name) self.assertEqual("Asset Received But Not Billed - _TC", doc.items[0].expense_account) @@ -579,9 +575,7 @@ def test_asset_cwip_toggling_cases(self): self.assertFalse(gle) # case 1 -- PR with cwip disabled, Asset with cwip enabled - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location") frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1) frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc) asset = frappe.db.get_value("Asset", {"purchase_receipt": pr.name, "docstatus": 0}, "name") @@ -593,9 +587,7 @@ def test_asset_cwip_toggling_cases(self): self.assertFalse(gle) # case 2 -- PR with cwip enabled, Asset with cwip disabled - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location") frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0) asset = frappe.db.get_value("Asset", {"purchase_receipt": pr.name, "docstatus": 0}, "name") asset_doc = frappe.get_doc("Asset", asset) @@ -1207,8 +1199,7 @@ def test_depr_entry_posting_when_depr_expense_account_is_an_expense_account(self je = frappe.get_doc("Journal Entry", asset.schedules[0].journal_entry) accounting_entries = [ - {"account": entry.account, "debit": entry.debit, "credit": entry.credit} - for entry in je.accounts + {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts ] for entry in accounting_entries: @@ -1243,8 +1234,7 @@ def test_depr_entry_posting_when_depr_expense_account_is_an_income_account(self) je = frappe.get_doc("Journal Entry", asset.schedules[0].journal_entry) accounting_entries = [ - {"account": entry.account, "debit": entry.debit, "credit": entry.credit} - for entry in je.accounts + {"account": entry.account, "debit": entry.debit, "credit": entry.credit} for entry in je.accounts ] for entry in accounting_entries: @@ -1468,13 +1458,13 @@ def test_expected_value_change(self): asset.finance_books[0].expected_value_after_useful_life = 100 asset.save() asset.reload() - self.assertEquals(asset.finance_books[0].value_after_depreciation, 98000.0) + self.assertEqual(asset.finance_books[0].value_after_depreciation, 98000.0) # changing expected_value_after_useful_life shouldn't affect value_after_depreciation asset.finance_books[0].expected_value_after_useful_life = 200 asset.save() asset.reload() - self.assertEquals(asset.finance_books[0].value_after_depreciation, 98000.0) + self.assertEqual(asset.finance_books[0].value_after_depreciation, 98000.0) def test_asset_cost_center(self): asset = create_asset(is_existing_asset=1, do_not_save=1) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 76a660d6a9a3..bfeeb75a6423 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -86,7 +86,7 @@ def on_cancel(self): def on_trash(self): frappe.db.set_value("Asset", self.target_asset, "capitalized_in", None) - super(AssetCapitalization, self).on_trash() + super().on_trash() def cancel_target_asset(self): if self.entry_type == "Capitalization" and self.target_asset: @@ -179,7 +179,9 @@ def validate_target_asset(self): if target_asset.item_code != self.target_item_code: frappe.throw( - _("Asset {0} does not belong to Item {1}").format(self.target_asset, self.target_item_code) + _("Asset {0} does not belong to Item {1}").format( + self.target_asset, self.target_item_code + ) ) if target_asset.status in ("Scrapped", "Sold", "Capitalized", "Decapitalized"): @@ -194,7 +196,9 @@ def validate_target_asset(self): if target_asset.company != self.company: frappe.throw( - _("Target Asset {0} does not belong to company {1}").format(target_asset.name, self.company) + _("Target Asset {0} does not belong to company {1}").format( + target_asset.name, self.company + ) ) def validate_consumed_stock_item(self): @@ -224,13 +228,17 @@ def validate_consumed_asset_item(self): if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"): frappe.throw( - _("Row #{0}: Consumed Asset {1} cannot be {2}").format(d.idx, asset.name, asset.status) + _("Row #{0}: Consumed Asset {1} cannot be {2}").format( + d.idx, asset.name, asset.status + ) ) if asset.docstatus == 0: frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be Draft").format(d.idx, asset.name)) elif asset.docstatus == 2: - frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be cancelled").format(d.idx, asset.name)) + frappe.throw( + _("Row #{0}: Consumed Asset {1} cannot be cancelled").format(d.idx, asset.name) + ) if asset.company != self.company: frappe.throw( @@ -387,9 +395,7 @@ def make_gl_entries(self, gl_entries=None, from_repost=False): elif self.docstatus == 2: make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name) - def get_gl_entries( - self, warehouse_account=None, default_expense_account=None, default_cost_center=None - ): + def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): # Stock GL Entries gl_entries = [] @@ -403,15 +409,9 @@ def get_gl_entries( target_account = self.get_target_account() target_against = set() - self.get_gl_entries_for_consumed_stock_items( - gl_entries, target_account, target_against, precision - ) - self.get_gl_entries_for_consumed_asset_items( - gl_entries, target_account, target_against, precision - ) - self.get_gl_entries_for_consumed_service_items( - gl_entries, target_account, target_against, precision - ) + self.get_gl_entries_for_consumed_stock_items(gl_entries, target_account, target_against, precision) + self.get_gl_entries_for_consumed_asset_items(gl_entries, target_account, target_against, precision) + self.get_gl_entries_for_consumed_service_items(gl_entries, target_account, target_against, precision) self.get_gl_entries_for_target_item(gl_entries, target_against, precision) @@ -423,9 +423,7 @@ def get_target_account(self): else: return self.warehouse_account[self.target_warehouse]["account"] - def get_gl_entries_for_consumed_stock_items( - self, gl_entries, target_account, target_against, precision - ): + def get_gl_entries_for_consumed_stock_items(self, gl_entries, target_account, target_against, precision): # Consumed Stock Items for item_row in self.stock_items: sle_list = self.sle_map.get(item_row.name) @@ -454,9 +452,7 @@ def get_gl_entries_for_consumed_stock_items( ) ) - def get_gl_entries_for_consumed_asset_items( - self, gl_entries, target_account, target_against, precision - ): + def get_gl_entries_for_consumed_asset_items(self, gl_entries, target_account, target_against, precision): # Consumed Assets for item in self.asset_items: asset = frappe.get_doc("Asset", item.asset) @@ -572,9 +568,9 @@ def create_target_asset(self): ) frappe.msgprint( - _( - "Asset {0} has been created. Please set the depreciation details if any and submit it." - ).format(get_link_to_form("Asset", asset_doc.name)) + _("Asset {0} has been created. Please set the depreciation details if any and submit it.").format( + get_link_to_form("Asset", asset_doc.name) + ) ) def update_target_asset(self): @@ -594,9 +590,9 @@ def update_target_asset(self): asset_doc.save() frappe.msgprint( - _( - "Asset {0} has been updated. Please set the depreciation details if any and submit it." - ).format(get_link_to_form("Asset", asset_doc.name)) + _("Asset {0} has been updated. Please set the depreciation details if any and submit it.").format( + get_link_to_form("Asset", asset_doc.name) + ) ) def restore_consumed_asset_items(self): @@ -709,9 +705,7 @@ def get_consumed_stock_item_details(args): item_defaults = get_item_defaults(item.name, args.company) item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - out.cost_center = get_default_cost_center( - args, item_defaults, item_group_defaults, brand_defaults - ) + out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults) if args.item_code and out.warehouse: incoming_rate_args = frappe._dict( @@ -797,9 +791,7 @@ def get_consumed_asset_details(args): item_defaults = get_item_defaults(item.name, args.company) item_group_defaults = get_item_group_defaults(item.name, args.company) brand_defaults = get_brand_defaults(item.name, args.company) - out.cost_center = get_default_cost_center( - args, item_defaults, item_group_defaults, brand_defaults - ) + out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults) return out @@ -826,9 +818,7 @@ def get_service_item_details(args): out.expense_account = get_default_expense_account( args, item_defaults, item_group_defaults, brand_defaults ) - out.cost_center = get_default_cost_center( - args, item_defaults, item_group_defaults, brand_defaults - ) + out.cost_center = get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults) return out diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index 59b65ec3fd02..128e2a7fe8b3 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -346,9 +346,7 @@ def test_decapitalization_with_depreciation(self): consumed_depreciation_schedule = [ d for d in consumed_asset.schedules if getdate(d.schedule_date) == getdate(capitalization_date) ] - self.assertTrue( - consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry - ) + self.assertTrue(consumed_depreciation_schedule and consumed_depreciation_schedule[0].journal_entry) self.assertEqual( consumed_depreciation_schedule[0].depreciation_amount, depreciation_before_disposal_amount ) @@ -371,15 +369,9 @@ def test_decapitalization_with_depreciation(self): def create_asset_capitalization_data(): - create_item( - "Capitalization Target Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0 - ) - create_item( - "Capitalization Source Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0 - ) - create_item( - "Capitalization Source Service Item", is_stock_item=0, is_fixed_asset=0, is_purchase_item=0 - ) + create_item("Capitalization Target Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0) + create_item("Capitalization Source Stock Item", is_stock_item=1, is_fixed_asset=0, is_purchase_item=0) + create_item("Capitalization Source Service Item", is_stock_item=0, is_fixed_asset=0, is_purchase_item=0) def create_asset_capitalization(**args): diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py index 2a204e11477c..1beb423ba258 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.py +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -38,7 +38,9 @@ def validate_account_currency(self): account_currency = frappe.get_value("Account", d.get(type_of_account), "account_currency") if account_currency != company_currency: invalid_accounts.append( - frappe._dict({"type": type_of_account, "idx": d.idx, "account": d.get(type_of_account)}) + frappe._dict( + {"type": type_of_account, "idx": d.idx, "account": d.get(type_of_account)} + ) ) for d in invalid_accounts: diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py index 2c9265657689..516e27e00fa2 100644 --- a/erpnext/assets/doctype/asset_category/test_asset_category.py +++ b/erpnext/assets/doctype/asset_category/test_asset_category.py @@ -31,9 +31,7 @@ def test_mandatory_fields(self): pass def test_cwip_accounting(self): - company_cwip_acc = frappe.db.get_value( - "Company", "_Test Company", "capital_work_in_progress_account" - ) + frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account") frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "") asset_category = frappe.new_doc("Asset Category") diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py index 5c40072086ea..7762e63d7797 100644 --- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py @@ -70,9 +70,7 @@ def calculate_next_due_date( if not start_date and not last_completion_date: start_date = frappe.utils.now() - if last_completion_date and ( - (start_date and last_completion_date > start_date) or not start_date - ): + if last_completion_date and ((start_date and last_completion_date > start_date) or not start_date): start_date = last_completion_date if periodicity == "Daily": next_due_date = add_days(start_date, 1) diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py index e40a5519eb2f..dcc2f4d32e6f 100644 --- a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py +++ b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py @@ -17,9 +17,7 @@ def setUp(self): create_maintenance_team() def test_create_asset_maintenance(self): - pr = make_purchase_receipt( - item_code="Photocopier", qty=1, rate=100000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Photocopier", qty=1, rate=100000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name") asset_doc = frappe.get_doc("Asset", asset_name) @@ -130,8 +128,7 @@ def create_maintenance_team(): def get_maintenance_team(user_list): return [ - {"team_member": user, "full_name": user, "maintenance_role": "Technician"} - for user in user_list[1:] + {"team_member": user, "full_name": user, "maintenance_role": "Technician"} for user in user_list[1:] ] diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index b85f7194f987..db9cb02a61e1 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -32,7 +32,9 @@ def validate_location(self): if d.source_location: if current_location != d.source_location: frappe.throw( - _("Asset {0} does not belongs to the location {1}").format(d.asset, d.source_location) + _("Asset {0} does not belongs to the location {1}").format( + d.asset, d.source_location + ) ) else: d.source_location = current_location @@ -57,19 +59,25 @@ def validate_location(self): title=_("Incorrect Movement Purpose"), ) if not d.target_location: - frappe.throw(_("Target Location is required while transferring Asset {0}").format(d.asset)) + frappe.throw( + _("Target Location is required while transferring Asset {0}").format(d.asset) + ) if d.source_location == d.target_location: frappe.throw(_("Source and Target Location cannot be same")) if self.purpose == "Receipt": if not (d.source_location) and not (d.target_location or d.to_employee): frappe.throw( - _("Target Location or To Employee is required while receiving Asset {0}").format(d.asset) + _("Target Location or To Employee is required while receiving Asset {0}").format( + d.asset + ) ) elif d.source_location: if d.from_employee and not d.target_location: frappe.throw( - _("Target Location is required while receiving Asset {0} from an employee").format(d.asset) + _( + "Target Location is required while receiving Asset {0} from an employee" + ).format(d.asset) ) elif d.to_employee and d.target_location: frappe.throw( @@ -109,19 +117,17 @@ def set_latest_location_and_custodian_in_asset(self): # latest entry corresponds to current document's location, employee when transaction date > previous dates # In case of cancellation it corresponds to previous latest document's location, employee latest_movement_entry = frappe.db.sql( - """ + f""" SELECT asm_item.target_location, asm_item.to_employee FROM `tabAsset Movement Item` asm_item, `tabAsset Movement` asm WHERE asm_item.parent=asm.name and asm_item.asset=%(asset)s and asm.company=%(company)s and - asm.docstatus=1 and {0} + asm.docstatus=1 and {cond} ORDER BY asm.transaction_date desc limit 1 - """.format( - cond - ), + """, args, ) if latest_movement_entry: diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.py b/erpnext/assets/doctype/asset_movement/test_asset_movement.py index 27e7e557f196..52590d2ba866 100644 --- a/erpnext/assets/doctype/asset_movement/test_asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.py @@ -20,9 +20,7 @@ def setUp(self): make_location() def test_movement(self): - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name") asset = frappe.get_doc("Asset", asset_name) @@ -51,7 +49,11 @@ def test_movement(self): purpose="Transfer", company=asset.company, assets=[ - {"asset": asset.name, "source_location": "Test Location", "target_location": "Test Location 2"} + { + "asset": asset.name, + "source_location": "Test Location", + "target_location": "Test Location 2", + } ], reference_doctype="Purchase Receipt", reference_name=pr.name, @@ -62,7 +64,11 @@ def test_movement(self): purpose="Transfer", company=asset.company, assets=[ - {"asset": asset.name, "source_location": "Test Location 2", "target_location": "Test Location"} + { + "asset": asset.name, + "source_location": "Test Location 2", + "target_location": "Test Location", + } ], reference_doctype="Purchase Receipt", reference_name=pr.name, @@ -97,9 +103,7 @@ def test_movement(self): self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location") def test_last_movement_cancellation(self): - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name") asset = frappe.get_doc("Asset", asset_name) @@ -129,7 +133,11 @@ def test_last_movement_cancellation(self): purpose="Transfer", company=asset.company, assets=[ - {"asset": asset.name, "source_location": "Test Location", "target_location": "Test Location 2"} + { + "asset": asset.name, + "source_location": "Test Location", + "target_location": "Test Location 2", + } ], reference_doctype="Purchase Receipt", reference_name=pr.name, @@ -167,6 +175,4 @@ def create_asset_movement(**args): def make_location(): for location in ["Pune", "Mumbai", "Nagpur"]: if not frappe.db.exists("Location", location): - frappe.get_doc({"doctype": "Location", "location_name": location}).insert( - ignore_permissions=True - ) + frappe.get_doc({"doctype": "Location", "location_name": location}).insert(ignore_permissions=True) diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index b348e13ca83d..da933c960578 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -98,9 +98,7 @@ def check_repair_status(self): def check_for_stock_items_and_warehouse(self): if not self.get("stock_items"): - frappe.throw( - _("Please enter Stock Items consumed during the Repair."), title=_("Missing Items") - ) + frappe.throw(_("Please enter Stock Items consumed during the Repair."), title=_("Missing Items")) if not self.warehouse: frappe.throw( _("Please enter Warehouse from which Stock Items consumed during the Repair were taken."), @@ -173,9 +171,7 @@ def make_gl_entries(self, cancel=False): def get_gl_entries(self): gl_entries = [] - fixed_asset_account = get_asset_account( - "fixed_asset_account", asset=self.asset, company=self.company - ) + fixed_asset_account = get_asset_account("fixed_asset_account", asset=self.asset, company=self.company) self.get_gl_entries_for_repair_cost(gl_entries, fixed_asset_account) self.get_gl_entries_for_consumed_items(gl_entries, fixed_asset_account) diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py index 3adb35169089..274c17681797 100644 --- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py @@ -193,9 +193,7 @@ def test_gl_entries_with_perpetual_inventory(self): self.assertEqual(expected_values[d.account][1], d.credit) def test_gl_entries_with_periodical_inventory(self): - frappe.db.set_value( - "Company", "_Test Company", "default_expense_account", "Cost of Goods Sold - _TC" - ) + frappe.db.set_value("Company", "_Test Company", "default_expense_account", "Cost of Goods Sold - _TC") asset_repair = create_asset_repair( capitalize_repair_cost=1, stock_consumption=1, @@ -275,9 +273,7 @@ def create_asset_repair(**args): if args.stock_consumption: asset_repair.stock_consumption = 1 - asset_repair.warehouse = args.warehouse or create_warehouse( - "Test Warehouse", company=asset.company - ) + asset_repair.warehouse = args.warehouse or create_warehouse("Test Warehouse", company=asset.company) asset_repair.append( "stock_items", { 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 d9797b0c24c4..e255c827f14d 100644 --- a/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py +++ b/erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.py @@ -108,9 +108,7 @@ def update_depr_schedule(self): 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 - } + 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_doc.schedules @@ -139,9 +137,9 @@ def allocate_shift_diff_in_depr_schedule(self): ) diff = 0 except Exception: - frappe.throw(_("Could not auto update shifts. Shift with shift factor {0} needed.")).format( - shift_factor - diff - ) + 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) @@ -202,9 +200,9 @@ def allocate_shift_diff_in_depr_schedule(self): ) diff = 0 except Exception: - frappe.throw(_("Could not auto update shifts. Shift with shift factor {0} needed.")).format( - shift_factor + diff - ) + frappe.throw( + _("Could not auto update shifts. Shift with shift factor {0} needed.") + ).format(shift_factor + diff) def update_asset_schedule(self): self.asset_doc.flags.shift_allocation = True @@ -239,9 +237,7 @@ def find_subsets_with_sum(numbers, k, target_sum, current_subset, result): return # Include the current number in the subset - find_subsets_with_sum( - numbers, k - 1, target_sum - numbers[0], current_subset + [numbers[0]], result - ) + 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_factor/asset_shift_factor.py b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py index 4c275ce092cc..d9bc2283f5b8 100644 --- a/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py +++ b/erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.py @@ -12,9 +12,7 @@ def validate(self): def validate_default(self): if self.default: - existing_default_shift_factor = frappe.db.get_value( - "Asset Shift Factor", {"default": 1}, "name" - ) + existing_default_shift_factor = frappe.db.get_value("Asset Shift Factor", {"default": 1}, "name") if existing_default_shift_factor: frappe.throw( 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 29e7a9bdfd6c..fca9bc33365e 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -61,7 +61,7 @@ def make_depreciation_entry(self): je.naming_series = depreciation_series je.posting_date = self.date je.company = self.company - je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount) + je.remark = f"Depreciation Entry against {self.asset} worth {self.difference_amount}" je.finance_book = self.finance_book credit_entry = { 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 8fdcd0c14df3..7661e70fd179 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 @@ -20,9 +20,7 @@ def setUp(self): ) def test_current_asset_value(self): - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name") asset_doc = frappe.get_doc("Asset", asset_name) @@ -49,9 +47,7 @@ def test_current_asset_value(self): self.assertEqual(current_value, 100000.0) def test_asset_depreciation_value_adjustment(self): - pr = make_purchase_receipt( - item_code="Macbook Pro", qty=1, rate=120000.0, location="Test Location" - ) + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=120000.0, location="Test Location") asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name") asset_doc = frappe.get_doc("Asset", asset_name) diff --git a/erpnext/assets/doctype/location/location.py b/erpnext/assets/doctype/location/location.py index 5bff3dd8c99c..a4376a685d08 100644 --- a/erpnext/assets/doctype/location/location.py +++ b/erpnext/assets/doctype/location/location.py @@ -195,17 +195,15 @@ def get_children(doctype, parent=None, location=None, is_root=False): parent = "" return frappe.db.sql( - """ + f""" select name as value, is_group as expandable from `tabLocation` comp where - ifnull(parent_location, "")={parent} - """.format( - parent=frappe.db.escape(parent) - ), + ifnull(parent_location, "")={frappe.db.escape(parent)} + """, as_dict=1, ) diff --git a/erpnext/assets/doctype/location/test_location.py b/erpnext/assets/doctype/location/test_location.py index b8563cb0a290..3b5af61fd444 100644 --- a/erpnext/assets/doctype/location/test_location.py +++ b/erpnext/assets/doctype/location/test_location.py @@ -31,9 +31,7 @@ def runTest(self): ordered_test_location_features = sorted( test_location_features, key=lambda x: x["properties"]["feature_of"] ) - ordered_formatted_locations = sorted( - formatted_locations, key=lambda x: x["properties"]["feature_of"] - ) + ordered_formatted_locations = sorted(formatted_locations, key=lambda x: x["properties"]["feature_of"]) self.assertEqual(ordered_formatted_locations, ordered_test_location_features) self.assertEqual(area, test_location.get("area")) diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index 4150494e22fc..4ff04c80434a 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -122,11 +122,7 @@ def get_data(filters): assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields) for asset in assets_record: - if ( - assets_linked_to_fb - and asset.calculate_depreciation - and asset.asset_id not in assets_linked_to_fb - ): + if assets_linked_to_fb and asset.calculate_depreciation and asset.asset_id not in assets_linked_to_fb: continue asset_value = get_asset_value_after_depreciation( @@ -241,9 +237,7 @@ def get_assets_linked_to_fb(filters): def get_asset_depreciation_amount_map(filters, finance_book): - start_date = ( - filters.from_date if filters.filter_based_on == "Date Range" else filters.year_start_date - ) + start_date = filters.from_date if filters.filter_based_on == "Date Range" else filters.year_start_date end_date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date asset = frappe.qb.DocType("Asset") @@ -260,9 +254,7 @@ def get_asset_depreciation_amount_map(filters, finance_book): .join(company) .on(company.name == asset.company) .select(asset.name.as_("asset"), Sum(gle.debit).as_("depreciation_amount")) - .where( - gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account) - ) + .where(gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account)) .where(gle.debit != 0) .where(gle.is_cancelled == 0) .where(company.name == filters.company) @@ -281,9 +273,7 @@ def get_asset_depreciation_amount_map(filters, finance_book): else: query = query.where(asset.status.isin(["Sold", "Scrapped", "Capitalized", "Decapitalized"])) if finance_book: - query = query.where( - (gle.finance_book.isin([cstr(finance_book), ""])) | (gle.finance_book.isnull()) - ) + query = query.where((gle.finance_book.isin([cstr(finance_book), ""])) | (gle.finance_book.isnull())) else: query = query.where((gle.finance_book.isin([""])) | (gle.finance_book.isnull())) if filters.filter_based_on in ("Date Range", "Fiscal Year"): diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 9d4846056eaf..58d7440211ce 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -34,7 +34,7 @@ class PurchaseOrder(BuyingController): def __init__(self, *args, **kwargs): - super(PurchaseOrder, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "source_dt": "Purchase Order Item", @@ -54,7 +54,7 @@ def onload(self): self.set_onload("supplier_tds", supplier_tds) def validate(self): - super(PurchaseOrder, self).validate() + super().validate() self.set_status() @@ -90,7 +90,7 @@ def validate_with_previous_doc(self): if self.is_subcontracted: mri_compare_fields = [["project", "="]] - super(PurchaseOrder, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Supplier Quotation": { "ref_dn_field": "supplier_quotation", @@ -185,9 +185,7 @@ def validate_minimum_order_qty(self): itemwise_min_order_qty = frappe._dict( frappe.db.sql( """select name, min_order_qty - from tabItem where name in ({0})""".format( - ", ".join(["%s"] * len(items)) - ), + from tabItem where name in ({})""".format(", ".join(["%s"] * len(items))), items, ) ) @@ -233,7 +231,9 @@ def validate_fg_item_for_subcontracting(self): ) elif not frappe.get_value("Item", item.fg_item, "default_bom"): frappe.throw( - _("Row #{0}: Default BOM not found for FG Item {1}").format(item.idx, item.fg_item) + _("Row #{0}: Default BOM not found for FG Item {1}").format( + item.idx, item.fg_item + ) ) if not item.fg_item_qty: frappe.throw(_("Row #{0}: Finished Good Item Qty can not be zero").format(item.idx)) @@ -267,8 +267,9 @@ def get_last_purchase_rate(self): d.rate = d.base_rate / conversion_rate d.last_purchase_rate = d.rate else: - - item_last_purchase_rate = frappe.get_cached_value("Item", d.item_code, "last_purchase_rate") + item_last_purchase_rate = frappe.get_cached_value( + "Item", d.item_code, "last_purchase_rate" + ) if item_last_purchase_rate: d.base_price_list_rate = ( d.base_rate @@ -303,7 +304,7 @@ def update_ordered_qty(self, po_item_rows=None): def check_modified_date(self): mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s", self.name) - date_diff = frappe.db.sql("select '%s' - '%s' " % (mod_db[0][0], cstr(self.modified))) + date_diff = frappe.db.sql(f"select '{mod_db[0][0]}' - '{cstr(self.modified)}' ") if date_diff and date_diff[0][0]: msgprint( @@ -322,7 +323,7 @@ def update_status(self, status): clear_doctype_notifications(self) def on_submit(self): - super(PurchaseOrder, self).on_submit() + super().on_submit() if self.is_against_so(): self.update_status_updater() @@ -345,7 +346,7 @@ def on_submit(self): def on_cancel(self): self.ignore_linked_doctypes = ("GL Entry", "Payment Ledger Entry") - super(PurchaseOrder, self).on_cancel() + super().on_cancel() if self.is_against_so(): self.update_status_updater() @@ -485,7 +486,9 @@ def close_or_unclose_purchase_orders(names, status): po = frappe.get_doc("Purchase Order", name) if po.docstatus == 1: if status == "Closed": - if po.status not in ("Cancelled", "Closed") and (po.per_received < 100 or po.per_billed < 100): + if po.status not in ("Cancelled", "Closed") and ( + po.per_received < 100 or po.per_billed < 100 + ): po.update_status(status) else: if po.status == "Closed": @@ -661,7 +664,6 @@ def make_subcontracting_order(source_name, target_doc=None): def get_mapped_subcontracting_order(source_name, target_doc=None): - if target_doc and isinstance(target_doc, str): target_doc = json.loads(target_doc) for key in ["service_items", "items", "supplied_items"]: diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 3a498ee271b4..a95be2969f54 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -11,11 +11,13 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.party import get_due_date_from_template -from erpnext.buying.doctype.purchase_order.purchase_order import make_inter_company_sales_order +from erpnext.buying.doctype.purchase_order.purchase_order import ( + make_inter_company_sales_order, + make_purchase_receipt, +) 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 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 @@ -190,7 +192,7 @@ def test_update_child_adding_new_item(self): po.items[0].qty = 4 po.save() po.submit() - pr = make_pr_against_po(po.name, 2) + make_pr_against_po(po.name, 2) po.load_from_db() existing_ordered_qty = get_ordered_qty() @@ -220,7 +222,7 @@ def test_update_child_removing_item(self): po.items[0].qty = 4 po.save() po.submit() - pr = make_pr_against_po(po.name, 2) + make_pr_against_po(po.name, 2) po.reload() first_item_of_po = po.get("items")[0] @@ -461,9 +463,7 @@ def test_return_against_purchase_order(self): make_purchase_receipt as make_purchase_receipt_return, ) - pr1 = make_purchase_receipt_return( - is_return=1, return_against=pr.name, qty=-3, do_not_submit=True - ) + pr1 = make_purchase_receipt_return(is_return=1, return_against=pr.name, qty=-3, do_not_submit=True) pr1.items[0].purchase_order = po.name pr1.items[0].purchase_order_item = po.items[0].name pr1.submit() @@ -544,9 +544,7 @@ def test_make_purchase_invoice_with_terms(self): self.assertEqual(po.payment_schedule[0].payment_amount, 2500.0) self.assertEqual(getdate(po.payment_schedule[0].due_date), getdate(po.transaction_date)) self.assertEqual(po.payment_schedule[1].payment_amount, 2500.0) - self.assertEqual( - getdate(po.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30) - ) + self.assertEqual(getdate(po.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30)) pi = make_pi_from_po(po.name) pi.save() @@ -556,9 +554,7 @@ def test_make_purchase_invoice_with_terms(self): self.assertEqual(pi.payment_schedule[0].payment_amount, 2500.0) self.assertEqual(getdate(pi.payment_schedule[0].due_date), getdate(po.transaction_date)) self.assertEqual(pi.payment_schedule[1].payment_amount, 2500.0) - self.assertEqual( - getdate(pi.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30) - ) + self.assertEqual(getdate(pi.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30)) automatically_fetch_payment_terms(enable=0) def test_warehouse_company_validation(self): @@ -702,9 +698,9 @@ def test_po_for_blocked_supplier_payments_past_date(self): raise Exception def test_default_payment_terms(self): - due_date = get_due_date_from_template( - "_Test Payment Term Template 1", "2023-02-03", None - ).strftime("%Y-%m-%d") + due_date = get_due_date_from_template("_Test Payment Term Template 1", "2023-02-03", None).strftime( + "%Y-%m-%d" + ) self.assertEqual(due_date, "2023-03-31") def test_terms_are_not_copied_if_automatically_fetch_payment_terms_is_unchecked(self): @@ -802,7 +798,7 @@ def test_po_optional_blanket_order(self): Second Purchase Order should not add on to Blanket Orders Ordered Quantity. """ - bo = make_blanket_order(blanket_order_type="Purchasing", quantity=10, rate=10) + make_blanket_order(blanket_order_type="Purchasing", quantity=10, rate=10) po = create_purchase_order(item_code="_Test Item", qty=5, against_blanket_order=1) po_doc = frappe.get_doc("Purchase Order", po.get("name")) @@ -1101,15 +1097,11 @@ def create_pr_against_po(po, received_qty=4): def get_ordered_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"): - return flt( - frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "ordered_qty") - ) + return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "ordered_qty")) def get_requested_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"): - return flt( - frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "indented_qty") - ) + return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "indented_qty")) test_dependencies = ["BOM", "Item Price"] 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 8226aa32c0e1..73882d39cec9 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -3,7 +3,6 @@ import json -from typing import Optional import frappe from frappe import _ @@ -27,7 +26,7 @@ def validate(self): self.validate_duplicate_supplier() self.validate_supplier_list() validate_for_items(self) - super(RequestforQuotation, self).set_qty_as_per_stock_uom() + super().set_qty_as_per_stock_uom() self.update_email_id() if self.docstatus < 1: @@ -253,7 +252,7 @@ def get_attachments(self): def update_rfq_supplier_status(self, sup_name=None): for supplier in self.suppliers: - if sup_name == None or supplier.supplier == sup_name: + if sup_name is None or supplier.supplier == sup_name: quote_status = _("Received") for item in self.items: sqi_count = frappe.db.sql( @@ -284,9 +283,7 @@ def send_supplier_emails(rfq_name): def check_portal_enabled(reference_doctype): - if not frappe.db.get_value( - "Portal Menu Item", {"reference_doctype": reference_doctype}, "enabled" - ): + if not frappe.db.get_value("Portal Menu Item", {"reference_doctype": reference_doctype}, "enabled"): frappe.throw( _( "The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings." @@ -415,9 +412,9 @@ def create_rfq_items(sq_doc, supplier, data): def get_pdf( name: str, supplier: str, - print_format: Optional[str] = None, - language: Optional[str] = None, - letterhead: Optional[str] = None, + print_format: str | None = None, + language: str | None = None, + letterhead: str | None = None, ): doc = frappe.get_doc("Request for Quotation", name) if supplier: @@ -492,9 +489,7 @@ def get_item_from_material_requests_based_on_supplier(source_name, target_doc=No @frappe.whitelist() def get_supplier_tag(): filters = {"document_type": "Supplier"} - tags = list( - set(tag.tag for tag in frappe.get_all("Tag Link", filters=filters, fields=["tag"]) if tag) - ) + tags = list(set(tag.tag for tag in frappe.get_all("Tag Link", filters=filters, fields=["tag"]) if tag)) return tags @@ -507,7 +502,7 @@ def get_rfq_containing_supplier(doctype, txt, searchfield, start, page_len, filt conditions += "and rfq.name like '%%" + txt + "%%' " if filters.get("transaction_date"): - conditions += "and rfq.transaction_date = '{0}'".format(filters.get("transaction_date")) + conditions += "and rfq.transaction_date = '{}'".format(filters.get("transaction_date")) rfq_data = frappe.db.sql( f""" diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py index 42fa1d923e16..da2a9d8a391a 100644 --- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py @@ -64,9 +64,7 @@ def test_make_supplier_quotation_with_special_characters(self): rfq = make_request_for_quotation(supplier_data=supplier_wt_appos) - sq = make_supplier_quotation_from_rfq( - rfq.name, for_supplier=supplier_wt_appos[0].get("supplier") - ) + sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=supplier_wt_appos[0].get("supplier")) sq.submit() frappe.form_dict.name = rfq.name @@ -97,9 +95,7 @@ def test_make_multi_uom_supplier_quotation(self): row = item.append("uoms", {"uom": "Kg", "conversion_factor": 2}) row.db_update() - rfq = make_request_for_quotation( - item_code="_Test Multi UOM RFQ Item", uom="Kg", conversion_factor=2 - ) + rfq = make_request_for_quotation(item_code="_Test Multi UOM RFQ Item", uom="Kg", conversion_factor=2) rfq.get("items")[0].rate = 100 rfq.supplier = rfq.suppliers[0].supplier diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index 91061c8fe8bc..2774f1aeffb9 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -11,9 +11,8 @@ ) from frappe.model.naming import set_name_by_naming_series, set_name_from_naming_options -from erpnext.accounts.party import ( # noqa +from erpnext.accounts.party import ( get_dashboard_info, - get_timeline_data, validate_party_accounts, ) from erpnext.utilities.transaction_base import TransactionBase @@ -154,6 +153,6 @@ def get_supplier_primary_contact(doctype, txt, searchfield, start, page_len, fil .where( (dynamic_link.link_name == supplier) & (dynamic_link.link_doctype == "Supplier") - & (contact.name.like("%{0}%".format(txt))) + & (contact.name.like(f"%{txt}%")) ) ).run(as_dict=False) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py index e27fbe8aaa23..492a73c3a859 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -15,7 +15,7 @@ class SupplierQuotation(BuyingController): def validate(self): - super(SupplierQuotation, self).validate() + super().validate() if not self.status: self.status = "Draft" @@ -41,7 +41,7 @@ def on_trash(self): pass def validate_with_previous_doc(self): - super(SupplierQuotation, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Material Request": { "ref_dn_field": "prevdoc_docname", diff --git a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py index 58da85129514..8b2026aec728 100644 --- a/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py +++ b/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py @@ -34,7 +34,11 @@ def validate_standings(self): for c2 in self.standings: if c1 != c2: if c1.max_grade > c2.min_grade and c1.min_grade < c2.max_grade: - throw(_("Overlap in scoring between {0} and {1}").format(c1.standing_name, c2.standing_name)) + throw( + _("Overlap in scoring between {0} and {1}").format( + c1.standing_name, c2.standing_name + ) + ) if c2.min_grade == score: score = c2.max_grade if score < 100: @@ -45,7 +49,6 @@ def validate_standings(self): ) def validate_criteria_weights(self): - weight = 0 for c in self.criteria: weight += c.weight @@ -164,7 +167,6 @@ def refresh_scorecards(): @frappe.whitelist() def make_all_scorecards(docname): - sc = frappe.get_doc("Supplier Scorecard", docname) supplier = frappe.get_doc("Supplier", sc.supplier) 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 ab7d4879c43e..7433ffff7930 100644 --- a/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py +++ b/erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.py @@ -29,8 +29,8 @@ def validate_formula(self): regex = r"\{(.*?)\}" mylist = re.finditer(regex, test_formula, re.MULTILINE | re.DOTALL) - for dummy1, match in enumerate(mylist): - for dummy2 in range(0, len(match.groups())): + for _dummy1, match in enumerate(mylist): + for _dummy2 in range(0, len(match.groups())): test_formula = test_formula.replace("{" + match.group(1) + "}", "0") try: @@ -64,8 +64,8 @@ def _get_variables(criteria): regex = r"\{(.*?)\}" mylist = re.finditer(regex, criteria.formula, re.MULTILINE | re.DOTALL) - for dummy1, match in enumerate(mylist): - for dummy2 in range(0, len(match.groups())): + for _dummy1, match in enumerate(mylist): + for _dummy2 in range(0, len(match.groups())): try: var = frappe.db.sql( """ @@ -80,6 +80,8 @@ def _get_variables(criteria): )[0] my_variables.append(var) except Exception: - frappe.throw(_("Unable to find variable:") + " " + str(match.group(1)), InvalidFormulaVariable) + frappe.throw( + _("Unable to find variable:") + " " + str(match.group(1)), InvalidFormulaVariable + ) return my_variables 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 a8b76db09312..c54c6aadd6ad 100644 --- a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py +++ b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py @@ -21,7 +21,6 @@ def validate(self): self.calculate_score() def validate_criteria_weights(self): - weight = 0 for c in self.criteria: weight += c.weight @@ -44,14 +43,17 @@ def calculate_criteria(self): crit.score = min( crit.max_score, max( - 0, frappe.safe_eval(self.get_eval_statement(crit.formula), None, {"max": max, "min": min}) + 0, + frappe.safe_eval( + self.get_eval_statement(crit.formula), None, {"max": max, "min": min} + ), ), ) except Exception: frappe.throw( - _("Could not solve criteria score function for {0}. Make sure the formula is valid.").format( - crit.criteria_name - ), + _( + "Could not solve criteria score function for {0}. Make sure the formula is valid." + ).format(crit.criteria_name), frappe.ValidationError, ) crit.score = 0 @@ -82,7 +84,7 @@ def get_eval_statement(self, formula): if var.value: if var.param_name in my_eval_statement: my_eval_statement = my_eval_statement.replace( - "{" + var.param_name + "}", "{:.2f}".format(var.value) + "{" + var.param_name + "}", f"{var.value:.2f}" ) else: if var.param_name in my_eval_statement: diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py index 9b53421319d9..ebceb7f655a5 100644 --- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py +++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py @@ -2,17 +2,8 @@ # For license information, please see license.txt -from datetime import datetime - -import frappe from frappe.tests.utils import FrappeTestCase -from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt -from erpnext.buying.report.procurement_tracker.procurement_tracker import execute -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 -from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse - class TestProcurementTracker(FrappeTestCase): pass diff --git a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py index b6e46302ffe8..b23c3f50b9a1 100644 --- a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py +++ b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py @@ -68,9 +68,7 @@ def get_data(filters): po.company, po_item.name, ) - .where( - (po_item.parent == po.name) & (po.status.notin(("Stopped", "Closed"))) & (po.docstatus == 1) - ) + .where((po_item.parent == po.name) & (po.status.notin(("Stopped", "Closed"))) & (po.docstatus == 1)) .groupby(po_item.name) .orderby(po.transaction_date) ) @@ -80,9 +78,7 @@ def get_data(filters): query = query.where(po[field] == filters.get(field)) if filters.get("from_date") and filters.get("to_date"): - query = query.where( - po.transaction_date.between(filters.get("from_date"), filters.get("to_date")) - ) + query = query.where(po.transaction_date.between(filters.get("from_date"), filters.get("to_date"))) if filters.get("status"): query = query.where(po.status.isin(filters.get("status"))) @@ -114,7 +110,7 @@ def prepare_data(data, filters): if filters.get("group_by_po"): po_name = row["purchase_order"] - if not po_name in purchase_order_map: + if po_name not in purchase_order_map: # create an entry row_copy = copy.deepcopy(row) purchase_order_map[po_name] = row_copy diff --git a/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py index 07187352eb70..55189a722a31 100644 --- a/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py +++ b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py @@ -57,9 +57,7 @@ def get_data(filters): "qty_to_receive" ), Sum(Coalesce(mr_item.received_qty, 0)).as_("received_qty"), - (Sum(Coalesce(mr_item.stock_qty, 0)) - Sum(Coalesce(mr_item.ordered_qty, 0))).as_( - "qty_to_order" - ), + (Sum(Coalesce(mr_item.stock_qty, 0)) - Sum(Coalesce(mr_item.ordered_qty, 0))).as_("qty_to_order"), mr_item.item_name, mr_item.description, mr.company, @@ -110,7 +108,7 @@ def prepare_data(data, filters): for row in data: # item wise map for charts - if not row["item_code"] in item_qty_map: + if row["item_code"] not in item_qty_map: item_qty_map[row["item_code"]] = { "qty": flt(row["stock_qty"], precision), "stock_qty": flt(row["stock_qty"], precision), @@ -127,7 +125,7 @@ def prepare_data(data, filters): if filters.get("group_by_mr"): # consolidated material request map for group by filter - if not row["material_request"] in material_request_map: + if row["material_request"] not in material_request_map: # create an entry with mr as key row_copy = copy.deepcopy(row) material_request_map[row["material_request"]] = row_copy diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py index 0213051aeb73..130cadaabc13 100644 --- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py +++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py @@ -112,7 +112,7 @@ def prepare_subcontracted_data(orders, supplied_items): def get_subcontracted_data(order_details, data): - for key, details in order_details.items(): + for _key, details in order_details.items(): res = details.order_item for index, row in enumerate(details.supplied_items): if index != 0: diff --git a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py index d13d9701f31e..d90be66af942 100644 --- a/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py +++ b/erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py @@ -62,7 +62,9 @@ def test_pending_and_received_qty(self): "from_date": frappe.utils.get_datetime( frappe.utils.add_to_date(sco.transaction_date, days=-10) ), - "to_date": frappe.utils.get_datetime(frappe.utils.add_to_date(sco.transaction_date, days=10)), + "to_date": frappe.utils.get_datetime( + frappe.utils.add_to_date(sco.transaction_date, days=10) + ), } ) ) diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py index 160295776b15..7b4ec5c2f390 100644 --- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py +++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py @@ -48,7 +48,9 @@ def test_pending_and_transferred_qty(self): "from_date": frappe.utils.get_datetime( frappe.utils.add_to_date(sco.transaction_date, days=-10) ), - "to_date": frappe.utils.get_datetime(frappe.utils.add_to_date(sco.transaction_date, days=10)), + "to_date": frappe.utils.get_datetime( + frappe.utils.add_to_date(sco.transaction_date, days=10) + ), } ) ) diff --git a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py index 01ff28d8103d..684cd3a0f9ee 100644 --- a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py +++ b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.py @@ -82,18 +82,14 @@ def prepare_data(supplier_quotation_data, filters): group_wise_map = defaultdict(list) supplier_qty_price_map = {} - group_by_field = ( - "supplier_name" if filters.get("group_by") == "Group by Supplier" else "item_code" - ) + group_by_field = "supplier_name" if filters.get("group_by") == "Group by Supplier" else "item_code" company_currency = frappe.db.get_default("currency") float_precision = cint(frappe.db.get_default("float_precision")) or 2 for data in supplier_quotation_data: group = data.get(group_by_field) # get item or supplier value for this row - supplier_currency = frappe.db.get_value( - "Supplier", data.get("supplier_name"), "default_currency" - ) + supplier_currency = frappe.db.get_value("Supplier", data.get("supplier_name"), "default_currency") if supplier_currency: exchange_rate = get_exchange_rate(supplier_currency, company_currency) @@ -126,7 +122,7 @@ def prepare_data(supplier_quotation_data, filters): # map for chart preparation of the form {'supplier1': {'qty': 'price'}} supplier = data.get("supplier_name") if filters.get("item_code"): - if not supplier in supplier_qty_price_map: + if supplier not in supplier_qty_price_map: supplier_qty_price_map[supplier] = {} supplier_qty_price_map[supplier][row["qty"]] = row["price"] @@ -169,7 +165,7 @@ def prepare_chart_data(suppliers, qty_list, supplier_qty_price_map): for supplier in suppliers: entry = supplier_qty_price_map[supplier] for qty in qty_list: - if not qty in data_points_map: + if qty not in data_points_map: data_points_map[qty] = [] if qty in entry: data_points_map[qty].append(entry[qty]) diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index e904af0dce3b..1d708b36980e 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -3,7 +3,6 @@ import json -from typing import Dict import frappe from frappe import _ @@ -87,7 +86,7 @@ def set_stock_levels(row) -> None: row.set(field, qty_data[field]) -def validate_item_and_get_basic_data(row) -> Dict: +def validate_item_and_get_basic_data(row) -> dict: item = frappe.db.get_values( "Item", filters={"name": row.item_code}, @@ -101,12 +100,7 @@ def validate_item_and_get_basic_data(row) -> Dict: def validate_stock_item_warehouse(row, item) -> None: - if ( - item.is_stock_item == 1 - and row.qty - and not row.warehouse - and not row.get("delivered_by_supplier") - ): + if item.is_stock_item == 1 and row.qty and not row.warehouse and not row.get("delivered_by_supplier"): frappe.throw( _("Row #{1}: Warehouse is mandatory for stock Item {0}").format( frappe.bold(row.item_code), row.idx @@ -118,9 +112,7 @@ def check_on_hold_or_closed_status(doctype, docname) -> None: status = frappe.db.get_value(doctype, docname, "status") if status in ("Closed", "On Hold"): - frappe.throw( - _("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError - ) + frappe.throw(_("{0} {1} status is {2}").format(doctype, docname, status), frappe.InvalidStatusError) @frappe.whitelist() diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 534bddcd6438..dd4a247e0a11 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -95,7 +95,7 @@ class InvalidQtyError(frappe.ValidationError): class AccountsController(TransactionBase): def __init__(self, *args, **kwargs): - super(AccountsController, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def get_print_settings(self): print_setting_fields = [] @@ -200,14 +200,13 @@ def validate(self): self.validate_return_against_account() if self.doctype in ["Purchase Invoice", "Sales Invoice"]: - if invalid_advances := [ - x for x in self.advances if not x.reference_type or not x.reference_name - ]: + if invalid_advances := [x for x in self.advances if not x.reference_type or not x.reference_name]: frappe.throw( _( "Rows: {0} in {1} section are Invalid. Reference Name should point to a valid Payment Entry or Journal Entry." ).format( - frappe.bold(comma_and([x.idx for x in invalid_advances])), frappe.bold(_("Advance Payments")) + frappe.bold(comma_and([x.idx for x in invalid_advances])), + frappe.bold(_("Advance Payments")), ) ) @@ -352,9 +351,7 @@ def on_trash(self): ) def validate_return_against_account(self): - if ( - self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against - ): + if self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against: cr_dr_account_field = "debit_to" if self.doctype == "Sales Invoice" else "credit_to" cr_dr_account_label = "Debit To" if self.doctype == "Sales Invoice" else "Credit To" cr_dr_account = self.get(cr_dr_account_field) @@ -387,11 +384,7 @@ def validate_deferred_income_expense_account(self): item.set(field_map.get(self.doctype), default_deferred_account) def validate_auto_repeat_subscription_dates(self): - if ( - self.get("from_date") - and self.get("to_date") - and getdate(self.from_date) > getdate(self.to_date) - ): + if self.get("from_date") and self.get("to_date") and getdate(self.from_date) > getdate(self.to_date): frappe.throw(_("To Date cannot be before From Date"), title=_("Invalid Auto Repeat Date")) def validate_deferred_start_and_end_date(self): @@ -399,11 +392,15 @@ def validate_deferred_start_and_end_date(self): if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"): if not (d.service_start_date and d.service_end_date): frappe.throw( - _("Row #{0}: Service Start and End Date is required for deferred accounting").format(d.idx) + _("Row #{0}: Service Start and End Date is required for deferred accounting").format( + d.idx + ) ) elif getdate(d.service_start_date) > getdate(d.service_end_date): frappe.throw( - _("Row #{0}: Service Start Date cannot be greater than Service End Date").format(d.idx) + _("Row #{0}: Service Start Date cannot be greater than Service End Date").format( + d.idx + ) ) elif getdate(self.posting_date) > getdate(d.service_end_date): frappe.throw( @@ -462,7 +459,9 @@ def calculate_paid_amount(self): if not self.cash_bank_account: # show message that the amount is not paid frappe.throw( - _("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified") + _( + "Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified" + ) ) if cint(self.is_return) and self.grand_total > self.paid_amount: @@ -506,7 +505,11 @@ def validate_date_with_fiscal_year(self): if date_field and self.get(date_field): validate_fiscal_year( - self.get(date_field), self.fiscal_year, self.company, self.meta.get_label(date_field), self + self.get(date_field), + self.fiscal_year, + self.company, + self.meta.get_label(date_field), + self, ) def validate_party_accounts(self): @@ -576,7 +579,9 @@ def disable_tax_included_prices_for_internal_transfer(self): if tax_updated: frappe.msgprint( - _("Disabled tax included prices since this {} is an internal transfer").format(self.doctype), + _("Disabled tax included prices since this {} is an internal transfer").format( + self.doctype + ), alert=1, ) @@ -667,7 +672,7 @@ def set_missing_item_details(self, for_validate=False): parent_dict[fieldname] = self.get(fieldname) if self.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]: - document_type = "{} Item".format(self.doctype) + document_type = f"{self.doctype} Item" parent_dict.update({"document_type": document_type}) # party_name field used for customer in quotation @@ -708,7 +713,9 @@ def set_missing_item_details(self, for_validate=False): if item.get(fieldname) is None or fieldname in force_item_fields: item.set(fieldname, value) - elif fieldname in ["cost_center", "conversion_factor"] and not item.get(fieldname): + elif fieldname in ["cost_center", "conversion_factor"] and not item.get( + fieldname + ): item.set(fieldname, value) elif fieldname == "serial_no": @@ -744,7 +751,8 @@ def set_missing_item_details(self, for_validate=False): # Items add via promotional scheme may not have cost center set if hasattr(item, "cost_center") and not item.get("cost_center"): item.set( - "cost_center", self.get("cost_center") or erpnext.get_default_cost_center(self.company) + "cost_center", + self.get("cost_center") or erpnext.get_default_cost_center(self.company), ) if ret.get("pricing_rules"): @@ -871,9 +879,7 @@ def validate_enabled_taxes_and_charges(self): if self.taxes_and_charges and frappe.get_cached_value( taxes_and_charges_doctype, self.taxes_and_charges, "disabled" ): - frappe.throw( - _("{0} '{1}' is disabled").format(taxes_and_charges_doctype, self.taxes_and_charges) - ) + frappe.throw(_("{0} '{1}' is disabled").format(taxes_and_charges_doctype, self.taxes_and_charges)) def validate_tax_account_company(self): for d in self.get("taxes"): @@ -998,9 +1004,8 @@ def clear_unallocated_advances(self, childtype, parentfield): self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]})) frappe.db.sql( - """delete from `tab%s` where parentfield=%s and parent = %s - and allocated_amount = 0""" - % (childtype, "%s", "%s"), + """delete from `tab{}` where parentfield={} and parent = {} + and allocated_amount = 0""".format(childtype, "%s", "%s"), (parentfield, self.name), ) @@ -1088,9 +1093,7 @@ def get_advance_entries(self, include_unallocated=True): return res def is_inclusive_tax(self): - is_inclusive = cint( - frappe.db.get_single_value("Accounts Settings", "show_inclusive_tax_in_print") - ) + is_inclusive = cint(frappe.db.get_single_value("Accounts Settings", "show_inclusive_tax_in_print")) if is_inclusive: is_inclusive = 0 @@ -1133,7 +1136,6 @@ def set_advance_gain_or_loss(self): for d in self.get("advances"): advance_exchange_rate = d.ref_exchange_rate if d.allocated_amount and self.conversion_rate != advance_exchange_rate: - base_allocated_amount_in_ref_rate = advance_exchange_rate * d.allocated_amount base_allocated_amount_in_inv_rate = self.conversion_rate * d.allocated_amount difference = base_allocated_amount_in_ref_rate - base_allocated_amount_in_inv_rate @@ -1179,7 +1181,7 @@ def gain_loss_journal_already_booked( return False def make_exchange_gain_loss_journal( - self, args: dict = None, dimensions_dict: dict = None + self, args: dict | None = None, dimensions_dict: dict | None = None ) -> None: """ Make Exchange Gain/Loss journal for Invoices and Payments @@ -1199,7 +1201,6 @@ def make_exchange_gain_loss_journal( flt(arg.get("difference_amount", 0), precision) != 0 or flt(arg.get("exchange_gain_loss", 0), precision) != 0 ) and arg.get("difference_account"): - party_account = arg.get("account") gain_loss_account = arg.get("difference_account") difference_amount = arg.get("difference_amount") or arg.get("exchange_gain_loss") @@ -1250,8 +1251,8 @@ def make_exchange_gain_loss_journal( gain_loss_to_book = [x for x in self.references if x.exchange_gain_loss != 0] booked = [] if gain_loss_to_book: - vtypes = [x.reference_doctype for x in gain_loss_to_book] - vnames = [x.reference_name for x in gain_loss_to_book] + [x.reference_doctype for x in gain_loss_to_book] + [x.reference_name for x in gain_loss_to_book] je = qb.DocType("Journal Entry") jea = qb.DocType("Journal Entry Account") parents = ( @@ -1391,7 +1392,9 @@ def update_against_document_in_jv(self): "allocated_amount": flt(d.allocated_amount), "precision": d.precision("advance_amount"), "exchange_rate": ( - self.conversion_rate if self.party_account_currency != self.company_currency else 1 + self.conversion_rate + if self.party_account_currency != self.company_currency + else 1 ), "grand_total": ( self.base_grand_total @@ -1574,9 +1577,12 @@ def make_discount_gl_entries(self, gl_entries): "account": item.discount_account, "against": supplier_or_customer, dr_or_cr: flt( - discount_amount * self.get("conversion_rate"), item.precision("discount_amount") + discount_amount * self.get("conversion_rate"), + item.precision("discount_amount"), + ), + dr_or_cr + "_in_account_currency": flt( + discount_amount, item.precision("discount_amount") ), - dr_or_cr + "_in_account_currency": flt(discount_amount, item.precision("discount_amount")), "cost_center": item.cost_center, "project": item.project, }, @@ -1592,10 +1598,12 @@ def make_discount_gl_entries(self, gl_entries): "account": income_or_expense_account, "against": supplier_or_customer, rev_dr_cr: flt( - discount_amount * self.get("conversion_rate"), item.precision("discount_amount") + discount_amount * self.get("conversion_rate"), + item.precision("discount_amount"), + ), + rev_dr_cr + "_in_account_currency": flt( + discount_amount, item.precision("discount_amount") ), - rev_dr_cr - + "_in_account_currency": flt(discount_amount, item.precision("discount_amount")), "cost_center": item.cost_center, "project": item.project or self.project, }, @@ -1635,9 +1643,7 @@ def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on): total_overbilled_amt = 0.0 reference_names = [d.get(item_ref_dn) for d in self.get("items") if d.get(item_ref_dn)] - reference_details = self.get_billing_reference_details( - reference_names, ref_dt + " Item", based_on - ) + reference_details = self.get_billing_reference_details(reference_names, ref_dt + " Item", based_on) for item in self.get("items"): if not item.get(item_ref_dn): @@ -1823,17 +1829,13 @@ def company_abbr(self): def raise_missing_debit_credit_account_error(self, party_type, party): """Raise an error if debit to/credit to account does not exist.""" - db_or_cr = ( - frappe.bold("Debit To") if self.doctype == "Sales Invoice" else frappe.bold("Credit To") - ) + db_or_cr = frappe.bold("Debit To") if self.doctype == "Sales Invoice" else frappe.bold("Credit To") rec_or_pay = "Receivable" if self.doctype == "Sales Invoice" else "Payable" link_to_party = frappe.utils.get_link_to_form(party_type, party) link_to_company = frappe.utils.get_link_to_form("Company", self.company) - message = _("{0} Account not found against Customer {1}.").format( - db_or_cr, frappe.bold(party) or "" - ) + message = _("{0} Account not found against Customer {1}.").format(db_or_cr, frappe.bold(party) or "") message += "
" + _("Please set one of the following:") + "
" message += ( "
  • " @@ -1886,7 +1888,6 @@ def validate_currency(self): and party_account_currency != self.company_currency and self.currency != party_account_currency ): - frappe.throw( _("Accounting Entry for {0}: {1} can only be made in currency: {2}").format( party_type, party, party_account_currency @@ -1907,9 +1908,7 @@ def validate_party_account_currency(self): party_type, party = self.get_party() party_gle_currency = get_party_gle_currency(party_type, party, self.company) - party_account = ( - self.get("debit_to") if self.doctype == "Sales Invoice" else self.get("credit_to") - ) + party_account = self.get("debit_to") if self.doctype == "Sales Invoice" else self.get("credit_to") party_account_currency = get_account_currency(party_account) allow_multi_currency_invoices_against_single_party_account = frappe.db.get_singles_value( "Accounts Settings", "allow_multi_currency_invoices_against_single_party_account" @@ -1932,10 +1931,8 @@ def delink_advance_entries(self, linked_doc_name): consider_for_total_advance = True if adv.reference_name == linked_doc_name: frappe.db.sql( - """delete from `tab{0} Advance` - where name = %s""".format( - self.doctype - ), + f"""delete from `tab{self.doctype} Advance` + where name = %s""", adv.name, ) consider_for_total_advance = False @@ -2152,7 +2149,9 @@ def validate_payment_schedule_dates(self): for d in self.get("payment_schedule"): if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date): frappe.throw( - _("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(d.idx) + _("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format( + d.idx + ) ) elif d.due_date in dates: li.append(_("{0} in row {1}").format(d.due_date, d.idx)) @@ -2160,9 +2159,7 @@ def validate_payment_schedule_dates(self): if li: duplicates = "
    " + "
    ".join(li) - frappe.throw( - _("Rows with duplicate due dates in other rows were found: {0}").format(duplicates) - ) + frappe.throw(_("Rows with duplicate due dates in other rows were found: {0}").format(duplicates)) def validate_payment_schedule_amount(self): if self.doctype == "Sales Invoice" and self.is_pos: @@ -2285,7 +2282,7 @@ def create_advance_and_reconcile(self, party_link): jv.voucher_type = "Journal Entry" jv.posting_date = self.posting_date jv.company = self.company - jv.remark = "Adjustment for {} {}".format(self.doctype, self.name) + jv.remark = f"Adjustment for {self.doctype} {self.name}" reconcilation_entry = frappe._dict() advance_entry = frappe._dict() @@ -2295,9 +2292,7 @@ def create_advance_and_reconcile(self, party_link): reconcilation_entry.party = secondary_party reconcilation_entry.reference_type = self.doctype reconcilation_entry.reference_name = self.name - reconcilation_entry.cost_center = self.cost_center or erpnext.get_default_cost_center( - self.company - ) + reconcilation_entry.cost_center = self.cost_center or erpnext.get_default_cost_center(self.company) advance_entry.account = primary_account advance_entry.party_type = primary_party_type @@ -2343,7 +2338,7 @@ def check_finance_books(self, item, asset): def check_if_fields_updated(self, fields_to_check, child_tables): # Check if any field affecting accounting entry is altered doc_before_update = self.get_doc_before_save() - accounting_dimensions = get_accounting_dimensions() + ["cost_center", "project"] + accounting_dimensions = [*get_accounting_dimensions(), "cost_center", "project"] # Check if opening entry check updated needs_repost = doc_before_update.get("is_opening") != self.is_opening @@ -2383,9 +2378,7 @@ def repost_accounting_entries(self): @frappe.whitelist() def get_tax_rate(account_head): - return frappe.get_cached_value( - "Account", account_head, ["tax_rate", "account_name"], as_dict=True - ) + return frappe.get_cached_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True) @frappe.whitelist() @@ -2415,7 +2408,7 @@ def get_taxes_and_charges(master_doctype, master_name): tax_master = frappe.get_doc(master_doctype, master_name) taxes_and_charges = [] - for i, tax in enumerate(tax_master.get("taxes")): + for _i, tax in enumerate(tax_master.get("taxes")): tax = tax.as_dict() for fieldname in default_fields + child_table_fields: @@ -2534,9 +2527,7 @@ def set_balance_in_account_currency( ): if (not conversion_rate) and (account_currency != company_currency): frappe.throw( - _("Account: {0} with currency: {1} can not be selected").format( - gl_dict.account, account_currency - ) + _("Account: {0} with currency: {1} can not be selected").format(gl_dict.account, account_currency) ) gl_dict["account_currency"] = ( @@ -2546,9 +2537,7 @@ def set_balance_in_account_currency( # set debit/credit in account currency if not provided if flt(gl_dict.debit) and not flt(gl_dict.debit_in_account_currency): gl_dict.debit_in_account_currency = ( - gl_dict.debit - if account_currency == company_currency - else flt(gl_dict.debit / conversion_rate, 2) + gl_dict.debit if account_currency == company_currency else flt(gl_dict.debit / conversion_rate, 2) ) if flt(gl_dict.credit) and not flt(gl_dict.credit_in_account_currency): @@ -2568,9 +2557,7 @@ def get_advance_journal_entries( order_list, include_unallocated=True, ): - dr_or_cr = ( - "credit_in_account_currency" if party_type == "Customer" else "debit_in_account_currency" - ) + dr_or_cr = "credit_in_account_currency" if party_type == "Customer" else "debit_in_account_currency" conditions = [] if include_unallocated: @@ -2579,7 +2566,7 @@ def get_advance_journal_entries( if order_list: order_condition = ", ".join(["%s"] * len(order_list)) conditions.append( - " (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))".format( + " (t2.reference_type = '{}' and ifnull(t2.reference_name, '') in ({}))".format( order_doctype, order_condition ) ) @@ -2588,10 +2575,10 @@ def get_advance_journal_entries( # nosemgrep journal_entries = frappe.db.sql( - """ + f""" select 'Journal Entry' as reference_type, t1.name as reference_name, - t1.remark as remarks, t2.{0} as amount, t2.name as reference_row, + t1.remark as remarks, t2.{amount_field} as amount, t2.name as reference_row, t2.reference_name as against_order, t2.exchange_rate from `tabJournal Entry` t1, `tabJournal Entry Account` t2 @@ -2599,11 +2586,9 @@ def get_advance_journal_entries( t1.name = t2.parent and t2.account = %s and t2.party_type = %s and t2.party = %s and t2.is_advance = 'Yes' and t1.docstatus = 1 - and {1} > 0 {2} - order by t1.posting_date""".format( - amount_field, dr_or_cr, reference_condition - ), - [party_account, party_type, party] + order_list, + and {dr_or_cr} > 0 {reference_condition} + order by t1.posting_date""", + [party_account, party_type, party, *order_list], as_dict=1, ) @@ -2631,13 +2616,9 @@ def get_advance_payment_entries( per = qb.DocType("Payment Entry Reference") party_account_field = "paid_from" if party_type == "Customer" else "paid_to" - currency_field = ( - "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency" - ) + currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency" payment_type = "Receive" if party_type == "Customer" else "Pay" - exchange_rate_field = ( - "source_exchange_rate" if payment_type == "Receive" else "target_exchange_rate" - ) + exchange_rate_field = "source_exchange_rate" if payment_type == "Receive" else "target_exchange_rate" payment_entries_against_order, unallocated_payment_entries = [], [] @@ -2783,9 +2764,7 @@ def get_payment_terms( schedule = [] for d in terms_doc.get("terms"): - term_details = get_payment_term_details( - d, posting_date, grand_total, base_grand_total, bill_date - ) + term_details = get_payment_term_details(d, posting_date, grand_total, base_grand_total, bill_date) schedule.append(term_details) return schedule @@ -2903,9 +2882,7 @@ def add_taxes_from_tax_template(child_item, parent_doc, db_insert=True): tax_row.db_insert() -def set_order_defaults( - parent_doctype, parent_doctype_name, child_doctype, child_docname, trans_item -): +def set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child_docname, trans_item): """ Returns a Sales/Purchase Order Item child item containing the default values """ @@ -2921,9 +2898,7 @@ def set_order_defaults( child_item.stock_uom = item.stock_uom child_item.uom = trans_item.get("uom") or item.stock_uom child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True) - conversion_factor = flt( - get_conversion_factor(item.item_code, child_item.uom).get("conversion_factor") - ) + conversion_factor = flt(get_conversion_factor(item.item_code, child_item.uom).get("conversion_factor")) child_item.conversion_factor = flt(trans_item.get("conversion_factor")) or conversion_factor if child_doctype == "Purchase Order Item": @@ -3070,9 +3045,7 @@ def validate_workflow_conditions(doc): def get_new_child_item(item_row): child_doctype = "Sales Order Item" if parent_doctype == "Sales Order" else "Purchase Order Item" - return set_order_defaults( - parent_doctype, parent_doctype_name, child_doctype, child_docname, item_row - ) + return set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child_docname, item_row) def validate_quantity(child_item, new_data): if not flt(new_data.get("qty")): @@ -3086,9 +3059,7 @@ def validate_quantity(child_item, new_data): if parent_doctype == "Sales Order" and flt(new_data.get("qty")) < flt(child_item.delivered_qty): frappe.throw(_("Cannot set quantity less than delivered quantity")) - if parent_doctype == "Purchase Order" and flt(new_data.get("qty")) < flt( - child_item.received_qty - ): + if parent_doctype == "Purchase Order" and flt(new_data.get("qty")) < flt(child_item.received_qty): frappe.throw(_("Cannot set quantity less than received quantity")) def should_update_supplied_items(doc) -> bool: @@ -3103,9 +3074,7 @@ def should_update_supplied_items(doc) -> bool: item.supplied_qty or item.consumed_qty or item.returned_qty for item in doc.supplied_items ) - update_supplied_items = ( - any_qty_changed or items_added_or_removed or any_conversion_factor_changed - ) + update_supplied_items = any_qty_changed or items_added_or_removed or any_conversion_factor_changed if update_supplied_items and supplied_items_processed: frappe.throw(_("Item qty can not be updated as raw materials are already processed.")) @@ -3142,8 +3111,9 @@ def should_update_supplied_items(doc) -> bool: prev_rate, new_rate = flt(child_item.get("rate")), flt(d.get("rate")) prev_qty, new_qty = flt(child_item.get("qty")), flt(d.get("qty")) - prev_con_fac, new_con_fac = flt(child_item.get("conversion_factor")), flt( - d.get("conversion_factor") + prev_con_fac, new_con_fac = ( + flt(child_item.get("conversion_factor")), + flt(d.get("conversion_factor")), ) prev_uom, new_uom = child_item.get("uom"), d.get("uom") @@ -3222,7 +3192,8 @@ def should_update_supplied_items(doc) -> bool: if parent_doctype in sales_doctypes: child_item.margin_type = "Amount" child_item.margin_rate_or_amount = flt( - child_item.rate - child_item.price_list_rate, child_item.precision("margin_rate_or_amount") + child_item.rate - child_item.price_list_rate, + child_item.precision("margin_rate_or_amount"), ) child_item.rate_with_margin = child_item.rate else: @@ -3302,10 +3273,8 @@ def should_update_supplied_items(doc) -> bool: parent.set_status() -def check_if_child_table_updated( - child_table_before_update, child_table_after_update, fields_to_check -): - accounting_dimensions = get_accounting_dimensions() + ["cost_center", "project"] +def check_if_child_table_updated(child_table_before_update, child_table_after_update, fields_to_check): + accounting_dimensions = [*get_accounting_dimensions(), "cost_center", "project"] # Check if any field affecting accounting entry is altered for index, item in enumerate(child_table_after_update): for field in fields_to_check: diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 1abf95f5953c..89226453b7ff 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -33,7 +33,7 @@ def get_feed(self): def validate(self): self.set_rate_for_standalone_debit_note() - super(BuyingController, self).validate() + super().validate() if getattr(self, "supplier", None) and not self.supplier_name: self.supplier_name = frappe.db.get_value("Supplier", self.supplier, "supplier_name") @@ -49,9 +49,7 @@ def validate(self): if self.doctype == "Purchase Invoice": self.validate_purchase_receipt_if_update_stock() - if self.doctype == "Purchase Receipt" or ( - self.doctype == "Purchase Invoice" and self.update_stock - ): + if self.doctype == "Purchase Receipt" or (self.doctype == "Purchase Invoice" and self.update_stock): # self.validate_purchase_return() self.validate_rejected_warehouse() self.validate_accepted_rejected_qty() @@ -67,12 +65,10 @@ def validate(self): self.update_valuation_rate() def onload(self): - super(BuyingController, self).onload() + super().onload() self.set_onload( "backflush_based_on", - frappe.db.get_single_value( - "Buying Settings", "backflush_raw_materials_of_subcontract_based_on" - ), + frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on"), ) def set_rate_for_standalone_debit_note(self): @@ -101,7 +97,7 @@ def set_rate_for_standalone_debit_note(self): row.margin_rate_or_amount = 0.0 def set_missing_values(self, for_validate=False): - super(BuyingController, self).set_missing_values(for_validate) + super().set_missing_values(for_validate) self.set_supplier_from_item_default() self.set_price_list_currency("Buying") @@ -161,9 +157,7 @@ def validate_asset_return(self): if self.doctype not in ["Purchase Receipt", "Purchase Invoice"] or not self.is_return: return - purchase_doc_field = ( - "purchase_receipt" if self.doctype == "Purchase Receipt" else "purchase_invoice" - ) + purchase_doc_field = "purchase_receipt" if self.doctype == "Purchase Receipt" else "purchase_invoice" not_cancelled_asset = [] if self.return_against: not_cancelled_asset = [ @@ -494,7 +488,6 @@ def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_vouche pr_qty = flt(flt(d.qty) * flt(d.conversion_factor), d.precision("stock_qty")) if pr_qty: - if d.from_warehouse and ( (not cint(self.is_return) and self.docstatus == 1) or (cint(self.is_return) and self.docstatus == 2) @@ -559,7 +552,8 @@ def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_vouche or (cint(self.is_return) and self.docstatus == 1) ): from_warehouse_sle = self.get_sl_entries( - d, {"actual_qty": -1 * pr_qty, "warehouse": d.from_warehouse, "recalculate_rate": 1} + d, + {"actual_qty": -1 * pr_qty, "warehouse": d.from_warehouse, "recalculate_rate": 1}, ) if flt(rejected_qty) != 0: @@ -631,7 +625,7 @@ def on_submit(self): update_last_purchase_rate(self, is_submit=1) def on_cancel(self): - super(BuyingController, self).on_cancel() + super().on_cancel() if self.get("is_return"): return @@ -656,7 +650,9 @@ def validate_budget(self): "doctype": self.doctype, "company": self.company, "posting_date": ( - self.schedule_date if self.doctype == "Material Request" else self.transaction_date + self.schedule_date + if self.doctype == "Material Request" + else self.transaction_date ), } ) @@ -688,17 +684,21 @@ def auto_make_assets(self, asset_items): asset = self.make_asset(d, is_grouped_asset=True) created_assets.append(asset) else: - for qty in range(cint(d.qty)): + for _qty in range(cint(d.qty)): asset = self.make_asset(d) created_assets.append(asset) if len(created_assets) > 5: # dont show asset form links if more than 5 assets are created messages.append( - _("{} Assets created for {}").format(len(created_assets), frappe.bold(d.item_code)) + _("{} Assets created for {}").format( + len(created_assets), frappe.bold(d.item_code) + ) ) else: - assets_link = list(map(lambda d: frappe.utils.get_link_to_form("Asset", d), created_assets)) + assets_link = list( + map(lambda d: frappe.utils.get_link_to_form("Asset", d), created_assets) + ) assets_link = frappe.bold(",".join(assets_link)) is_plural = "s" if len(created_assets) != 1 else "" @@ -709,9 +709,9 @@ def auto_make_assets(self, asset_items): ) else: frappe.throw( - _("Row {}: Asset Naming Series is mandatory for the auto creation for item {}").format( - d.idx, frappe.bold(d.item_code) - ) + _( + "Row {}: Asset Naming Series is mandatory for the auto creation for item {}" + ).format(d.idx, frappe.bold(d.item_code)) ) else: messages.append( @@ -874,11 +874,9 @@ def validate_item_type(doc, fieldname, message): invalid_items = [ d[0] for d in frappe.db.sql( - """ - select item_code from tabItem where name in ({0}) and {1}=0 - """.format( - item_list, fieldname - ), + f""" + select item_code from tabItem where name in ({item_list}) and {fieldname}=0 + """, as_list=True, ) ] diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 1ba10259a8ec..2a1a00c52146 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -56,9 +56,7 @@ def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part variant.flags.ignore_mandatory = True variant.save() - if not frappe.db.exists( - "Item Manufacturer", {"item_code": variant.name, "manufacturer": manufacturer} - ): + if not frappe.db.exists("Item Manufacturer", {"item_code": variant.name, "manufacturer": manufacturer}): manufacturer_doc = frappe.new_doc("Item Manufacturer") manufacturer_doc.update( { @@ -122,9 +120,7 @@ def validate_is_incremental(numeric_attribute, attribute, value, item): ) -def validate_item_attribute_value( - attributes_list, attribute, attribute_value, item, from_variant=True -): +def validate_item_attribute_value(attributes_list, attribute, attribute_value, item, from_variant=True): allow_rename_attribute_value = frappe.db.get_single_value( "Item Variant Settings", "allow_rename_attribute_value" ) @@ -172,7 +168,7 @@ def get_attribute_values(item): def find_variant(template, args, variant_item_code=None): conditions = [ - """(iv_attribute.attribute={0} and iv_attribute.attribute_value={1})""".format( + """(iv_attribute.attribute={} and iv_attribute.attribute_value={})""".format( frappe.db.escape(key), frappe.db.escape(cstr(value)) ) for key, value in args.items() @@ -182,9 +178,7 @@ def find_variant(template, args, variant_item_code=None): from erpnext.e_commerce.variant_selector.utils import get_item_codes_by_attributes - possible_variants = [ - i for i in get_item_codes_by_attributes(args, template) if i != variant_item_code - ] + possible_variants = [i for i in get_item_codes_by_attributes(args, template) if i != variant_item_code] for variant in possible_variants: variant = frappe.get_doc("Item", variant) @@ -360,7 +354,9 @@ def copy_attributes_to_variant(item, variant): if variant.attributes: attributes_description = item.description + " " for d in variant.attributes: - attributes_description += "
    " + d.attribute + ": " + cstr(d.attribute_value) + "
    " + attributes_description += ( + "
    " + d.attribute + ": " + cstr(d.attribute_value) + "
    " + ) if attributes_description not in variant.description: variant.description = attributes_description @@ -394,8 +390,8 @@ def make_variant_item_code(template_item_code, template_item_name, variant): abbreviations.append(abbr_or_value) if abbreviations: - variant.item_code = "{0}-{1}".format(template_item_code, "-".join(abbreviations)) - variant.item_name = "{0}-{1}".format(template_item_name, "-".join(abbreviations)) + variant.item_code = "{}-{}".format(template_item_code, "-".join(abbreviations)) + variant.item_name = "{}-{}".format(template_item_name, "-".join(abbreviations)) @frappe.whitelist() diff --git a/erpnext/controllers/print_settings.py b/erpnext/controllers/print_settings.py index b906a8a79872..629404d3c821 100644 --- a/erpnext/controllers/print_settings.py +++ b/erpnext/controllers/print_settings.py @@ -39,7 +39,7 @@ def set_print_templates_for_taxes(doc, settings): def format_columns(display_columns, compact_fields): - compact_fields = compact_fields + ["image", "item_code", "item_name"] + compact_fields = [*compact_fields, "image", "item_code", "item_name"] final_columns = [] for column in display_columns: if column not in compact_fields: diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 0e5f67247771..be965e41b3e7 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -162,7 +162,7 @@ def get_accounts(with_account_type_filter): account_type_condition = "AND account_type in %(account_types)s" accounts = frappe.db.sql( - """ + f""" SELECT name, parent_account FROM `tabAccount` WHERE `tabAccount`.docstatus!=2 @@ -172,20 +172,16 @@ def get_accounts(with_account_type_filter): AND disabled = %(disabled)s AND (account_currency = %(currency)s or ifnull(account_currency, '') = '') AND `{searchfield}` LIKE %(txt)s - {mcond} + {get_match_cond(doctype)} ORDER BY idx DESC, name LIMIT %(limit)s offset %(offset)s - """.format( - account_type_condition=account_type_condition, - searchfield=searchfield, - mcond=get_match_cond(doctype), - ), + """, dict( account_types=filters.get("account_type"), company=filters.get("company"), disabled=filters.get("disabled", 0), currency=company_currency, - txt="%{}%".format(txt), + txt=f"%{txt}%", offset=start, limit=page_len, ), @@ -215,7 +211,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals searchfields = meta.get_search_fields() columns = "" - extra_searchfields = [field for field in searchfields if not field in ["name", "description"]] + extra_searchfields = [field for field in searchfields if field not in ["name", "description"]] if extra_searchfields: columns += ", " + ", ".join(extra_searchfields) @@ -227,7 +223,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals searchfields = searchfields + [ field for field in [searchfield or "name", "item_code", "item_group", "item_name"] - if not field in searchfields + if field not in searchfields ] searchfields = " or ".join([field + " like %(txt)s" for field in searchfields]) @@ -235,7 +231,9 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if filters.get("customer") or filters.get("supplier"): party = filters.get("customer") or filters.get("supplier") item_rules_list = frappe.get_all( - "Party Specific Item", filters={"party": party}, fields=["restrict_based_on", "based_on_value"] + "Party Specific Item", + filters={"party": party}, + fields=["restrict_based_on", "based_on_value"], ) filters_dict = {} @@ -384,11 +382,11 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, return frappe.db.sql( """ - select %(fields)s + select {fields} from `tabDelivery Note` - where `tabDelivery Note`.`%(key)s` like %(txt)s and + where `tabDelivery Note`.`{key}` like {txt} and `tabDelivery Note`.docstatus = 1 - and status not in ('Stopped', 'Closed') %(fcond)s + and status not in ('Stopped', 'Closed') {fcond} and ( (`tabDelivery Note`.is_return = 0 and `tabDelivery Note`.per_billed < 100) or (`tabDelivery Note`.grand_total = 0 and `tabDelivery Note`.per_billed < 100) @@ -397,17 +395,16 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, and return_against in (select name from `tabDelivery Note` where per_billed < 100) ) ) - %(mcond)s order by `tabDelivery Note`.`%(key)s` asc limit %(page_len)s offset %(start)s - """ - % { - "fields": ", ".join(["`tabDelivery Note`.{0}".format(f) for f in fields]), - "key": searchfield, - "fcond": get_filters_cond(doctype, filters, []), - "mcond": get_match_cond(doctype), - "start": start, - "page_len": page_len, - "txt": "%(txt)s", - }, + {mcond} order by `tabDelivery Note`.`{key}` asc limit {page_len} offset {start} + """.format( + fields=", ".join([f"`tabDelivery Note`.{f}" for f in fields]), + key=searchfield, + fcond=get_filters_cond(doctype, filters, []), + mcond=get_match_cond(doctype), + start=start, + page_len=page_len, + txt="%(txt)s", + ), {"txt": ("%%%s%%" % txt)}, as_dict=as_dict, ) @@ -426,7 +423,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): "item_code": filters.get("item_code"), "warehouse": filters.get("warehouse"), "posting_date": filters.get("posting_date"), - "txt": "%{0}%".format(txt), + "txt": f"%{txt}%", "start": start, "page_len": page_len, } @@ -452,7 +449,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields]) batch_nos = frappe.db.sql( - """select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, + f"""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date) {search_columns} from `tabStock Ledger Entry` sle @@ -468,23 +465,17 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): {search_cond}) and batch.docstatus < 2 {cond} - {match_conditions} + {get_match_cond(doctype)} group by batch_no {having_clause} order by batch.expiry_date, sle.batch_no desc - limit %(page_len)s offset %(start)s""".format( - search_columns=search_columns, - cond=cond, - match_conditions=get_match_cond(doctype), - having_clause=having_clause, - search_cond=search_cond, - ), + limit %(page_len)s offset %(start)s""", args, ) return batch_nos else: return frappe.db.sql( - """select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date) + f"""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date) {search_columns} from `tabBatch` batch where batch.disabled = 0 @@ -494,16 +485,11 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): or manufacturing_date like %(txt)s {search_cond}) and docstatus < 2 - {0} - {match_conditions} + {cond} + {get_match_cond(doctype)} order by expiry_date, name desc - limit %(page_len)s offset %(start)s""".format( - cond, - search_columns=search_columns, - search_cond=search_cond, - match_conditions=get_match_cond(doctype), - ), + limit %(page_len)s offset %(start)s""", args, ) @@ -516,7 +502,7 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters): if isinstance(filters, dict): for key, val in filters.items(): - if isinstance(val, (list, tuple)): + if isinstance(val, list | tuple): filter_list.append([doctype, key, val[0], val[1]]) else: filter_list.append([doctype, key, "=", val]) @@ -577,24 +563,20 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters): condition += f"and tabAccount.disabled = {filters.get('disabled', 0)}" return frappe.db.sql( - """select tabAccount.name from `tabAccount` + f"""select tabAccount.name from `tabAccount` where (tabAccount.report_type = "Profit and Loss" or tabAccount.account_type in ("Income Account", "Temporary")) and tabAccount.is_group=0 - and tabAccount.`{key}` LIKE %(txt)s - {condition} {match_condition} - order by idx desc, name""".format( - condition=condition, match_condition=get_match_cond(doctype), key=searchfield - ), + and tabAccount.`{searchfield}` LIKE %(txt)s + {condition} {get_match_cond(doctype)} + order by idx desc, name""", {"txt": "%" + txt + "%", "company": filters.get("company", "")}, ) @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs -def get_filtered_dimensions( - doctype, txt, searchfield, start, page_len, filters, reference_doctype=None -): +def get_filtered_dimensions(doctype, txt, searchfield, start, page_len, filters, reference_doctype=None): from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import ( get_dimension_filter_map, ) @@ -660,15 +642,13 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters): condition += "and tabAccount.company = %(company)s" return frappe.db.sql( - """select tabAccount.name from `tabAccount` + f"""select tabAccount.name from `tabAccount` where (tabAccount.report_type = "Profit and Loss" or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed", "Capital Work in Progress")) and tabAccount.is_group=0 and tabAccount.docstatus!=2 - and tabAccount.{key} LIKE %(txt)s - {condition} {match_condition}""".format( - condition=condition, key=searchfield, match_condition=get_match_cond(doctype) - ), + and tabAccount.{searchfield} LIKE %(txt)s + {condition} {get_match_cond(doctype)}""", {"company": filters.get("company", ""), "txt": "%" + txt + "%"}, ) @@ -707,7 +687,7 @@ def warehouse_query(doctype, txt, searchfield, start, page_len, filters): mcond=get_match_cond(doctype), start=start, page_len=page_len, - txt=frappe.db.escape("%{0}%".format(txt)), + txt=frappe.db.escape(f"%{txt}%"), ) return frappe.db.sql(query) @@ -727,9 +707,7 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters): query = """select batch_id from `tabBatch` where disabled = 0 and (expiry_date >= CURRENT_DATE or expiry_date IS NULL) - and name like {txt}""".format( - txt=frappe.db.escape("%{0}%".format(txt)) - ) + and name like {txt}""".format(txt=frappe.db.escape(f"%{txt}%")) if filters and filters.get("item"): query += " and item = {item}".format(item=frappe.db.escape(filters.get("item"))) @@ -763,9 +741,7 @@ def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters): select pr.name from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pritem where pr.docstatus = 1 and pritem.parent = pr.name - and pr.name like {txt}""".format( - txt=frappe.db.escape("%{0}%".format(txt)) - ) + and pr.name like {txt}""".format(txt=frappe.db.escape(f"%{txt}%")) if filters and filters.get("item_code"): query += " and pritem.item_code = {item_code}".format( @@ -782,9 +758,7 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters): select pi.name from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` piitem where pi.docstatus = 1 and piitem.parent = pi.name - and pi.name like {txt}""".format( - txt=frappe.db.escape("%{0}%".format(txt)) - ) + and pi.name like {txt}""".format(txt=frappe.db.escape(f"%{txt}%")) if filters and filters.get("item_code"): query += " and piitem.item_code = {item_code}".format( @@ -806,7 +780,6 @@ def get_doctypes_for_closing(doctype, txt, searchfield, start, page_len, filters @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def get_tax_template(doctype, txt, searchfield, start, page_len, filters): - item_doc = frappe.get_cached_doc("Item", filters.get("item_code")) item_group = filters.get("item_group") company = filters.get("company") @@ -818,9 +791,7 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters): item_group = item_group_doc.parent_item_group if not taxes: - return frappe.get_all( - "Item Tax Template", filters={"disabled": 0, "company": company}, as_list=True - ) + return frappe.get_all("Item Tax Template", filters={"disabled": 0, "company": company}, as_list=True) else: valid_from = filters.get("valid_from") valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from @@ -842,7 +813,7 @@ def get_fields(doctype, fields=None): meta = frappe.get_meta(doctype) fields.extend(meta.get_search_fields()) - if meta.title_field and not meta.title_field.strip() in fields: + if meta.title_field and meta.title_field.strip() not in fields: fields.insert(1, meta.title_field.strip()) return unique(fields) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index f1d1e7eaebdb..eca751f76bce 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -26,9 +26,7 @@ def validate_return(doc): def validate_return_against(doc): if not frappe.db.exists(doc.doctype, doc.return_against): - frappe.throw( - _("Invalid {0}: {1}").format(doc.meta.get_label("return_against"), doc.return_against) - ) + frappe.throw(_("Invalid {0}: {1}").format(doc.meta.get_label("return_against"), doc.return_against)) else: ref_doc = frappe.get_doc(doc.doctype, doc.return_against) @@ -40,8 +38,8 @@ def validate_return_against(doc): and ref_doc.docstatus.is_submitted() ): # validate posting date time - return_posting_datetime = "%s %s" % (doc.posting_date, doc.get("posting_time") or "00:00:00") - ref_posting_datetime = "%s %s" % ( + return_posting_datetime = "{} {}".format(doc.posting_date, doc.get("posting_time") or "00:00:00") + ref_posting_datetime = "{} {}".format( ref_doc.posting_date, ref_doc.get("posting_time") or "00:00:00", ) @@ -81,7 +79,7 @@ def validate_returned_items(doc): select_fields += ",rejected_qty, received_qty" for d in frappe.db.sql( - """select {0} from `tab{1} Item` where parent = %s""".format(select_fields, doc.doctype), + f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""", doc.return_against, as_dict=1, ): @@ -249,17 +247,15 @@ def get_already_returned_items(doc): sum(abs(child.received_qty) * child.conversion_factor) as received_qty""" data = frappe.db.sql( - """ - select {0} + f""" + select {column} from - `tab{1} Item` child, `tab{2}` par + `tab{doc.doctype} Item` child, `tab{doc.doctype}` par where child.parent = par.name and par.docstatus = 1 and par.is_return = 1 and par.return_against = %s group by item_code - """.format( - column, doc.doctype, doc.doctype - ), + """, doc.return_against, as_dict=1, ) @@ -292,22 +288,22 @@ def get_returned_qty_map_for_row(return_against, party, row_name, doctype): party_type = "customer" fields = [ - "sum(abs(`tab{0}`.qty)) as qty".format(child_doctype), + f"sum(abs(`tab{child_doctype}`.qty)) as qty", ] if doctype != "Subcontracting Receipt": fields += [ - "sum(abs(`tab{0}`.stock_qty)) as stock_qty".format(child_doctype), + f"sum(abs(`tab{child_doctype}`.stock_qty)) as stock_qty", ] if doctype in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"): fields += [ - "sum(abs(`tab{0}`.rejected_qty)) as rejected_qty".format(child_doctype), - "sum(abs(`tab{0}`.received_qty)) as received_qty".format(child_doctype), + f"sum(abs(`tab{child_doctype}`.rejected_qty)) as rejected_qty", + f"sum(abs(`tab{child_doctype}`.received_qty)) as received_qty", ] if doctype == "Purchase Receipt": - fields += ["sum(abs(`tab{0}`.received_stock_qty)) as received_stock_qty".format(child_doctype)] + fields += [f"sum(abs(`tab{child_doctype}`.received_stock_qty)) as received_stock_qty"] # Used retrun against and supplier and is_retrun because there is an index added for it data = frappe.get_all( @@ -523,8 +519,7 @@ def update_terms(source_doc, target_doc, source_parent): "docstatus": ["=", 1], }, }, - doctype - + " Item": { + doctype + " Item": { "doctype": doctype + " Item", "field_map": {"serial_no": "serial_no", "batch_no": "batch_no", "bom": "bom"}, "postprocess": update_item, @@ -623,11 +618,7 @@ def get_filters( if reference_voucher_detail_no: filters["voucher_detail_no"] = reference_voucher_detail_no - if ( - voucher_type in ["Purchase Receipt", "Purchase Invoice"] - and item_row - and item_row.get("warehouse") - ): + if voucher_type in ["Purchase Receipt", "Purchase Invoice"] and item_row and item_row.get("warehouse"): filters["warehouse"] = item_row.get("warehouse") return filters diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 34abe9f764f5..5c38d7bef3a0 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -23,13 +23,13 @@ def get_feed(self): return _("To {0} | {1} {2}").format(self.customer_name, self.currency, self.grand_total) def onload(self): - super(SellingController, self).onload() + super().onload() if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"): for item in self.get("items") + (self.get("packed_items") or []): item.update(get_bin_details(item.item_code, item.warehouse, include_child_warehouses=True)) def validate(self): - super(SellingController, self).validate() + super().validate() self.validate_items() if not self.get("is_debit_note"): self.validate_max_discount() @@ -44,7 +44,7 @@ def validate(self): self.validate_auto_repeat_subscription_dates() def set_missing_values(self, for_validate=False): - super(SellingController, self).set_missing_values(for_validate) + super().set_missing_values(for_validate) # set contact and address details for customer, if they are not mentioned self.set_missing_lead_customer_details(for_validate=for_validate) @@ -284,7 +284,10 @@ def throw_message(idx, item_name, rate, ref_rate_field): if flt(item.base_net_rate) < flt(last_valuation_rate_in_sales_uom): throw_message( - item.idx, item.item_name, last_valuation_rate_in_sales_uom, "valuation rate (Moving Average)" + item.idx, + item.item_name, + last_valuation_rate_in_sales_uom, + "valuation rate (Moving Average)", ) def get_item_list(self): @@ -412,7 +415,8 @@ def update_reserved_qty(self): "Cancelled" ]: frappe.throw( - _("{0} {1} is cancelled or closed").format(_("Sales Order"), so), frappe.InvalidStatusError + _("{0} {1} is cancelled or closed").format(_("Sales Order"), so), + frappe.InvalidStatusError, ) sales_order.update_reserved_qty(so_item_rows) @@ -587,7 +591,8 @@ def set_gross_profit(self): if self.doctype in ["Sales Order", "Quotation"]: for item in self.items: item.gross_profit = flt( - ((item.base_rate - flt(item.valuation_rate)) * item.stock_qty), self.precision("amount", item) + ((item.base_rate - flt(item.valuation_rate)) * item.stock_qty), + self.precision("amount", item), ) def set_customer_address(self): @@ -664,9 +669,9 @@ def validate_target_warehouse(self): if d.get("target_warehouse") and d.get("warehouse") == d.get("target_warehouse"): warehouse = frappe.bold(d.get("target_warehouse")) frappe.throw( - _("Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same").format( - d.idx, warehouse, warehouse - ) + _( + "Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same" + ).format(d.idx, warehouse, warehouse) ) if not self.get("is_internal_customer") and any(d.get("target_warehouse") for d in items): diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 04d0dd36775b..dd3fab05ce68 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -253,9 +253,7 @@ def validate_qty(self): """select item_code, `{target_ref_field}`, `{target_field}`, parenttype, parent from `tab{target_dt}` where `{target_ref_field}` < `{target_field}` - and name=%s and docstatus=1""".format( - **args - ), + and name=%s and docstatus=1""".format(**args), args["name"], as_dict=1, ) @@ -300,9 +298,7 @@ def check_overflow_with_allowance(self, item, args): role_allowed_to_over_bill = frappe.db.get_single_value( "Accounts Settings", "role_allowed_to_over_bill" ) - role = ( - role_allowed_to_over_deliver_receive if qty_or_amount == "qty" else role_allowed_to_over_bill - ) + role = role_allowed_to_over_deliver_receive if qty_or_amount == "qty" else role_allowed_to_over_bill overflow_percent = ( (item[args["target_field"]] - item[args["target_ref_field"]]) / item[args["target_ref_field"]] @@ -413,12 +409,11 @@ def _update_children(self, args, update_modified): args["second_source_extra_cond"] = "" args["second_source_condition"] = frappe.db.sql( - """ select ifnull((select sum(%(second_source_field)s) - from `tab%(second_source_dt)s` - where `%(second_join_field)s`='%(detail_id)s' - and (`tab%(second_source_dt)s`.docstatus=1) - %(second_source_extra_cond)s), 0) """ - % args + """ select ifnull((select sum({second_source_field}) + from `tab{second_source_dt}` + where `{second_join_field}`='{detail_id}' + and (`tab{second_source_dt}`.docstatus=1) + {second_source_extra_cond}), 0) """.format(**args) )[0][0] if args["detail_id"]: @@ -428,11 +423,10 @@ def _update_children(self, args, update_modified): args["source_dt_value"] = ( frappe.db.sql( """ - (select ifnull(sum(%(source_field)s), 0) - from `tab%(source_dt)s` where `%(join_field)s`='%(detail_id)s' - and (docstatus=1 %(cond)s) %(extra_cond)s) - """ - % args + (select ifnull(sum({source_field}), 0) + from `tab{source_dt}` where `{join_field}`='{detail_id}' + and (docstatus=1 {cond}) {extra_cond}) + """.format(**args) )[0][0] or 0.0 ) @@ -441,10 +435,9 @@ def _update_children(self, args, update_modified): args["source_dt_value"] += flt(args["second_source_condition"]) frappe.db.sql( - """update `tab%(target_dt)s` - set %(target_field)s = %(source_dt_value)s %(update_modified)s - where name='%(detail_id)s'""" - % args + """update `tab{target_dt}` + set {target_field} = {source_dt_value} {update_modified} + where name='{detail_id}'""".format(**args) ) def _update_percent_field_in_targets(self, args, update_modified=True): @@ -471,26 +464,24 @@ def _update_percent_field(self, args, update_modified=True): if args.get("target_parent_field"): frappe.db.sql( - """update `tab%(target_parent_dt)s` - set %(target_parent_field)s = round( + """update `tab{target_parent_dt}` + set {target_parent_field} = round( ifnull((select - ifnull(sum(case when abs(%(target_ref_field)s) > abs(%(target_field)s) then abs(%(target_field)s) else abs(%(target_ref_field)s) end), 0) - / sum(abs(%(target_ref_field)s)) * 100 - from `tab%(target_dt)s` where parent='%(name)s' and parenttype='%(target_parent_dt)s' having sum(abs(%(target_ref_field)s)) > 0), 0), 6) - %(update_modified)s - where name='%(name)s'""" - % args + ifnull(sum(case when abs({target_ref_field}) > abs({target_field}) then abs({target_field}) else abs({target_ref_field}) end), 0) + / sum(abs({target_ref_field})) * 100 + from `tab{target_dt}` where parent='{name}' and parenttype='{target_parent_dt}' having sum(abs({target_ref_field})) > 0), 0), 6) + {update_modified} + where name='{name}'""".format(**args) ) # update field if args.get("status_field"): frappe.db.sql( - """update `tab%(target_parent_dt)s` - set %(status_field)s = (case when %(target_parent_field)s<0.001 then 'Not %(keyword)s' - else case when %(target_parent_field)s>=99.999999 then 'Fully %(keyword)s' - else 'Partly %(keyword)s' end end) - where name='%(name)s'""" - % args + """update `tab{target_parent_dt}` + set {status_field} = (case when {target_parent_field}<0.001 then 'Not {keyword}' + else case when {target_parent_field}>=99.999999 then 'Fully {keyword}' + else 'Partly {keyword}' end end) + where name='{name}'""".format(**args) ) if update_modified: @@ -503,21 +494,19 @@ def _update_modified(self, args, update_modified): args["update_modified"] = "" return - args["update_modified"] = ", modified = {0}, modified_by = {1}".format( + args["update_modified"] = ", modified = {}, modified_by = {}".format( frappe.db.escape(now()), frappe.db.escape(frappe.session.user) ) def update_billing_status_for_zero_amount_refdoc(self, ref_dt): ref_fieldname = frappe.scrub(ref_dt) - ref_docs = [ - item.get(ref_fieldname) for item in (self.get("items") or []) if item.get(ref_fieldname) - ] + ref_docs = [item.get(ref_fieldname) for item in (self.get("items") or []) if item.get(ref_fieldname)] if not ref_docs: return zero_amount_refdocs = frappe.db.sql_list( - """ + f""" SELECT name from @@ -526,9 +515,7 @@ def update_billing_status_for_zero_amount_refdoc(self, ref_dt): docstatus = 1 and base_net_total = 0 and name in %(ref_docs)s - """.format( - ref_dt=ref_dt - ), + """, {"ref_docs": ref_docs}, ) @@ -539,9 +526,8 @@ def update_billing_status(self, zero_amount_refdoc, ref_dt, ref_fieldname): for ref_dn in zero_amount_refdoc: ref_doc_qty = flt( frappe.db.sql( - """select ifnull(sum(qty), 0) from `tab%s Item` - where parent=%s""" - % (ref_dt, "%s"), + """select ifnull(sum(qty), 0) from `tab{} Item` + where parent={}""".format(ref_dt, "%s"), (ref_dn), )[0][0] ) @@ -549,8 +535,7 @@ def update_billing_status(self, zero_amount_refdoc, ref_dt, ref_fieldname): billed_qty = flt( frappe.db.sql( """select ifnull(sum(qty), 0) - from `tab%s Item` where %s=%s and docstatus=1""" - % (self.doctype, ref_fieldname, "%s"), + from `tab{} Item` where {}={} and docstatus=1""".format(self.doctype, ref_fieldname, "%s"), (ref_dn), )[0][0] ) @@ -608,13 +593,13 @@ def get_allowance_for( ) if qty_or_amount == "qty" and not qty_allowance: - if global_qty_allowance == None: + if global_qty_allowance is None: global_qty_allowance = flt( frappe.get_cached_value("Stock Settings", None, "over_delivery_receipt_allowance") ) qty_allowance = global_qty_allowance elif qty_or_amount == "amount" and not over_billing_allowance: - if global_amount_allowance == None: + if global_amount_allowance is None: global_amount_allowance = flt( frappe.get_cached_value("Accounts Settings", None, "over_billing_allowance") ) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 8d7d888c2c9c..15a79c8efb41 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -3,7 +3,6 @@ import json from collections import defaultdict -from typing import List, Tuple import frappe from frappe import _, bold @@ -42,7 +41,7 @@ class BatchExpiredError(frappe.ValidationError): class StockController(AccountsController): def validate(self): - super(StockController, self).validate() + super().validate() if not self.get("is_return"): self.validate_inspection() self.validate_serialized_batch() @@ -126,10 +125,7 @@ def clean_serial_nos(self): # remove extra whitespace and store one serial no on each line row.serial_no = clean_serial_no_string(row.serial_no) - def get_gl_entries( - self, warehouse_account=None, default_expense_account=None, default_cost_center=None - ): - + def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account_map(self.company) @@ -167,7 +163,9 @@ def get_gl_entries( "project": item_row.project or self.get("project"), "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": flt(sle.stock_value_difference, precision), - "is_opening": item_row.get("is_opening") or self.get("is_opening") or "No", + "is_opening": item_row.get("is_opening") + or self.get("is_opening") + or "No", }, warehouse_account[sle.warehouse]["account_currency"], item=item_row, @@ -183,7 +181,9 @@ def get_gl_entries( "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": -1 * flt(sle.stock_value_difference, precision), "project": item_row.get("project") or self.get("project"), - "is_opening": item_row.get("is_opening") or self.get("is_opening") or "No", + "is_opening": item_row.get("is_opening") + or self.get("is_opening") + or "No", }, item=item_row, ) @@ -250,9 +250,7 @@ def get_gl_entries( def get_debit_field_precision(self): if not frappe.flags.debit_field_precision: - frappe.flags.debit_field_precision = frappe.get_precision( - "GL Entry", "debit_in_account_currency" - ) + frappe.flags.debit_field_precision = frappe.get_precision("GL Entry", "debit_in_account_currency") return frappe.flags.debit_field_precision @@ -285,7 +283,7 @@ def get_voucher_details(self, default_expense_account, default_cost_center, sle_ return details - def get_items_and_warehouses(self) -> Tuple[List[str], List[str]]: + def get_items_and_warehouses(self) -> tuple[list[str], list[str]]: """Get list of items and warehouses affected by a transaction""" if not (hasattr(self, "items") or hasattr(self, "packed_items")): @@ -395,9 +393,7 @@ def delete_auto_created_batches(self): if not d.batch_no: continue - frappe.db.set_value( - "Serial No", {"batch_no": d.batch_no, "status": "Inactive"}, "batch_no", None - ) + frappe.db.set_value("Serial No", {"batch_no": d.batch_no, "status": "Inactive"}, "batch_no", None) d.batch_no = None d.db_set("batch_no", None) @@ -520,9 +516,7 @@ def get_serialized_items(self): if item_codes: serialized_items = frappe.db.sql_list( """select name from `tabItem` - where has_serial_no=1 and name in ({})""".format( - ", ".join(["%s"] * len(item_codes)) - ), + where has_serial_no=1 and name in ({})""".format(", ".join(["%s"] * len(item_codes))), tuple(item_codes), ) @@ -610,16 +604,12 @@ def validate_qi_presence(self, row): def validate_qi_submission(self, row): """Check if QI is submitted on row level, during submission""" - action = frappe.db.get_single_value( - "Stock Settings", "action_if_quality_inspection_is_not_submitted" - ) + action = frappe.db.get_single_value("Stock Settings", "action_if_quality_inspection_is_not_submitted") qa_docstatus = frappe.db.get_value("Quality Inspection", row.quality_inspection, "docstatus") if not qa_docstatus == 1: link = frappe.utils.get_link_to_form("Quality Inspection", row.quality_inspection) - msg = ( - f"Row #{row.idx}: Quality Inspection {link} is not submitted for the item: {row.item_code}" - ) + msg = f"Row #{row.idx}: Quality Inspection {link} is not submitted for the item: {row.item_code}" if action == "Stop": frappe.throw(_(msg), title=_("Inspection Submission"), exc=QualityInspectionNotSubmittedError) else: @@ -683,9 +673,7 @@ def validate_internal_transfer_warehouse(self): row.from_warehouse = None def validate_in_transit_warehouses(self): - if ( - self.doctype == "Sales Invoice" and self.get("update_stock") - ) or self.doctype == "Delivery Note": + if (self.doctype == "Sales Invoice" and self.get("update_stock")) or self.doctype == "Delivery Note": for item in self.get("items"): if not item.target_warehouse: frappe.throw( @@ -854,7 +842,9 @@ def validate_putaway_capacity(self): if self.doctype == "Stock Reconciliation": stock_qty = flt(item.qty) else: - stock_qty = flt(item.transfer_qty) if self.doctype == "Stock Entry" else flt(item.stock_qty) + stock_qty = ( + flt(item.transfer_qty) if self.doctype == "Stock Entry" else flt(item.stock_qty) + ) rule_name = rule.get("name") if not rule_map[rule_name]: @@ -870,9 +860,7 @@ def validate_putaway_capacity(self): frappe.throw(msg=message, title=_("Over Receipt")) def prepare_over_receipt_message(self, rule, values): - message = _( - "{0} qty of Item {1} is being received into Warehouse {2} with capacity {3}." - ).format( + message = _("{0} qty of Item {1} is being received into Warehouse {2} with capacity {3}.").format( frappe.bold(values["qty_put"]), frappe.bold(values["item"]), frappe.bold(values["warehouse"]), @@ -923,7 +911,6 @@ def add_gl_entry( item=None, posting_date=None, ): - gl_entry = { "account": account, "cost_center": cost_center, @@ -1050,9 +1037,7 @@ def future_sle_exists(args, sl_entries=None): and is_cancelled = 0 GROUP BY item_code, warehouse - """.format( - " or ".join(or_conditions) - ), + """.format(" or ".join(or_conditions)), args, as_dict=1, ) diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index 5c069b1e2755..6c9f066ff55a 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -17,7 +17,7 @@ class SubcontractingController(StockController): def __init__(self, *args, **kwargs): - super(SubcontractingController, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.get("is_old_subcontracting_flow"): self.subcontract_data = frappe._dict( { @@ -49,7 +49,7 @@ def validate(self): self.validate_items() self.create_raw_materials_supplied() else: - super(SubcontractingController, self).validate() + super().validate() def remove_empty_rows(self): for key in ["service_items", "items", "supplied_items"]: @@ -85,11 +85,15 @@ def validate_items(self): bom = frappe.get_doc("BOM", item.bom) if not bom.is_active: frappe.throw( - _("Row {0}: Please select an active BOM for Item {1}.").format(item.idx, item.item_name) + _("Row {0}: Please select an active BOM for Item {1}.").format( + item.idx, item.item_name + ) ) if bom.item != item.item_code: frappe.throw( - _("Row {0}: Please select an valid BOM for Item {1}.").format(item.idx, item.item_name) + _("Row {0}: Please select an valid BOM for Item {1}.").format( + item.idx, item.item_name + ) ) else: frappe.throw(_("Row {0}: Please select a BOM for Item {1}.").format(item.idx, item.item_name)) @@ -165,7 +169,6 @@ def __get_pending_qty_to_receive(self): fields=["item_code", "(qty - received_qty) as qty", "parent", "name"], filters={"docstatus": 1, "parent": ("in", self.subcontract_orders)}, ): - self.qty_to_be_received[(row.item_code, row.parent)] += row.qty def __get_transferred_items(self): @@ -253,9 +256,7 @@ def __update_consumed_materials(self, doctype, return_consumed_items=False): if not receipt_items: return ([], {}) if return_consumed_items else None - receipt_items = { - item.name: item.get(self.subcontract_data.order_field) for item in receipt_items - } + receipt_items = {item.name: item.get(self.subcontract_data.order_field) for item in receipt_items} consumed_materials = self.__get_consumed_items(doctype, receipt_items.keys()) if return_consumed_items: @@ -370,9 +371,7 @@ def __get_materials_from_bom(self, item_code, bom_no, exploded_item=0): [doctype, "sourced_by_supplier", "=", 0], ] - return ( - frappe.get_all("BOM", fields=fields, filters=filters, order_by=f"`tab{doctype}`.`idx`") or [] - ) + return frappe.get_all("BOM", fields=fields, filters=filters, order_by=f"`tab{doctype}`.`idx`") or [] def __update_reserve_warehouse(self, row, item): if self.doctype == self.subcontract_data.order_doctype: @@ -809,7 +808,8 @@ def update_requested_qty(self): if mr_obj.status in ["Stopped", "Cancelled"]: frappe.throw( - _("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError + _("Material Request {0} is cancelled or stopped").format(mr), + frappe.InvalidStatusError, ) mr_obj.update_requested_qty(mr_item_rows) @@ -892,8 +892,10 @@ def make_rm_stock_entry( for fg_item_code in fg_item_code_list: for rm_item in rm_items: - - if rm_item.get("main_item_code") == fg_item_code or rm_item.get("item_code") == fg_item_code: + if ( + rm_item.get("main_item_code") == fg_item_code + or rm_item.get("item_code") == fg_item_code + ): rm_item_code = rm_item.get("rm_item_code") items_dict = { @@ -904,13 +906,16 @@ def make_rm_stock_entry( "description": item_wh.get(rm_item_code, {}).get("description", ""), "qty": rm_item.get("qty") or max(rm_item.get("required_qty") - rm_item.get("total_supplied_qty"), 0), - "from_warehouse": rm_item.get("warehouse") or rm_item.get("reserve_warehouse"), + "from_warehouse": rm_item.get("warehouse") + or rm_item.get("reserve_warehouse"), "to_warehouse": subcontract_order.supplier_warehouse, "stock_uom": rm_item.get("stock_uom"), "serial_no": rm_item.get("serial_no"), "batch_no": rm_item.get("batch_no"), "main_item_code": fg_item_code, - "allow_alternative_item": item_wh.get(rm_item_code, {}).get("allow_alternative_item"), + "allow_alternative_item": item_wh.get(rm_item_code, {}).get( + "allow_alternative_item" + ), } } @@ -924,9 +929,7 @@ def make_rm_stock_entry( frappe.throw(_("No Items selected for transfer.")) -def add_items_in_ste( - ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_detail", batch_no=None -): +def add_items_in_ste(ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_detail", batch_no=None): item = ste_doc.append("items", row.item_details) rm_detail = list(set(row.get(f"{rm_detail_field}s")).intersection(rm_details)) @@ -971,7 +974,7 @@ def make_return_stock_entry_for_subcontract( ste_doc.company = order_doc.company ste_doc.is_return = 1 - for key, value in available_materials.items(): + for _key, value in available_materials.items(): if not value.qty: continue @@ -989,9 +992,7 @@ def make_return_stock_entry_for_subcontract( @frappe.whitelist() -def get_materials_from_supplier( - subcontract_order, rm_details, order_doctype="Subcontracting Order" -): +def get_materials_from_supplier(subcontract_order, rm_details, order_doctype="Subcontracting Order"): if isinstance(rm_details, str): rm_details = json.loads(rm_details) @@ -1005,6 +1006,4 @@ def get_materials_from_supplier( _("Materials are already received against the {0} {1}").format(order_doctype, subcontract_order) ) - return make_return_stock_entry_for_subcontract( - doc.available_materials, doc, rm_details, order_doctype - ) + return make_return_stock_entry_for_subcontract(doc.available_materials, doc, rm_details, order_doctype) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 2881c15a14df..e92356e30a81 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -21,7 +21,7 @@ from erpnext.utilities.regional import temporary_flag -class calculate_taxes_and_totals(object): +class calculate_taxes_and_totals: def __init__(self, doc: Document): self.doc = doc frappe.flags.round_off_applicable_accounts = [] @@ -155,7 +155,8 @@ def calculate_item_values(self): elif item.price_list_rate: if not item.rate or (item.pricing_rules and item.discount_percentage > 0): item.rate = flt( - item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate") + item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), + item.precision("rate"), ) item.discount_amount = item.price_list_rate * (item.discount_percentage / 100.0) @@ -176,7 +177,8 @@ def calculate_item_values(self): item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item) if flt(item.rate_with_margin) > 0: item.rate = flt( - item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate") + item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), + item.precision("rate"), ) if item.discount_amount and not item.discount_percentage: @@ -192,7 +194,9 @@ def calculate_item_values(self): item.net_rate = item.rate if ( - not item.qty and self.doc.get("is_return") and self.doc.get("doctype") != "Purchase Receipt" + not item.qty + and self.doc.get("is_return") + and self.doc.get("doctype") != "Purchase Receipt" ): item.amount = flt(-1 * item.rate, item.precision("amount")) elif not item.qty and self.doc.get("is_debit_note"): @@ -278,7 +282,9 @@ def determine_exclusive_rate(self): item.net_amount = flt(amount / (1 + cumulated_tax_fraction)) item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) - item.discount_percentage = flt(item.discount_percentage, item.precision("discount_percentage")) + item.discount_percentage = flt( + item.discount_percentage, item.precision("discount_percentage") + ) self._set_in_company_currency(item, ["net_rate", "net_amount"]) @@ -339,7 +345,6 @@ def calculate_net_total(self): self.doc.round_floats_in(self.doc, ["total", "base_total", "net_total", "base_net_total"]) def calculate_shipping_charges(self): - # Do not apply shipping rule for POS if self.doc.get("is_pos"): return @@ -351,9 +356,7 @@ def calculate_shipping_charges(self): self._calculate() def calculate_taxes(self): - rounding_adjustment_computed = self.doc.get("is_consolidated") and self.doc.get( - "rounding_adjustment" - ) + rounding_adjustment_computed = self.doc.get("is_consolidated") and self.doc.get("rounding_adjustment") if not rounding_adjustment_computed: self.doc.rounding_adjustment = 0 @@ -391,7 +394,9 @@ def calculate_taxes(self): # set tax after discount tax.tax_amount_after_discount_amount += current_tax_amount - current_tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(current_tax_amount, tax) + current_tax_amount = self.get_tax_amount_if_for_valuation_or_deduction( + current_tax_amount, tax + ) # note: grand_total_for_current_item contains the contribution of # item's amount, previously applied tax and the current tax on that item @@ -455,9 +460,7 @@ def get_current_tax_amount(self, item, tax, item_tax_map): if tax.charge_type == "Actual": # distribute the tax amount proportionally to each item row actual = flt(tax.tax_amount, tax.precision("tax_amount")) - current_tax_amount = ( - item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0 - ) + current_tax_amount = item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0 elif tax.charge_type == "On Net Total": current_tax_amount = (tax_rate / 100.0) * item.net_amount @@ -571,9 +574,7 @@ def calculate_totals(self): else self.doc.base_net_total ) - self._set_in_company_currency( - self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"] - ) + self._set_in_company_currency(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]) self.doc.round_floats_in(self.doc, ["grand_total", "base_grand_total"]) @@ -627,12 +628,11 @@ def apply_discount_amount(self): frappe.throw(_("Please select Apply Discount On")) self.doc.base_discount_amount = flt( - self.doc.discount_amount * self.doc.conversion_rate, self.doc.precision("base_discount_amount") + self.doc.discount_amount * self.doc.conversion_rate, + self.doc.precision("base_discount_amount"), ) - if self.doc.apply_discount_on == "Grand Total" and self.doc.get( - "is_cash_or_non_trade_discount" - ): + if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"): self.discount_amount_applied = True return @@ -657,12 +657,17 @@ def apply_discount_amount(self): or total_for_discount_amount == self.doc.net_total ) and i == len(self._items) - 1: discount_amount_loss = flt( - self.doc.net_total - net_total - self.doc.discount_amount, self.doc.precision("net_total") + self.doc.net_total - net_total - self.doc.discount_amount, + self.doc.precision("net_total"), ) - item.net_amount = flt(item.net_amount + discount_amount_loss, item.precision("net_amount")) + item.net_amount = flt( + item.net_amount + discount_amount_loss, item.precision("net_amount") + ) - item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0 + item.net_rate = ( + flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0 + ) self._set_in_company_currency(item, ["net_rate", "net_amount"]) @@ -818,7 +823,6 @@ def calculate_outstanding_amount(self): self.calculate_paid_amount() def calculate_paid_amount(self): - paid_amount = base_paid_amount = 0.0 if self.doc.is_pos: @@ -918,7 +922,9 @@ def set_total_amount_to_default_mop(self, total_amount_to_pay): total_paid_amount = 0 for payment in self.doc.get("payments"): total_paid_amount += ( - payment.amount if self.doc.party_account_currency == self.doc.currency else payment.base_amount + payment.amount + if self.doc.party_account_currency == self.doc.currency + else payment.base_amount ) pending_amount = total_amount_to_pay - total_paid_amount @@ -992,7 +998,7 @@ def update_itemised_tax_data(doc): @erpnext.allow_regional def get_itemised_tax_breakup_header(item_doctype, tax_accounts): - return [_("Item"), _("Taxable Amount")] + tax_accounts + return [_("Item"), _("Taxable Amount"), *tax_accounts] @erpnext.allow_regional @@ -1060,7 +1066,7 @@ def get_rounded_tax_amount(itemised_tax, precision): row["tax_amount"] = flt(row["tax_amount"], precision) -class init_landed_taxes_and_totals(object): +class init_landed_taxes_and_totals: def __init__(self, doc): self.doc = doc self.tax_field = "taxes" if self.doc.doctype == "Landed Cost Voucher" else "additional_costs" diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index e348d296cd71..5bfed8cddeb5 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -1,18 +1,15 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -import unittest import frappe from frappe import qb from frappe.query_builder.functions import Sum -from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import add_days, flt, getdate, nowdate +from frappe.tests.utils import FrappeTestCase +from frappe.utils import add_days, getdate, nowdate -from erpnext import get_default_cost_center from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry -from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.party import get_party_account from erpnext.stock.doctype.item.test_item import create_item @@ -174,9 +171,7 @@ def create_sales_invoice( ) return sinv - def create_payment_entry( - self, amount=1, source_exc_rate=75, posting_date=nowdate(), customer=None - ): + def create_payment_entry(self, amount=1, source_exc_rate=75, posting_date=nowdate(), customer=None): """ Helper function to populate default values in payment entry """ @@ -294,9 +289,7 @@ def assert_ledger_outstanding( .run(as_dict=True)[0] ) self.assertEqual(outstanding, current_outstanding.outstanding) - self.assertEqual( - outstanding_in_account_currency, current_outstanding.outstanding_in_account_currency - ) + self.assertEqual(outstanding_in_account_currency, current_outstanding.outstanding_in_account_currency) def test_10_payment_against_sales_invoice(self): # Sales Invoice in Foreign Currency @@ -402,7 +395,6 @@ def test_12_partial_advance_and_payment_for_sales_invoice(self): adv.reload() # sales invoice with advance(partial amount) - rate = 80 rate_in_account_currency = 1 si = self.create_sales_invoice( qty=2, conversion_rate=80, rate=rate_in_account_currency, do_not_submit=True @@ -789,7 +781,9 @@ def test_21_advance_journal_against_sales_invoice(self): self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0) # Exchange Gain/Loss Journal should've been created. - exc_je_for_si = [x for x in self.get_journals_for(si.doctype, si.name) if x.parent != adv.name] + exc_je_for_si = [ + x for x in self.get_journals_for(si.doctype, si.name) if x.parent != adv.name + ] exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) self.assertNotEqual(exc_je_for_si, []) self.assertEqual(len(exc_je_for_si), 1) @@ -1254,7 +1248,9 @@ def test_42_cost_center_from_cr_note(self): with self.subTest(x=x): self.assertEqual( [self.cost_center, self.cost_center], - frappe.db.get_all("Journal Entry Account", filters={"parent": x.parent}, pluck="cost_center"), + frappe.db.get_all( + "Journal Entry Account", filters={"parent": x.parent}, pluck="cost_center" + ), ) frappe.db.set_value("Company", self.company, "cost_center", cc) @@ -1419,14 +1415,15 @@ def test_91_cr_note_should_inherit_dimension(self): with self.subTest(x=x): self.assertEqual( [cr_note.department, cr_note.department], - frappe.db.get_all("Journal Entry Account", filters={"parent": x.parent}, pluck="department"), + frappe.db.get_all( + "Journal Entry Account", filters={"parent": x.parent}, pluck="department" + ), ) self.disable_dimensions() def test_92_dimension_inhertiance_exc_gain_loss(self): # Sales Invoice in Foreign Currency self.setup_dimensions() - rate = 80 rate_in_account_currency = 1 dpt = "Research & Development" diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py index 919bcdab6606..9dbcf6cafd21 100644 --- a/erpnext/controllers/tests/test_mapper.py +++ b/erpnext/controllers/tests/test_mapper.py @@ -29,7 +29,6 @@ def test_map_docs(self): self.assertEqual(set(d for d in src_items), set(d.item_code for d in updated_so.items)) def make_quotation(self, item_list, customer): - qtn = frappe.get_doc( { "doctype": "Quotation", diff --git a/erpnext/controllers/tests/test_qty_based_taxes.py b/erpnext/controllers/tests/test_qty_based_taxes.py index 2e9dfd2faa08..e7896b57f237 100644 --- a/erpnext/controllers/tests/test_qty_based_taxes.py +++ b/erpnext/controllers/tests/test_qty_based_taxes.py @@ -25,7 +25,7 @@ def setUp(self): "account_name": uuid4(), "account_type": "Tax", "company": self.company.name, - "parent_account": "Duties and Taxes - {self.company.abbr}".format(self=self), + "parent_account": f"Duties and Taxes - {self.company.abbr}", } ).insert() self.item_group = frappe.get_doc( diff --git a/erpnext/controllers/tests/test_queries.py b/erpnext/controllers/tests/test_queries.py index 3a3bc1cd725a..904f75f64de7 100644 --- a/erpnext/controllers/tests/test_queries.py +++ b/erpnext/controllers/tests/test_queries.py @@ -7,13 +7,10 @@ def add_default_params(func, doctype): - return partial( - func, doctype=doctype, txt="", searchfield="name", start=0, page_len=20, filters=None - ) + return partial(func, doctype=doctype, txt="", searchfield="name", start=0, page_len=20, filters=None) class TestQueries(unittest.TestCase): - # All tests are based on doctype/test_records.json def assert_nested_in(self, item, container): diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py index 68af142afcb4..c7cda2dea988 100644 --- a/erpnext/controllers/tests/test_subcontracting_controller.py +++ b/erpnext/controllers/tests/test_subcontracting_controller.py @@ -423,7 +423,7 @@ def test_item_with_batch_based_on_bom(self): scr1.set_missing_values() scr1.submit() - for key, value in get_supplied_items(scr1).items(): + for _key, value in get_supplied_items(scr1).items(): self.assertEqual(value.qty, 4) scr2 = make_subcontracting_receipt(sco.name) @@ -434,7 +434,7 @@ def test_item_with_batch_based_on_bom(self): scr2.set_missing_values() scr2.submit() - for key, value in get_supplied_items(scr2).items(): + for _key, value in get_supplied_items(scr2).items(): self.assertEqual(value.qty, 4) scr3 = make_subcontracting_receipt(sco.name) @@ -444,7 +444,7 @@ def test_item_with_batch_based_on_bom(self): scr3.set_missing_values() scr3.submit() - for key, value in get_supplied_items(scr3).items(): + for _key, value in get_supplied_items(scr3).items(): self.assertEqual(value.qty, 2) def test_item_with_batch_based_on_material_transfer(self): @@ -729,7 +729,7 @@ def test_partial_transfer_batch_based_on_material_transfer(self): scr1.load_from_db() scr1.supplied_items[0].consumed_qty = 5 - scr1.supplied_items[0].batch_no = list(transferred_batch_no.keys())[0] + scr1.supplied_items[0].batch_no = next(iter(transferred_batch_no.keys())) scr1.save() scr1.submit() @@ -872,9 +872,7 @@ def make_stock_in_entry(**args): def update_item_details(child_row, details): details.qty += ( - child_row.get("qty") - if child_row.doctype == "Stock Entry Detail" - else child_row.get("consumed_qty") + child_row.get("qty") if child_row.doctype == "Stock Entry Detail" else child_row.get("consumed_qty") ) if child_row.serial_no: @@ -967,7 +965,9 @@ def make_raw_materials(): make_item(item, properties) -def make_service_item(item, properties={}): +def make_service_item(item, properties=None): + if properties is None: + properties = {} if not frappe.db.exists("Item", item): properties.update({"is_stock_item": 0}) make_item(item, properties) @@ -1015,9 +1015,7 @@ def make_bom_for_subcontracted_items(): def set_backflush_based_on(based_on): - frappe.db.set_value( - "Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", based_on - ) + frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", based_on) def get_subcontracting_order(**args): diff --git a/erpnext/controllers/tests/test_transaction_base.py b/erpnext/controllers/tests/test_transaction_base.py index 1471543f1b2a..ab5525a7f069 100644 --- a/erpnext/controllers/tests/test_transaction_base.py +++ b/erpnext/controllers/tests/test_transaction_base.py @@ -44,7 +44,10 @@ def test_reset_default_field_value_in_mfg_stock_entry(self): item_code="_Test Item", qty=1, basic_rate=200, s_warehouse="_Test Warehouse - _TC" ), frappe._dict( - item_code="_Test FG Item", qty=4, t_warehouse="_Test Warehouse 1 - _TC", is_finished_item=1 + item_code="_Test FG Item", + qty=4, + t_warehouse="_Test Warehouse 1 - _TC", + is_finished_item=1, ), ], ) diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index 1fb722e11235..18fe7767c5d6 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -100,12 +100,11 @@ def get_data(filters, conditions): else: inc = 1 data1 = frappe.db.sql( - """ select %s from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and %s between %s and %s and - t1.docstatus = 1 %s %s - group by %s - """ - % ( + """ select {} from `tab{}` t1, `tab{} Item` t2 {} + where t2.parent = t1.name and t1.company = {} and {} between {} and {} and + t1.docstatus = 1 {} {} + group by {} + """.format( query_details, conditions["trans"], conditions["trans"], @@ -130,11 +129,10 @@ def get_data(filters, conditions): # to get distinct value of col specified by group_by in filter row = frappe.db.sql( - """select DISTINCT(%s) from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and %s between %s and %s - and t1.docstatus = 1 and %s = %s %s %s - """ - % ( + """select DISTINCT({}) from `tab{}` t1, `tab{} Item` t2 {} + where t2.parent = t1.name and t1.company = {} and {} between {} and {} + and t1.docstatus = 1 and {} = {} {} {} + """.format( sel_col, conditions["trans"], conditions["trans"], @@ -157,11 +155,10 @@ def get_data(filters, conditions): # get data for group_by filter row1 = frappe.db.sql( - """ select %s , %s from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and %s between %s and %s - and t1.docstatus = 1 and %s = %s and %s = %s %s %s - """ - % ( + """ select {} , {} from `tab{}` t1, `tab{} Item` t2 {} + where t2.parent = t1.name and t1.company = {} and {} between {} and {} + and t1.docstatus = 1 and {} = {} and {} = {} {} {} + """.format( sel_col, conditions["period_wise_select"], conditions["trans"], @@ -190,12 +187,11 @@ def get_data(filters, conditions): data.append(des) else: data = frappe.db.sql( - """ select %s from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and %s between %s and %s and - t1.docstatus = 1 %s %s - group by %s - """ - % ( + """ select {} from `tab{}` t1, `tab{} Item` t2 {} + where t2.parent = t1.name and t1.company = {} and {} between {} and {} and + t1.docstatus = 1 {} {} + group by {} + """.format( query_details, conditions["trans"], conditions["trans"], @@ -260,13 +256,13 @@ def get_period_wise_columns(bet_dates, period, pwc): def get_period_wise_query(bet_dates, trans_date, query_details): - query_details += """SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.stock_qty, NULL)), - SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.base_net_amount, NULL)), - """ % { - "trans_date": trans_date, - "sd": bet_dates[0], - "ed": bet_dates[1], - } + query_details += """SUM(IF(t1.{trans_date} BETWEEN '{sd}' AND '{ed}', t2.stock_qty, NULL)), + SUM(IF(t1.{trans_date} BETWEEN '{sd}' AND '{ed}', t2.base_net_amount, NULL)), + """.format( + trans_date=trans_date, + sd=bet_dates[0], + ed=bet_dates[1], + ) return query_details @@ -282,7 +278,7 @@ def get_period_date_ranges(period, fiscal_year=None, year_start_date=None): increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(period) period_date_ranges = [] - for i in range(1, 13, increment): + for _i in range(1, 13, increment): period_end_date = getdate(year_start_date) + relativedelta(months=increment, days=-1) if period_end_date > getdate(year_end_date): period_end_date = year_end_date @@ -331,9 +327,7 @@ def based_wise_columns_query(based_on, trans): "Territory:Link/Territory:120", ] based_on_details["based_on_select"] = "t1.customer_name, t1.territory, " - based_on_details["based_on_group_by"] = ( - "t1.party_name" if trans == "Quotation" else "t1.customer" - ) + based_on_details["based_on_group_by"] = "t1.party_name" if trans == "Quotation" else "t1.customer" based_on_details["addl_tables"] = "" elif based_on == "Customer Group": diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 7c3c38706dc8..22c68dd36320 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -81,9 +81,7 @@ def get_transaction_list( filters["docstatus"] = ["<", "2"] if doctype in ["Supplier Quotation", "Purchase Invoice"] else 1 if (user != "Guest" and is_website_user()) or doctype == "Request for Quotation": - parties_doctype = ( - "Request for Quotation Supplier" if doctype == "Request for Quotation" else doctype - ) + parties_doctype = "Request for Quotation Supplier" if doctype == "Request for Quotation" else doctype # find party for this contact customers, suppliers = get_customers_suppliers(parties_doctype, user) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index bd49bdc925c4..03ef9c9f2e09 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -178,7 +178,9 @@ def create_calendar_event(self): "starts_on": self.scheduled_time, "status": "Open", "type": "Public", - "send_reminder": frappe.db.get_single_value("Appointment Booking Settings", "email_reminders"), + "send_reminder": frappe.db.get_single_value( + "Appointment Booking Settings", "email_reminders" + ), "event_participants": [ dict(reference_doctype=self.appointment_with, reference_docname=self.party) ], @@ -231,9 +233,7 @@ def _get_agent_list_as_strings(): def _check_agent_availability(agent_email, scheduled_time): - appointemnts_at_scheduled_time = frappe.get_all( - "Appointment", filters={"scheduled_time": scheduled_time} - ) + appointemnts_at_scheduled_time = frappe.get_all("Appointment", filters={"scheduled_time": scheduled_time}) for appointment in appointemnts_at_scheduled_time: if appointment._assign == agent_email: return False 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 e43f4601e9cb..57e80f9abc88 100644 --- a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py +++ b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py @@ -19,13 +19,13 @@ def validate(self): def save(self): self.number_of_agents = len(self.agent_list) - super(AppointmentBookingSettings, self).save() + super().save() def validate_availability_of_slots(self): for record in self.availability_of_slots: from_time = datetime.datetime.strptime(self.min_date + record.from_time, self.format_string) to_time = datetime.datetime.strptime(self.min_date + record.to_time, self.format_string) - timedelta = to_time - from_time + to_time - from_time self.validate_from_and_to_time(from_time, to_time, record) self.duration_is_divisible(from_time, to_time) @@ -39,6 +39,4 @@ def validate_from_and_to_time(self, from_time, to_time, record): def duration_is_divisible(self, from_time, to_time): timedelta = to_time - from_time if timedelta.total_seconds() % (self.appointment_duration * 60): - frappe.throw( - _("The difference between from time and To Time must be a multiple of Appointment") - ) + frappe.throw(_("The difference between from time and To Time must be a multiple of Appointment")) diff --git a/erpnext/crm/doctype/contract/contract.py b/erpnext/crm/doctype/contract/contract.py index 1c2470b6e4e8..db23d570644d 100644 --- a/erpnext/crm/doctype/contract/contract.py +++ b/erpnext/crm/doctype/contract/contract.py @@ -13,12 +13,12 @@ def autoname(self): name = self.party_name if self.contract_template: - name += " - {} Agreement".format(self.contract_template) + name += f" - {self.contract_template} Agreement" # If identical, append contract name with the next number in the iteration if frappe.db.exists("Contract", name): - count = len(frappe.get_all("Contract", filters={"name": ["like", "%{}%".format(name)]})) - name = "{} - {}".format(name, count) + count = len(frappe.get_all("Contract", filters={"name": ["like", f"%{name}%"]})) + name = f"{name} - {count}" self.name = _(name) diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index cbef699ce617..3135bcff049c 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -19,7 +19,7 @@ class Lead(SellingController, CRMNote): def get_feed(self): - return "{0}: {1}".format(_(self.status), self.lead_name) + return f"{_(self.status)}: {self.lead_name}" def onload(self): customer = frappe.db.get_value("Customer", {"lead_name": self.name}) @@ -122,9 +122,7 @@ def link_to_contact(self): self.contact_doc.save() def update_prospect(self): - lead_row_name = frappe.db.get_value( - "Prospect Lead", filters={"lead": self.name}, fieldname="name" - ) + lead_row_name = frappe.db.get_value("Prospect Lead", filters={"lead": self.name}, fieldname="name") if lead_row_name: lead_row = frappe.get_doc("Prospect Lead", lead_row_name) lead_row.update( @@ -174,9 +172,7 @@ def has_quotation(self): ) def has_lost_quotation(self): - return frappe.db.get_value( - "Quotation", {"party_name": self.name, "docstatus": 1, "status": "Lost"} - ) + return frappe.db.get_value("Quotation", {"party_name": self.name, "docstatus": 1, "status": "Lost"}) @frappe.whitelist() def create_prospect_and_contact(self, data): @@ -448,8 +444,8 @@ def get_lead_with_phone_number(number): leads = frappe.get_all( "Lead", or_filters={ - "phone": ["like", "%{}".format(number)], - "mobile_no": ["like", "%{}".format(number)], + "phone": ["like", f"%{number}"], + "mobile_no": ["like", f"%{number}"], }, limit=1, order_by="creation DESC", @@ -476,9 +472,7 @@ def add_lead_to_prospect(lead, prospect): link_open_events("Lead", lead, prospect) frappe.msgprint( - _("Lead {0} has been added to prospect {1}.").format( - frappe.bold(lead), frappe.bold(prospect.name) - ), + _("Lead {0} has been added to prospect {1}.").format(frappe.bold(lead), frappe.bold(prospect.name)), title=_("Lead -> Prospect"), indicator="green", ) diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index 8fe688de46db..bab9947b3332 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -134,9 +134,7 @@ def test_opportunity_from_lead(self): self.assertEqual(event.event_participants[1].reference_docname, opportunity.name) self.assertTrue( - frappe.db.get_value( - "ToDo", {"reference_type": "Opportunity", "reference_name": opportunity.name} - ) + frappe.db.get_value("ToDo", {"reference_type": "Opportunity", "reference_name": opportunity.name}) ) def test_copy_events_from_lead_to_prospect(self): @@ -194,7 +192,7 @@ def make_lead(**args): "doctype": "Lead", "first_name": args.first_name or "_Test", "last_name": args.last_name or "Lead", - "email_id": args.email_id or "new_lead_{}@example.com".format(random_string(5)), + "email_id": args.email_id or f"new_lead_{random_string(5)}@example.com", "company_name": args.company_name or "_Test Company", } ).insert() diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py index 64b3a017b46b..1b535e14c461 100644 --- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py +++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py @@ -19,14 +19,14 @@ def get_authorization_url(self): { "response_type": "code", "client_id": self.consumer_key, - "redirect_uri": "{0}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format( + "redirect_uri": "{}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format( frappe.utils.get_url() ), "scope": "r_emailaddress w_organization_social r_basicprofile r_liteprofile r_organization_social rw_organization_admin w_member_social", } ) - url = "https://www.linkedin.com/oauth/v2/authorization?{}".format(params) + url = f"https://www.linkedin.com/oauth/v2/authorization?{params}" return url @@ -37,7 +37,7 @@ def get_access_token(self, code): "code": code, "client_id": self.consumer_key, "client_secret": self.get_password(fieldname="consumer_secret"), - "redirect_uri": "{0}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format( + "redirect_uri": "{}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format( frappe.utils.get_url() ), } @@ -80,7 +80,7 @@ def upload_image(self, media): body = { "registerUploadRequest": { "recipes": ["urn:li:digitalmediaRecipe:feedshare-image"], - "owner": "urn:li:organization:{0}".format(self.company_id), + "owner": f"urn:li:organization:{self.company_id}", "serviceRelationships": [ {"relationshipType": "OWNER", "identifier": "urn:li:userGeneratedContent"} ], @@ -100,7 +100,7 @@ def upload_image(self, media): if response.status_code < 200 and response.status_code > 299: frappe.throw( _("Error While Uploading Image"), - title="{0} {1}".format(response.status_code, response.reason), + title=f"{response.status_code} {response.reason}", ) return None return asset @@ -115,7 +115,7 @@ def post_text(self, text, title, media_id=None): body = { "distribution": {"linkedInDistributionTarget": {}}, - "owner": "urn:li:organization:{0}".format(self.company_id), + "owner": f"urn:li:organization:{self.company_id}", "subject": title, "text": {"text": text}, } @@ -136,13 +136,13 @@ def http_post(self, url, headers=None, body=None, data=None): if response.status_code not in [201, 200]: raise - except Exception as e: + except Exception: self.api_error(response) return response def get_headers(self): - return {"Authorization": "Bearer {}".format(self.access_token)} + return {"Authorization": f"Bearer {self.access_token}"} def get_reference_url(self, text): import re @@ -155,7 +155,7 @@ def get_reference_url(self, text): def delete_post(self, post_id): try: response = requests.delete( - url="https://api.linkedin.com/v2/shares/urn:li:share:{0}".format(post_id), + url=f"https://api.linkedin.com/v2/shares/urn:li:share:{post_id}", headers=self.get_headers(), ) if response.status_code != 200: @@ -164,7 +164,7 @@ def delete_post(self, post_id): self.api_error(response) def get_post(self, post_id): - url = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:{0}&shares[0]=urn:li:share:{1}".format( + url = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:{}&shares[0]=urn:li:share:{}".format( self.company_id, post_id ) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 2a8d65f48666..a0301f9ea0a4 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -304,9 +304,7 @@ def set_missing_values(source, target): quotation.conversion_rate = exchange_rate # get default taxes - taxes = get_default_taxes_and_charges( - "Sales Taxes and Charges Template", company=quotation.company - ) + taxes = get_default_taxes_and_charges("Sales Taxes and Charges Template", company=quotation.company) if taxes.get("taxes"): quotation.update(taxes) @@ -412,9 +410,7 @@ def set_multiple_status(names, status): def auto_close_opportunity(): """auto close the `Replied` Opportunities after 7 days""" - auto_close_after_days = ( - frappe.db.get_single_value("CRM Settings", "close_opportunity_after_days") or 15 - ) + auto_close_after_days = frappe.db.get_single_value("CRM Settings", "close_opportunity_after_days") or 15 table = frappe.qb.DocType("Opportunity") opportunities = ( diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py index 1ff3267e7196..79aca1b0033a 100644 --- a/erpnext/crm/doctype/opportunity/test_opportunity.py +++ b/erpnext/crm/doctype/opportunity/test_opportunity.py @@ -4,7 +4,7 @@ import unittest import frappe -from frappe.utils import add_days, now_datetime, random_string, today +from frappe.utils import now_datetime, random_string, today from erpnext.crm.doctype.lead.lead import make_customer from erpnext.crm.doctype.lead.test_lead import make_lead @@ -32,9 +32,7 @@ def test_make_new_lead_if_required(self): self.assertTrue(opp_doc.party_name) self.assertEqual(opp_doc.opportunity_from, "Lead") - self.assertEqual( - frappe.db.get_value("Lead", opp_doc.party_name, "email_id"), opp_doc.contact_email - ) + self.assertEqual(frappe.db.get_value("Lead", opp_doc.party_name, "email_id"), opp_doc.contact_email) # create new customer and create new contact against 'new.opportunity@example.com' customer = make_customer(opp_doc.party_name).insert(ignore_permissions=True) @@ -53,9 +51,7 @@ def test_opportunity_item(self): self.assertEqual(opportunity_doc.total, 2200) def test_carry_forward_of_email_and_comments(self): - frappe.db.set_value( - "CRM Settings", "CRM Settings", "carry_forward_communication_and_comments", 1 - ) + frappe.db.set_value("CRM Settings", "CRM Settings", "carry_forward_communication_and_comments", 1) lead_doc = make_lead() lead_doc.add_comment("Comment", text="Test Comment 1") lead_doc.add_comment("Comment", text="Test Comment 2") @@ -66,9 +62,7 @@ def test_carry_forward_of_email_and_comments(self): opportunity_comment_count = frappe.db.count( "Comment", {"reference_doctype": opp_doc.doctype, "reference_name": opp_doc.name} ) - opportunity_communication_count = len( - get_linked_communication_list(opp_doc.doctype, opp_doc.name) - ) + opportunity_communication_count = len(get_linked_communication_list(opp_doc.doctype, opp_doc.name)) self.assertEqual(opportunity_comment_count, 2) self.assertEqual(opportunity_communication_count, 2) @@ -79,7 +73,7 @@ def test_carry_forward_of_email_and_comments(self): def make_opportunity_from_lead(): - new_lead_email_id = "new{}@example.com".format(random_string(5)) + new_lead_email_id = f"new{random_string(5)}@example.com" args = { "doctype": "Opportunity", "contact_email": new_lead_email_id, @@ -128,9 +122,7 @@ def make_opportunity(**args): return opp_doc -def create_communication( - reference_doctype, reference_name, sender, sent_or_received=None, creation=None -): +def create_communication(reference_doctype, reference_name, sender, sent_or_received=None, creation=None): communication = frappe.get_doc( { "doctype": "Communication", diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index 874f84ca843f..c3930ee6c93d 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -34,7 +34,7 @@ def make_prospect(**args): prospect_doc = frappe.get_doc( { "doctype": "Prospect", - "company_name": args.company_name or "_Test Company {}".format(random_string(3)), + "company_name": args.company_name or f"_Test Company {random_string(3)}", } ).insert() diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.py b/erpnext/crm/doctype/social_media_post/social_media_post.py index 55db29a627a3..5822f3cc51ac 100644 --- a/erpnext/crm/doctype/social_media_post/social_media_post.py +++ b/erpnext/crm/doctype/social_media_post/social_media_post.py @@ -26,7 +26,7 @@ def validate(self): def submit(self): if self.scheduled_time: self.post_status = "Scheduled" - super(SocialMediaPost, self).submit() + super().submit() def on_cancel(self): self.db_set("post_status", "Cancelled") diff --git a/erpnext/crm/doctype/twitter_settings/twitter_settings.py b/erpnext/crm/doctype/twitter_settings/twitter_settings.py index 42874ddeea58..c3a0177c4877 100644 --- a/erpnext/crm/doctype/twitter_settings/twitter_settings.py +++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.py @@ -16,10 +16,8 @@ class TwitterSettings(Document): @frappe.whitelist() def get_authorize_url(self): - callback_url = ( - "{0}/api/method/erpnext.crm.doctype.twitter_settings.twitter_settings.callback?".format( - frappe.utils.get_url() - ) + callback_url = "{}/api/method/erpnext.crm.doctype.twitter_settings.twitter_settings.callback?".format( + frappe.utils.get_url() ) auth = tweepy.OAuthHandler( self.consumer_key, self.get_password(fieldname="consumer_secret"), callback_url @@ -27,10 +25,12 @@ def get_authorize_url(self): try: redirect_url = auth.get_authorization_url() return redirect_url - except tweepy.TweepError as e: + except tweepy.TweepError: frappe.msgprint(_("Error! Failed to get request token.")) frappe.throw( - _("Invalid {0} or {1}").format(frappe.bold("Consumer Key"), frappe.bold("Consumer Secret Key")) + _("Invalid {0} or {1}").format( + frappe.bold("Consumer Key"), frappe.bold("Consumer Secret Key") + ) ) def get_access_token(self, oauth_token, oauth_verifier): @@ -59,7 +59,7 @@ def get_access_token(self, oauth_token, oauth_verifier): frappe.local.response["type"] = "redirect" frappe.local.response["location"] = get_url_to_form("Twitter Settings", "Twitter Settings") - except TweepError as e: + except TweepError: frappe.msgprint(_("Error! Failed to get access token.")) frappe.throw(_("Invalid Consumer Key or Consumer Secret Key")) diff --git a/erpnext/crm/doctype/utils.py b/erpnext/crm/doctype/utils.py index 6bcfcb7e6260..cacc5a166073 100644 --- a/erpnext/crm/doctype/utils.py +++ b/erpnext/crm/doctype/utils.py @@ -3,7 +3,6 @@ @frappe.whitelist() def get_last_interaction(contact=None, lead=None): - if not contact and not lead: return @@ -23,16 +22,14 @@ def get_last_interaction(contact=None, lead=None): # remove extra appended 'OR' query_condition = query_condition[:-2] last_communication = frappe.db.sql( - """ + f""" SELECT `name`, `content` FROM `tabCommunication` WHERE `sent_or_received`='Received' - AND ({}) + AND ({query_condition}) ORDER BY `modified` LIMIT 1 - """.format( - query_condition - ), + """, values, as_dict=1, ) # nosec diff --git a/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py b/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py index be7f5ca29b3c..6d01bd289d3b 100644 --- a/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py +++ b/erpnext/crm/report/campaign_efficiency/campaign_efficiency.py @@ -33,13 +33,11 @@ def get_lead_data(filters, based_on): conditions = get_filter_conditions(filters) lead_details = frappe.db.sql( - """ + f""" select {based_on_field}, name from `tabLead` where {based_on_field} is not null and {based_on_field} != '' {conditions} - """.format( - based_on_field=based_on_field, conditions=conditions - ), + """, filters, as_dict=1, ) @@ -82,9 +80,7 @@ def get_lead_quotation_count(leads): where quotation_to = 'Lead' and party_name in (%s)""" % ", ".join(["%s"] * len(leads)), tuple(leads), - )[0][ - 0 - ] # nosec + )[0][0] # nosec def get_lead_opp_count(leads): diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.py b/erpnext/crm/report/lost_opportunity/lost_opportunity.py index b37cfa449fee..eb09711667a0 100644 --- a/erpnext/crm/report/lost_opportunity/lost_opportunity.py +++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.py @@ -67,7 +67,7 @@ def get_columns(): def get_data(filters): return frappe.db.sql( - """ + f""" SELECT `tabOpportunity`.name, `tabOpportunity`.opportunity_from, @@ -79,17 +79,15 @@ def get_data(filters): `tabOpportunity`.territory FROM `tabOpportunity` - {join} + {get_join(filters)} WHERE `tabOpportunity`.status = 'Lost' and `tabOpportunity`.company = %(company)s AND DATE(`tabOpportunity`.modified) BETWEEN %(from_date)s AND %(to_date)s - {conditions} + {get_conditions(filters)} GROUP BY `tabOpportunity`.name ORDER BY - `tabOpportunity`.creation asc """.format( - conditions=get_conditions(filters), join=get_join(filters) - ), + `tabOpportunity`.creation asc """, filters, as_dict=1, ) @@ -119,9 +117,7 @@ def get_join(filters): join = """JOIN `tabOpportunity Lost Reason Detail` ON `tabOpportunity Lost Reason Detail`.parenttype = 'Opportunity' and `tabOpportunity Lost Reason Detail`.parent = `tabOpportunity`.name and - `tabOpportunity Lost Reason Detail`.lost_reason = '{0}' - """.format( - filters.get("lost_reason") - ) + `tabOpportunity Lost Reason Detail`.lost_reason = '{}' + """.format(filters.get("lost_reason")) return join diff --git a/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.py b/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.py index 809311777b71..5a36c9997478 100644 --- a/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.py +++ b/erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.py @@ -14,7 +14,7 @@ def execute(filters=None): return OpportunitySummaryBySalesStage(filters).run() -class OpportunitySummaryBySalesStage(object): +class OpportunitySummaryBySalesStage: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) @@ -199,7 +199,6 @@ def get_conditions(self): return filters def get_chart_data(self): - labels = [] datasets = [] values = [0] * len(self.sales_stage_list) diff --git a/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py b/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py index 50c42efe3c53..39b49b20f510 100644 --- a/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py +++ b/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py @@ -62,9 +62,7 @@ def get_data(filters): lead_details = [] lead_filters = get_lead_filters(filters) - for lead in frappe.get_all( - "Lead", fields=["name", "lead_name", "company_name"], filters=lead_filters - ): + for lead in frappe.get_all("Lead", fields=["name", "lead_name", "company_name"], filters=lead_filters): data = frappe.db.sql( """ select @@ -90,7 +88,7 @@ def get_data(filters): ) for lead_info in data: - lead_data = [lead.name, lead.lead_name, lead.company_name] + list(lead_info) + lead_data = [lead.name, lead.lead_name, lead.company_name, *list(lead_info)] lead_details.append(lead_data) return lead_details diff --git a/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.py b/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.py index 4f7436ff9e4c..9cc69d24a2b1 100644 --- a/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.py +++ b/erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.py @@ -17,7 +17,7 @@ def execute(filters=None): return SalesPipelineAnalytics(filters).run() -class SalesPipelineAnalytics(object): +class SalesPipelineAnalytics: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) @@ -98,7 +98,7 @@ def get_data(self): "Opportunity", filters=self.get_conditions(), fields=[self.based_on, self.data_based_on, self.duration], - group_by="{},{}".format(self.group_by_based_on, self.group_by_period), + group_by=f"{self.group_by_based_on},{self.group_by_period}", order_by=self.group_by_period, ) @@ -230,7 +230,7 @@ def get_month_list(self): current_date = date.today() month_number = date.today().month - for month in range(month_number, 13): + for _month in range(month_number, 13): month_list.append(current_date.strftime("%B")) current_date = current_date + relativedelta(months=1) diff --git a/erpnext/crm/utils.py b/erpnext/crm/utils.py index 737452021c00..c543c387c03a 100644 --- a/erpnext/crm/utils.py +++ b/erpnext/crm/utils.py @@ -94,9 +94,7 @@ def get_linked_prospect(reference_doctype, reference_name): "Opportunity", reference_name, ["opportunity_from", "party_name"] ) if opportunity_from == "Lead": - prospect = frappe.db.get_value( - "Prospect Opportunity", {"opportunity": reference_name}, "parent" - ) + prospect = frappe.db.get_value("Prospect Opportunity", {"opportunity": reference_name}, "parent") if opportunity_from == "Prospect": prospect = party_name diff --git a/erpnext/e_commerce/api.py b/erpnext/e_commerce/api.py index bfada0faa7a9..e2cccda2ba66 100644 --- a/erpnext/e_commerce/api.py +++ b/erpnext/e_commerce/api.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py index c27d29a62cd6..14798e0d3cdd 100644 --- a/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py +++ b/erpnext/e_commerce/doctype/e_commerce_settings/e_commerce_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/doctype/item_review/item_review.py b/erpnext/e_commerce/doctype/item_review/item_review.py index 3e540e38853f..5fe7d4d8fdb1 100644 --- a/erpnext/e_commerce/doctype/item_review/item_review.py +++ b/erpnext/e_commerce/doctype/item_review/item_review.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/doctype/item_review/test_item_review.py b/erpnext/e_commerce/doctype/item_review/test_item_review.py index 6147a9153e62..c3f76623c9cc 100644 --- a/erpnext/e_commerce/doctype/item_review/test_item_review.py +++ b/erpnext/e_commerce/doctype/item_review/test_item_review.py @@ -1,7 +1,5 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.core.doctype.user_permission.test_user_permission import create_user diff --git a/erpnext/e_commerce/doctype/website_item/test_website_item.py b/erpnext/e_commerce/doctype/website_item/test_website_item.py index 8dffb4364e11..86ca1f2cb61b 100644 --- a/erpnext/e_commerce/doctype/website_item/test_website_item.py +++ b/erpnext/e_commerce/doctype/website_item/test_website_item.py @@ -1,8 +1,6 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe @@ -347,9 +345,7 @@ def test_website_item_stock_when_in_stock(self): ) # stock up item - stock_entry = make_stock_entry( - item_code=item_code, target="_Test Warehouse - _TC", qty=2, rate=100 - ) + stock_entry = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=2, rate=100) # check if stock details are fetched and item is in stock with warehouse set data = get_product_info_for_website(item_code, skip_quotation_creation=True) @@ -429,9 +425,7 @@ def test_recommended_item_for_guest_user(self): web_item = create_regular_web_item(item_code) # price visible to guests - setup_e_commerce_settings( - {"enable_recommendations": 1, "show_price": 1, "hide_price_for_guest": 0} - ) + setup_e_commerce_settings({"enable_recommendations": 1, "show_price": 1, "hide_price_for_guest": 0}) # create recommended web item and price for it recommended_web_item = create_regular_web_item("Test Mobile Phone 1") diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py index 81b8ecab48e8..f7637cb3553e 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.py +++ b/erpnext/e_commerce/doctype/website_item/website_item.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt import json -from typing import TYPE_CHECKING, List, Union +from typing import TYPE_CHECKING, Union if TYPE_CHECKING: from erpnext.stock.doctype.item.item import Item @@ -45,10 +44,10 @@ def autoname(self): self.name = make_autoname(naming_series, doc=self) def onload(self): - super(WebsiteItem, self).onload() + super().onload() def validate(self): - super(WebsiteItem, self).validate() + super().validate() if not self.item_code: frappe.throw(_("Item Code is required"), title=_("Mandatory")) @@ -78,7 +77,7 @@ def on_update(self): self.update_template_item() def on_trash(self): - super(WebsiteItem, self).on_trash() + super().on_trash() delete_item_from_index(self) self.publish_unpublish_desk_item(publish=False) @@ -197,7 +196,7 @@ def make_thumbnail(self): } ).save() - except IOError: + except OSError: self.website_image = None if file_doc: @@ -234,9 +233,7 @@ def get_context(self, context): context.reviews = context.reviews[:4] context.wished = False - if frappe.db.exists( - "Wishlist Item", {"item_code": self.item_code, "parent": frappe.session.user} - ): + if frappe.db.exists("Wishlist Item", {"item_code": self.item_code, "parent": frappe.session.user}): context.wished = True context.user_is_customer = check_if_user_is_customer() @@ -256,9 +253,7 @@ def set_selected_attributes(self, variants, context, attribute_values_available) ) # make an attribute-value map for easier access in templates - variant.attribute_map = frappe._dict( - {attr.attribute: attr.value for attr in variant.attributes} - ) + variant.attribute_map = frappe._dict({attr.attribute: attr.value for attr in variant.attributes}) for attr in variant.attributes: values = attribute_values_available.setdefault(attr.attribute, []) @@ -283,7 +278,6 @@ def set_attribute_values(self, attributes, context, attribute_values_available): filters={"parent": attr.attribute}, order_by="idx asc", ): - if attr_value.attribute_value in attribute_values_available.get(attr.attribute, []): values.append(attr_value.attribute_value) @@ -311,9 +305,7 @@ def set_metatags(self, context): def set_shopping_cart_data(self, context): from erpnext.e_commerce.shopping_cart.product_info import get_product_info_for_website - context.shopping_cart = get_product_info_for_website( - self.item_code, skip_quotation_creation=True - ) + context.shopping_cart = get_product_info_for_website(self.item_code, skip_quotation_creation=True) @frappe.whitelist() def copy_specification_from_item_group(self): @@ -425,7 +417,7 @@ def check_if_user_is_customer(user=None): @frappe.whitelist() -def make_website_item(doc: "Item", save: bool = True) -> Union["WebsiteItem", List[str]]: +def make_website_item(doc: "Item", save: bool = True) -> Union["WebsiteItem", list[str]]: "Make Website Item from Item. Used via Form UI or patch." if not doc: diff --git a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py index 91148b8b0480..ebe016cfab2f 100644 --- a/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py +++ b/erpnext/e_commerce/doctype/website_item_tabbed_section/website_item_tabbed_section.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/doctype/website_offer/website_offer.py b/erpnext/e_commerce/doctype/website_offer/website_offer.py index 8c92f75a1e9b..d64254ac9bde 100644 --- a/erpnext/e_commerce/doctype/website_offer/website_offer.py +++ b/erpnext/e_commerce/doctype/website_offer/website_offer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/doctype/wishlist/test_wishlist.py b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py index 9d27126fdb29..b551f923dac1 100644 --- a/erpnext/e_commerce/doctype/wishlist/test_wishlist.py +++ b/erpnext/e_commerce/doctype/wishlist/test_wishlist.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt import unittest @@ -42,17 +41,13 @@ def test_add_remove_items_in_wishlist(self): # add second item to wishlist add_to_wishlist("Test Phone Series Y") - wishlist_length = frappe.db.get_value( - "Wishlist Item", {"parent": frappe.session.user}, "count(*)" - ) + wishlist_length = frappe.db.get_value("Wishlist Item", {"parent": frappe.session.user}, "count(*)") self.assertEqual(wishlist_length, 2) remove_from_wishlist("Test Phone Series X") remove_from_wishlist("Test Phone Series Y") - wishlist_length = frappe.db.get_value( - "Wishlist Item", {"parent": frappe.session.user}, "count(*)" - ) + wishlist_length = frappe.db.get_value("Wishlist Item", {"parent": frappe.session.user}, "count(*)") self.assertIsNone(frappe.db.exists("Wishlist Item", {"parent": frappe.session.user})) self.assertEqual(wishlist_length, 0) @@ -75,9 +70,7 @@ def test_add_remove_in_wishlist_multiple_users(self): # check wishlist and its content for users self.assertTrue(frappe.db.exists("Wishlist", {"user": test_user.name})) self.assertTrue( - frappe.db.exists( - "Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name} - ) + frappe.db.exists("Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name}) ) self.assertTrue(frappe.db.exists("Wishlist", {"user": test_user_1.name})) @@ -97,18 +90,14 @@ def test_add_remove_in_wishlist_multiple_users(self): ) ) self.assertTrue( - frappe.db.exists( - "Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name} - ) + frappe.db.exists("Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name}) ) # remove item for first user frappe.set_user(test_user.name) remove_from_wishlist("Test Phone Series X") self.assertFalse( - frappe.db.exists( - "Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name} - ) + frappe.db.exists("Wishlist Item", {"item_code": "Test Phone Series X", "parent": test_user.name}) ) # tear down diff --git a/erpnext/e_commerce/doctype/wishlist/wishlist.py b/erpnext/e_commerce/doctype/wishlist/wishlist.py index eb74027d77de..86672c91d7a5 100644 --- a/erpnext/e_commerce/doctype/wishlist/wishlist.py +++ b/erpnext/e_commerce/doctype/wishlist/wishlist.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py index 75ebccbc1b7c..99f0fcd34758 100644 --- a/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py +++ b/erpnext/e_commerce/doctype/wishlist_item/wishlist_item.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt diff --git a/erpnext/e_commerce/legacy_search.py b/erpnext/e_commerce/legacy_search.py index ef8e86d44282..9d36bfd58511 100644 --- a/erpnext/e_commerce/legacy_search.py +++ b/erpnext/e_commerce/legacy_search.py @@ -114,9 +114,7 @@ def parse_result(self, result): def get_all_published_items(): - return frappe.get_all( - "Website Item", filters={"variant_of": "", "published": 1}, pluck="item_code" - ) + return frappe.get_all("Website Item", filters={"variant_of": "", "published": 1}, pluck="item_code") def update_index_for_path(path): diff --git a/erpnext/e_commerce/product_data_engine/filters.py b/erpnext/e_commerce/product_data_engine/filters.py index e5e5e97f86af..7e2904793e2b 100644 --- a/erpnext/e_commerce/product_data_engine/filters.py +++ b/erpnext/e_commerce/product_data_engine/filters.py @@ -24,9 +24,7 @@ def get_field_filters(self): # filter valid field filters i.e. those that exist in Website Item web_item_meta = frappe.get_meta("Website Item", cached=True) - fields = [ - web_item_meta.get_field(field) for field in filter_fields if web_item_meta.has_field(field) - ] + fields = [web_item_meta.get_field(field) for field in filter_fields if web_item_meta.has_field(field)] for df in fields: item_filters, item_or_filters = {"published": 1}, [] @@ -41,14 +39,24 @@ def get_field_filters(self): item_or_filters.extend( [ ["item_group", "in", include_groups], - ["Website Item Group", "item_group", "=", self.item_group], # consider website item groups + [ + "Website Item Group", + "item_group", + "=", + self.item_group, + ], # consider website item groups ] ) else: item_or_filters.extend( [ ["item_group", "=", self.item_group], - ["Website Item Group", "item_group", "=", self.item_group], # consider website item groups + [ + "Website Item Group", + "item_group", + "=", + self.item_group, + ], # consider website item groups ] ) diff --git a/erpnext/e_commerce/product_data_engine/query.py b/erpnext/e_commerce/product_data_engine/query.py index 975f87608a63..1c1275051e26 100644 --- a/erpnext/e_commerce/product_data_engine/query.py +++ b/erpnext/e_commerce/product_data_engine/query.py @@ -56,7 +56,7 @@ def query(self, attributes=None, fields=None, search_term=None, start=0, item_gr """ # track if discounts included in field filters self.filter_with_discount = bool(fields.get("discount")) - result, discount_list, website_item_groups, cart_items, count = [], [], [], [], 0 + result, discount_list, _website_item_groups, cart_items, count = [], [], [], [], 0 if fields: self.build_fields_filters(fields) @@ -215,7 +215,7 @@ def build_search_filters(self, search_term): search_fields.discard("web_long_description") # Build or filters for query - search = "%{}%".format(search_term) + search = f"%{search_term}%" for field in search_fields: self.or_filters.append([field, "like", search]) diff --git a/erpnext/e_commerce/product_data_engine/test_product_data_engine.py b/erpnext/e_commerce/product_data_engine/test_product_data_engine.py index c3b6ed5da253..76cabfffc872 100644 --- a/erpnext/e_commerce/product_data_engine/test_product_data_engine.py +++ b/erpnext/e_commerce/product_data_engine/test_product_data_engine.py @@ -136,9 +136,7 @@ def test_product_list_with_field_filter(self): field_filters = {"item_group": "Raw Material"} engine = ProductQuery() - result = engine.query( - attributes={}, fields=field_filters, search_term=None, start=0, item_group=None - ) + result = engine.query(attributes={}, fields=field_filters, search_term=None, start=0, item_group=None) items = result.get("items") # check if only 'Raw Material' are fetched in the right order @@ -229,9 +227,7 @@ def test_product_list_with_discount_filters(self): frappe.local.shopping_cart_settings = None engine = ProductQuery() - result = engine.query( - attributes={}, fields=field_filters, search_term=None, start=0, item_group=None - ) + result = engine.query(attributes={}, fields=field_filters, search_term=None, start=0, item_group=None) items = result.get("items") # check if only product with 10% and below discount are fetched @@ -293,12 +289,8 @@ def test_custom_field_as_filter(self): ), ) - frappe.db.set_value( - "Website Item", {"item_code": "Test 11I Laptop"}, "supplier", "_Test Supplier" - ) - frappe.db.set_value( - "Website Item", {"item_code": "Test 12I Laptop"}, "supplier", "_Test Supplier 1" - ) + frappe.db.set_value("Website Item", {"item_code": "Test 11I Laptop"}, "supplier", "_Test Supplier") + frappe.db.set_value("Website Item", {"item_code": "Test 12I Laptop"}, "supplier", "_Test Supplier 1") settings = frappe.get_doc("E Commerce Settings") settings.append("filter_fields", {"fieldname": "supplier"}) @@ -316,9 +308,7 @@ def test_custom_field_as_filter(self): # test if custom filter works in query field_filters = {"supplier": "_Test Supplier 1"} engine = ProductQuery() - result = engine.query( - attributes={}, fields=field_filters, search_term=None, start=0, item_group=None - ) + result = engine.query(attributes={}, fields=field_filters, search_term=None, start=0, item_group=None) items = result.get("items") # check if only 'Raw Material' are fetched in the right order diff --git a/erpnext/e_commerce/redisearch_utils.py b/erpnext/e_commerce/redisearch_utils.py index 1f649c7b486d..e096208c9fd8 100644 --- a/erpnext/e_commerce/redisearch_utils.py +++ b/erpnext/e_commerce/redisearch_utils.py @@ -38,7 +38,7 @@ def is_search_module_loaded(): out = cache.execute_command("MODULE LIST") parsed_output = " ".join( - (" ".join([frappe.as_unicode(s) for s in o if not isinstance(s, int)]) for o in out) + " ".join([frappe.as_unicode(s) for s in o if not isinstance(s, int)]) for o in out ) return "search" in parsed_output except Exception: @@ -58,7 +58,7 @@ def wrapper(*args, **kwargs): def make_key(key): - return "{0}|{1}".format(frappe.conf.db_name, key).encode("utf-8") + return f"{frappe.conf.db_name}|{key}".encode() @if_redisearch_enabled @@ -89,7 +89,7 @@ def create_website_items_index(): idx_fields = list(map(to_search_field, idx_fields)) client.create_index( - [TextField("web_item_name", sortable=True)] + idx_fields, + [TextField("web_item_name", sortable=True), *idx_fields], definition=idx_def, ) @@ -187,9 +187,7 @@ def define_autocomplete_dictionary(): @if_redisearch_enabled def create_items_autocomplete_dict(autocompleter): "Add items as suggestions in Autocompleter." - items = frappe.get_all( - "Website Item", fields=["web_item_name", "item_group"], filters={"published": 1} - ) + items = frappe.get_all("Website Item", fields=["web_item_name", "item_group"], filters={"published": 1}) for item in items: autocompleter.add_suggestions(Suggestion(item.web_item_name)) @@ -248,6 +246,4 @@ def raise_redisearch_error(): log = frappe.log_error("Redisearch Error") log_link = frappe.utils.get_link_to_form("Error Log", log.name) - frappe.throw( - msg=_("Something went wrong. Check {0}").format(log_link), title=_("Redisearch Error") - ) + frappe.throw(msg=_("Something went wrong. Check {0}").format(log_link), title=_("Redisearch Error")) diff --git a/erpnext/e_commerce/shopping_cart/cart.py b/erpnext/e_commerce/shopping_cart/cart.py index 029506b7a1e2..c168b4f5a953 100644 --- a/erpnext/e_commerce/shopping_cart/cart.py +++ b/erpnext/e_commerce/shopping_cart/cart.py @@ -150,9 +150,7 @@ def update_cart(item_code, qty, additional_notes=None, with_items=False): empty_card = True else: - warehouse = frappe.get_cached_value( - "Website Item", {"item_code": item_code}, "website_warehouse" - ) + warehouse = frappe.get_cached_value("Website Item", {"item_code": item_code}, "website_warehouse") quotation_items = quotation.get("items", {"item_code": item_code}) if not quotation_items: @@ -243,14 +241,12 @@ def create_lead_for_item_inquiry(lead, subject, message): lead_doc.add_comment( "Comment", - text=""" + text=f"""
    {subject}

    {message}

    - """.format( - subject=subject, message=message - ), + """, ) return lead_doc @@ -276,9 +272,7 @@ def update_cart_address(address_type, address_name): quotation.shipping_address_name = address_name quotation.shipping_address = address_display quotation.customer_address = quotation.customer_address or address_name - address_doc = next( - (doc for doc in get_shipping_addresses() if doc["name"] == address_name), None - ) + address_doc = next((doc for doc in get_shipping_addresses() if doc["name"] == address_name), None) apply_cart_settings(quotation=quotation) quotation.flags.ignore_permissions = True @@ -300,9 +294,7 @@ def guess_territory(): territory = frappe.db.get_value("Territory", geoip_country) return ( - territory - or frappe.db.get_value("E Commerce Settings", None, "territory") - or get_root_of("Territory") + territory or frappe.db.get_value("E Commerce Settings", None, "territory") or get_root_of("Territory") ) @@ -591,9 +583,7 @@ def get_debtors_account(cart_settings): return debtors_account_name -def get_address_docs( - doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None -): +def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None): if not party: party = get_party() diff --git a/erpnext/e_commerce/shopping_cart/product_info.py b/erpnext/e_commerce/shopping_cart/product_info.py index 0248ca73d7f6..b1966dd33c67 100644 --- a/erpnext/e_commerce/shopping_cart/product_info.py +++ b/erpnext/e_commerce/shopping_cart/product_info.py @@ -29,9 +29,7 @@ def get_product_info_for_website(item_code, skip_quotation_creation=False): cart_quotation = _get_cart_quotation() selling_price_list = ( - cart_quotation.get("selling_price_list") - if cart_quotation - else _set_price_list(cart_settings, None) + cart_quotation.get("selling_price_list") if cart_quotation else _set_price_list(cart_settings, None) ) price = {} diff --git a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py index 363a80545b0f..1dcd494a5456 100644 --- a/erpnext/e_commerce/shopping_cart/test_shopping_cart.py +++ b/erpnext/e_commerce/shopping_cart/test_shopping_cart.py @@ -44,9 +44,7 @@ def tearDownClass(cls): frappe.db.sql("delete from `tabTax Rule`") def test_get_cart_new_user(self): - self.login_as_customer( - "test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer" - ) + self.login_as_customer("test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer") create_address_and_contact( address_title="_Test Address for Customer 2", first_name="_Test Contact for Customer 2", @@ -79,9 +77,7 @@ def validate_quotation(customer_name): return quotation def test_add_to_cart(self): - self.login_as_customer( - "test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer" - ) + self.login_as_customer("test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer") create_address_and_contact( address_title="_Test Address for Customer 2", first_name="_Test Contact for Customer 2", @@ -140,9 +136,7 @@ def test_remove_from_cart(self): def test_tax_rule(self): self.create_tax_rule() - self.login_as_customer( - "test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer" - ) + self.login_as_customer("test_contact_two_customer@example.com", "_Test Contact 2 For _Test Customer") create_address_and_contact( address_title="_Test Address for Customer 2", first_name="_Test Contact for Customer 2", diff --git a/erpnext/e_commerce/shopping_cart/utils.py b/erpnext/e_commerce/shopping_cart/utils.py index 3d48c28dd1ca..d6461767dc12 100644 --- a/erpnext/e_commerce/shopping_cart/utils.py +++ b/erpnext/e_commerce/shopping_cart/utils.py @@ -6,10 +6,7 @@ def show_cart_count(): - if ( - is_cart_enabled() - and frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User" - ): + if is_cart_enabled() and frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User": return True return False diff --git a/erpnext/e_commerce/variant_selector/utils.py b/erpnext/e_commerce/variant_selector/utils.py index 88356f5e9096..ea7221ed674e 100644 --- a/erpnext/e_commerce/variant_selector/utils.py +++ b/erpnext/e_commerce/variant_selector/utils.py @@ -35,7 +35,7 @@ def get_item_codes_by_attributes(attribute_filters, template_item_code=None): else: variant_of_query = "" - query = """ + query = f""" SELECT t1.parent FROM @@ -58,9 +58,7 @@ def get_item_codes_by_attributes(attribute_filters, template_item_code=None): t1.parent ORDER BY NULL - """.format( - attribute_query=attribute_query, variant_of_query=variant_of_query - ) + """ item_codes = set([r[0] for r in frappe.db.sql(query, query_values)]) # nosemgrep items.append(item_codes) @@ -175,12 +173,10 @@ def get_next_attribute_and_values(item_code, selected_attributes): if exact_match and len(exact_match) == 1: product_id = exact_match[0] elif filtered_items_count == 1: - product_id = list(filtered_items)[0] + product_id = next(iter(filtered_items)) if product_id: - warehouse = frappe.get_cached_value( - "Website Item", {"item_code": product_id}, "website_warehouse" - ) + warehouse = frappe.get_cached_value("Website Item", {"item_code": product_id}, "website_warehouse") available_qty = 0.0 if warehouse and frappe.get_cached_value("Warehouse", warehouse, "is_group") == 1: diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py index 6d977e022ffe..0298373ba88a 100644 --- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py +++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py @@ -11,15 +11,10 @@ def verify_request(): woocommerce_settings = frappe.get_doc("Woocommerce Settings") sig = base64.b64encode( - hmac.new( - woocommerce_settings.secret.encode("utf8"), frappe.request.data, hashlib.sha256 - ).digest() + hmac.new(woocommerce_settings.secret.encode("utf8"), frappe.request.data, hashlib.sha256).digest() ) - if ( - frappe.request.data - and not sig == frappe.get_request_header("X-Wc-Webhook-Signature", "").encode() - ): + if frappe.request.data and not sig == frappe.get_request_header("X-Wc-Webhook-Signature", "").encode(): frappe.throw(_("Unverified Webhook Data")) frappe.set_user(woocommerce_settings.creation_user) diff --git a/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py b/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py index 4879cb56239d..a9d6db4222fd 100644 --- a/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py +++ b/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py @@ -15,7 +15,7 @@ def validate(self): def verify_credentials(self): if self.enabled: response = requests.get( - "https://api.exotel.com/v1/Accounts/{sid}".format(sid=self.account_sid), + f"https://api.exotel.com/v1/Accounts/{self.account_sid}", auth=(self.api_key, self.api_token), ) if response.status_code != 200: diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py index 65be5993ffc8..d8f8a3d3d915 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/__init__.py @@ -34,7 +34,7 @@ def set_status(event): def set_mandate_status(event): mandates = [] - if isinstance(event["links"], (list,)): + if isinstance(event["links"], list): for link in event["links"]: mandates.append(link["mandate"]) else: diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py index 4a29a6a21de5..93cab9e4e4ab 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py @@ -23,9 +23,7 @@ def validate(self): def initialize_client(self): self.environment = self.get_environment() try: - self.client = gocardless_pro.Client( - access_token=self.access_token, environment=self.environment - ) + self.client = gocardless_pro.Client(access_token=self.access_token, environment=self.environment) return self.client except Exception as e: frappe.throw(e) @@ -67,7 +65,6 @@ def on_payment_request_submission(self, data): return True def check_mandate_validity(self, data): - if frappe.db.exists("GoCardless Mandate", dict(customer=data.get("payer_name"), disabled=0)): registered_mandate = frappe.db.get_value( "GoCardless Mandate", dict(customer=data.get("payer_name"), disabled=0), "mandate" @@ -102,7 +99,7 @@ def validate_transaction_currency(self, currency): ) def get_payment_url(self, **kwargs): - return get_url("./integrations/gocardless_checkout?{0}".format(urlencode(kwargs))) + return get_url(f"./integrations/gocardless_checkout?{urlencode(kwargs)}") def create_payment_request(self, data): self.data = frappe._dict(data) @@ -127,9 +124,7 @@ def create_charge_on_gocardless(self): redirect_to = self.data.get("redirect_to") or None redirect_message = self.data.get("redirect_message") or None - reference_doc = frappe.get_doc( - self.data.get("reference_doctype"), self.data.get("reference_docname") - ) + reference_doc = frappe.get_doc(self.data.get("reference_doctype"), self.data.get("reference_docname")) self.initialize_client() try: @@ -175,7 +170,7 @@ def create_charge_on_gocardless(self): frappe.log_error("Gocardless payment failed") self.integration_request.db_set("error", payment.status, update_modified=False) - except Exception as e: + except Exception: frappe.log_error("GoCardless Payment Error") if self.flags.status_changed_to == "Completed": diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py index a577e7fa6920..ce6df833b38d 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_connector.py @@ -32,7 +32,7 @@ def authenticate(self): access_token (str): This token is to be used with the Bearer header for further API calls to Mpesa. """ authenticate_uri = "/oauth/v1/generate?grant_type=client_credentials" - authenticate_url = "{0}{1}".format(self.base_url, authenticate_uri) + authenticate_url = f"{self.base_url}{authenticate_uri}" r = requests.get(authenticate_url, auth=HTTPBasicAuth(self.app_key, self.app_secret)) self.authentication_token = r.json()["access_token"] return r.json()["access_token"] @@ -77,10 +77,10 @@ def get_balance( "ResultURL": result_url, } headers = { - "Authorization": "Bearer {0}".format(self.authentication_token), + "Authorization": f"Bearer {self.authentication_token}", "Content-Type": "application/json", } - saf_url = "{0}{1}".format(self.base_url, "/mpesa/accountbalance/v1/query") + saf_url = "{}{}".format(self.base_url, "/mpesa/accountbalance/v1/query") r = requests.post(saf_url, headers=headers, json=payload) return r.json() @@ -119,10 +119,8 @@ def stk_push( errorMessage(str): This is a predefined code that indicates the reason for request failure. """ - time = ( - str(datetime.datetime.now()).split(".")[0].replace("-", "").replace(" ", "").replace(":", "") - ) - password = "{0}{1}{2}".format(str(business_shortcode), str(passcode), time) + time = str(datetime.datetime.now()).split(".")[0].replace("-", "").replace(" ", "").replace(":", "") + password = f"{business_shortcode!s}{passcode!s}{time}" encoded = base64.b64encode(bytes(password, encoding="utf8")) payload = { "BusinessShortCode": business_shortcode, @@ -135,15 +133,13 @@ def stk_push( "CallBackURL": callback_url, "AccountReference": reference_code, "TransactionDesc": description, - "TransactionType": "CustomerPayBillOnline" - if self.env == "sandbox" - else "CustomerBuyGoodsOnline", + "TransactionType": "CustomerPayBillOnline" if self.env == "sandbox" else "CustomerBuyGoodsOnline", } headers = { - "Authorization": "Bearer {0}".format(self.authentication_token), + "Authorization": f"Bearer {self.authentication_token}", "Content-Type": "application/json", } - saf_url = "{0}{1}".format(self.base_url, "/mpesa/stkpush/v1/processrequest") + saf_url = "{}{}".format(self.base_url, "/mpesa/stkpush/v1/processrequest") r = requests.post(saf_url, headers=headers, json=payload) return r.json() diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py index a298e11eaf52..d42112991783 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py @@ -51,7 +51,7 @@ def request_for_payment(self, **kwargs): args = frappe._dict(kwargs) request_amounts = self.split_request_amount_according_to_transaction_limit(args) - for i, amount in enumerate(request_amounts): + for _i, amount in enumerate(request_amounts): args.request_amount = amount if frappe.flags.in_test: from erpnext.erpnext_integrations.doctype.mpesa_settings.test_mpesa_settings import ( @@ -104,8 +104,8 @@ def get_account_balance_info(self): def handle_api_response(self, global_id, request_dict, response): """Response received from API calls returns a global identifier for each transaction, this code is returned during the callback.""" # check error response - if getattr(response, "requestId"): - req_name = getattr(response, "requestId") + if response.requestId: + req_name = response.requestId error = response else: # global checkout id used as request name @@ -116,7 +116,7 @@ def handle_api_response(self, global_id, request_dict, response): create_request_log(request_dict, "Host", "Mpesa", req_name, error) if error: - frappe.throw(_(getattr(response, "errorMessage")), title=_("Transaction Error")) + frappe.throw(_(response.errorMessage), title=_("Transaction Error")) def generate_stk_push(**kwargs): @@ -197,7 +197,7 @@ def verify_transaction(**kwargs): ) total_paid = amount + sum(completed_payments) - mpesa_receipts = ", ".join(mpesa_receipts + [mpesa_receipt]) + mpesa_receipts = ", ".join([*mpesa_receipts, mpesa_receipt]) if total_paid >= pr.grand_total: pr.run_method("on_payment_authorized", "Completed") @@ -318,9 +318,7 @@ def process_balance_info(**kwargs): ) except Exception: request.handle_failure(account_balance_response) - frappe.log_error( - title="Mpesa Account Balance Processing Error", message=account_balance_response - ) + frappe.log_error(title="Mpesa Account Balance Processing Error", message=account_balance_response) else: request.handle_failure(account_balance_response) diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py index b52662421d33..4218e03b91d8 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py @@ -90,9 +90,7 @@ def test_processing_of_callback_payload(self): pluck="name", ) - callback_response = get_payment_callback_payload( - Amount=500, CheckoutRequestID=integration_req_ids[0] - ) + callback_response = get_payment_callback_payload(Amount=500, CheckoutRequestID=integration_req_ids[0]) verify_transaction(**callback_response) # test creation of integration request integration_request = frappe.get_doc("Integration Request", integration_req_ids[0]) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index af1052a37007..4f14143a9a0e 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -127,7 +127,9 @@ def add_bank_accounts(response, bank, company): result.append(new_account.name) except frappe.UniqueValidationError: frappe.msgprint( - _("Bank account {0} already exists and could not be created again").format(account["name"]) + _("Bank account {0} already exists and could not be created again").format( + account["name"] + ) ) except Exception: frappe.log_error("Plaid Link Error") @@ -205,9 +207,7 @@ def sync_transactions(bank, bank_account): f"Plaid added {len(result)} new Bank Transactions from '{bank_account}' between {start_date} and {end_date}" ) - frappe.db.set_value( - "Bank Account", bank_account, "last_integration_date", last_transaction_date - ) + frappe.db.set_value("Bank Account", bank_account, "last_integration_date", last_transaction_date) except Exception: frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error")) @@ -229,9 +229,7 @@ def get_transactions(bank, bank_account=None, start_date=None, end_date=None): transactions = [] try: - transactions = plaid.get_transactions( - start_date=start_date, end_date=end_date, account_id=account_id - ) + transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id) except ItemError as e: if e.code == "ITEM_LOGIN_REQUIRED": msg = _("There was an error syncing transactions.") + " " diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py index da5699776fdf..b3229ab19ddf 100644 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py +++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.py @@ -35,10 +35,8 @@ def callback(*args, **kwargs): class QuickBooksMigrator(Document): def __init__(self, *args, **kwargs): - super(QuickBooksMigrator, self).__init__(*args, **kwargs) - self.oauth = OAuth2Session( - client_id=self.client_id, redirect_uri=self.redirect_url, scope=self.scope - ) + super().__init__(*args, **kwargs) + self.oauth = OAuth2Session(client_id=self.client_id, redirect_uri=self.redirect_url, scope=self.scope) if not self.authorization_url and self.authorization_endpoint: self.authorization_url = self.oauth.authorization_url(self.authorization_endpoint)[0] @@ -46,9 +44,7 @@ def on_update(self): if self.company: # We need a Cost Center corresponding to the selected erpnext Company self.default_cost_center = frappe.db.get_value("Company", self.company, "cost_center") - company_warehouses = frappe.get_all( - "Warehouse", filters={"company": self.company, "is_group": 0} - ) + company_warehouses = frappe.get_all("Warehouse", filters={"company": self.company, "is_group": 0}) if company_warehouses: self.default_warehouse = company_warehouses[0].name if self.authorization_endpoint: @@ -196,14 +192,14 @@ def _make_root_accounts(self): if not frappe.db.exists( { "doctype": "Account", - "name": encode_company_abbr("{} - QB".format(root), self.company), + "name": encode_company_abbr(f"{root} - QB", self.company), "company": self.company, } ): frappe.get_doc( { "doctype": "Account", - "account_name": "{} - QB".format(root), + "account_name": f"{root} - QB", "root_type": root, "is_group": "1", "company": self.company, @@ -215,13 +211,10 @@ def _make_root_accounts(self): def _migrate_entries(self, entity): try: - query_uri = "{}/company/{}/query".format( - self.api_endpoint, - self.quickbooks_company_id, - ) + query_uri = f"{self.api_endpoint}/company/{self.quickbooks_company_id}/query" max_result_count = 1000 # Count number of entries - response = self._get(query_uri, params={"query": """SELECT COUNT(*) FROM {}""".format(entity)}) + response = self._get(query_uri, params={"query": f"""SELECT COUNT(*) FROM {entity}"""}) entry_count = response.json()["QueryResponse"]["totalCount"] # fetch pages and accumulate @@ -243,9 +236,7 @@ def _migrate_entries(self, entity): def _fetch_general_ledger(self): try: - query_uri = "{}/company/{}/reports/GeneralLedger".format( - self.api_endpoint, self.quickbooks_company_id - ) + query_uri = f"{self.api_endpoint}/company/{self.quickbooks_company_id}/reports/GeneralLedger" response = self._get( query_uri, params={ @@ -574,7 +565,9 @@ def _save_item(self, item): "is_stock_item": 0, "item_group": "All Item Groups", "company": self.company, - "item_defaults": [{"company": self.company, "default_warehouse": self.default_warehouse}], + "item_defaults": [ + {"company": self.company, "default_warehouse": self.default_warehouse} + ], } if "ExpenseAccountRef" in item: expense_account = self._get_account_name_by_id(item["ExpenseAccountRef"]["value"]) @@ -614,7 +607,9 @@ def _save_preference(self, preference): try: if preference["SalesFormsPrefs"]["AllowShipping"]: default_shipping_account_id = preference["SalesFormsPrefs"]["DefaultShippingAccount"] - self.default_shipping_account = self._get_account_name_by_id(self, default_shipping_account_id) + self.default_shipping_account = self._get_account_name_by_id( + self, default_shipping_account_id + ) self.save() except Exception as e: self._log_error(e, preference) @@ -722,7 +717,9 @@ def _get_si_items(self, invoice, is_return=False): "item_code": item["name"], "conversion_factor": 1, "uom": item["stock_uom"], - "description": line.get("Description", line["SalesItemLineDetail"]["ItemRef"]["name"]), + "description": line.get( + "Description", line["SalesItemLineDetail"]["ItemRef"]["name"] + ), "qty": line["SalesItemLineDetail"]["Qty"], "price_list_rate": line["SalesItemLineDetail"]["UnitPrice"], "cost_center": self.default_cost_center, @@ -994,7 +991,11 @@ def _save_payment(self, payment): si_quickbooks_id = "Invoice - {}".format(linked_transaction["TxnId"]) # Invoice could have been saved as a Sales Invoice or a Journal Entry if frappe.db.exists( - {"doctype": "Sales Invoice", "quickbooks_id": si_quickbooks_id, "company": self.company} + { + "doctype": "Sales Invoice", + "quickbooks_id": si_quickbooks_id, + "company": self.company, + } ): sales_invoice = frappe.get_all( "Sales Invoice", @@ -1010,7 +1011,11 @@ def _save_payment(self, payment): party_account = sales_invoice["debit_to"] if frappe.db.exists( - {"doctype": "Journal Entry", "quickbooks_id": si_quickbooks_id, "company": self.company} + { + "doctype": "Journal Entry", + "quickbooks_id": si_quickbooks_id, + "company": self.company, + } ): journal_entry = frappe.get_doc( "Journal Entry", @@ -1020,9 +1025,9 @@ def _save_payment(self, payment): }, ) # Invoice saved as a Journal Entry must have party and party_type set on line containing Receivable Account - customer_account_line = list( + customer_account_line = next( filter(lambda acc: acc.party_type == "Customer", journal_entry.accounts) - )[0] + ) reference_type = "Journal Entry" reference_name = journal_entry.name @@ -1064,7 +1069,11 @@ def _save_bill_payment(self, bill_payment): if linked_transaction["TxnType"] == "Bill": pi_quickbooks_id = "Bill - {}".format(linked_transaction["TxnId"]) if frappe.db.exists( - {"doctype": "Purchase Invoice", "quickbooks_id": pi_quickbooks_id, "company": self.company} + { + "doctype": "Purchase Invoice", + "quickbooks_id": pi_quickbooks_id, + "company": self.company, + } ): purchase_invoice = frappe.get_all( "Purchase Invoice", @@ -1199,7 +1208,9 @@ def _save_deposit(self, deposit): else: accounts.append( { - "account": self._get_account_name_by_id(line["DepositLineDetail"]["AccountRef"]["value"]), + "account": self._get_account_name_by_id( + line["DepositLineDetail"]["AccountRef"]["value"] + ), "credit_in_account_currency": line["Amount"], "cost_center": self.default_cost_center, } @@ -1254,7 +1265,7 @@ def _get_taxes(self, entry): return taxes for line in entry["TxnTaxDetail"]["TaxLine"]: tax_rate = line["TaxLineDetail"]["TaxRateRef"]["value"] - account_head = self._get_account_name_by_id("TaxRate - {}".format(tax_rate)) + account_head = self._get_account_name_by_id(f"TaxRate - {tax_rate}") tax_type_applicable = self._get_tax_type(tax_rate) if tax_type_applicable == "TaxOnAmount": taxes.append( @@ -1303,7 +1314,7 @@ def _get_parent_tax_rate(self, tax_rate): return tax_rate_detail["TaxRateRef"]["value"] def _get_parent_row_id(self, tax_rate, taxes): - tax_account = self._get_account_name_by_id("TaxRate - {}".format(tax_rate)) + tax_account = self._get_account_name_by_id(f"TaxRate - {tax_rate}") for index, tax in enumerate(taxes): if tax["account_head"] == tax_account: return index + 1 @@ -1328,7 +1339,7 @@ def _create_address(self, entity, doctype, address, address_type): def _get(self, *args, **kwargs): kwargs["headers"] = { "Accept": "application/json", - "Authorization": "Bearer {}".format(self.access_token), + "Authorization": f"Bearer {self.access_token}", } response = requests.get(*args, **kwargs) # HTTP Status code 401 here means that the access_token is expired @@ -1340,18 +1351,18 @@ def _get(self, *args, **kwargs): return response def _get_account_name_by_id(self, quickbooks_id): - return frappe.get_all( - "Account", filters={"quickbooks_id": quickbooks_id, "company": self.company} - )[0]["name"] + return frappe.get_all("Account", filters={"quickbooks_id": quickbooks_id, "company": self.company})[ + 0 + ]["name"] def _publish(self, *args, **kwargs): frappe.publish_realtime("quickbooks_progress_update", *args, **kwargs, user=self.modified_by) def _get_unique_account_name(self, quickbooks_name, number=0): if number: - quickbooks_account_name = "{} - {} - QB".format(quickbooks_name, number) + quickbooks_account_name = f"{quickbooks_name} - {number} - QB" else: - quickbooks_account_name = "{} - QB".format(quickbooks_name) + quickbooks_account_name = f"{quickbooks_name} - QB" company_encoded_account_name = encode_company_abbr(quickbooks_account_name, self.company) if frappe.db.exists( {"doctype": "Account", "name": company_encoded_account_name, "company": self.company} diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py index e6840f505bed..0a27a647129a 100644 --- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py +++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py @@ -96,9 +96,7 @@ def set_account_defaults(self): self.default_cost_center, self.default_round_off_account = frappe.db.get_value( "Company", self.erpnext_company, ["cost_center", "round_off_account"] ) - self.default_warehouse = frappe.db.get_value( - "Stock Settings", "Stock Settings", "default_warehouse" - ) + self.default_warehouse = frappe.db.get_value("Stock Settings", "Stock Settings", "default_warehouse") def _process_master_data(self): def get_company_name(collection): @@ -159,7 +157,7 @@ def get_parent(account): def get_children_and_parent_dict(accounts): children, parents = {}, {} - for parent, account, is_group in accounts: + for parent, account, _is_group in accounts: children.setdefault(parent, set()).add(account) parents.setdefault(account, set()).add(parent) parents[account].update(parents.get(parent, [])) @@ -204,7 +202,9 @@ def get_parties_addresses(collection, customers, suppliers): { "doctype": party_type, "customer_name": account.NAME.string.strip(), - "tax_id": account.INCOMETAXNUMBER.string.strip() if account.INCOMETAXNUMBER else None, + "tax_id": account.INCOMETAXNUMBER.string.strip() + if account.INCOMETAXNUMBER + else None, "customer_group": "All Customer Groups", "territory": "All Territories", "customer_type": "Individual", @@ -218,7 +218,9 @@ def get_parties_addresses(collection, customers, suppliers): { "doctype": party_type, "supplier_name": account.NAME.string.strip(), - "pan": account.INCOMETAXNUMBER.string.strip() if account.INCOMETAXNUMBER else None, + "pan": account.INCOMETAXNUMBER.string.strip() + if account.INCOMETAXNUMBER + else None, "supplier_group": "All Supplier Groups", "supplier_type": "Individual", } @@ -234,7 +236,9 @@ def get_parties_addresses(collection, customers, suppliers): "address_line2": address[140:].strip(), "country": account.COUNTRYNAME.string.strip() if account.COUNTRYNAME else None, "state": account.LEDSTATENAME.string.strip() if account.LEDSTATENAME else None, - "gst_state": account.LEDSTATENAME.string.strip() if account.LEDSTATENAME else None, + "gst_state": account.LEDSTATENAME.string.strip() + if account.LEDSTATENAME + else None, "pin_code": account.PINCODE.string.strip() if account.PINCODE else None, "mobile": account.LEDGERPHONE.string.strip() if account.LEDGERPHONE else None, "phone": account.LEDGERPHONE.string.strip() if account.LEDGERPHONE else None, @@ -576,7 +580,7 @@ def create_fiscal_years(vouchers): if new_year.year_start_date.year == new_year.year_end_date.year: new_year.year = new_year.year_start_date.year else: - new_year.year = "{}-{}".format(new_year.year_start_date.year, new_year.year_end_date.year) + new_year.year = f"{new_year.year_start_date.year}-{new_year.year_end_date.year}" new_year.save() oldest_year = new_year diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py index 2148863c5569..e649707c8064 100644 --- a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py +++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py @@ -23,9 +23,7 @@ def on_update(self): "Custom Field", {"dt": ("in", ["Item", "Sales Invoice Item"]), "fieldname": "product_tax_category"}, ) - fields_hidden = frappe.get_value( - "Custom Field", {"dt": ("in", ["Sales Invoice Item"])}, "hidden" - ) + fields_hidden = frappe.get_value("Custom Field", {"dt": ("in", ["Sales Invoice Item"])}, "hidden") if TAXJAR_CREATE_TRANSACTIONS or TAXJAR_CALCULATE_TAX or TAXJAR_SANDBOX_MODE: if not fields_already_exist: @@ -70,13 +68,11 @@ def toggle_tax_category_fields(hidden): "hidden", hidden, ) - frappe.set_value( - "Custom Field", {"dt": "Item", "fieldname": "product_tax_category"}, "hidden", hidden - ) + frappe.set_value("Custom Field", {"dt": "Item", "fieldname": "product_tax_category"}, "hidden", hidden) def add_product_tax_categories(): - with open(os.path.join(os.path.dirname(__file__), "product_tax_category_data.json"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "product_tax_category_data.json")) as f: tax_categories = json.loads(f.read()) create_tax_categories(tax_categories["categories"]) diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py index 4aa98aab56bd..99a39d7da884 100644 --- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py +++ b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py @@ -67,7 +67,7 @@ def create_webhook_url(self): # for CI Test to work url = "http://localhost:8000" - server_url = "{uri.scheme}://{uri.netloc}".format(uri=urlparse(url)) + server_url = f"{urlparse(url).scheme}://{urlparse(url).netloc}" delivery_url = server_url + endpoint self.endpoint = delivery_url diff --git a/erpnext/erpnext_integrations/exotel_integration.py b/erpnext/erpnext_integrations/exotel_integration.py index fd0f78357599..a7b7c3ee3061 100644 --- a/erpnext/erpnext_integrations/exotel_integration.py +++ b/erpnext/erpnext_integrations/exotel_integration.py @@ -23,7 +23,7 @@ def handle_incoming_call(**kwargs): create_call_log(call_payload) else: update_call_log(call_payload, call_log=call_log) - except Exception as e: + except Exception: frappe.db.rollback() exotel_settings.log_error("Error in Exotel incoming call") frappe.db.commit() @@ -86,7 +86,7 @@ def create_call_log(call_payload): @frappe.whitelist() def get_call_status(call_id): - endpoint = get_exotel_endpoint("Calls/{call_id}.json".format(call_id=call_id)) + endpoint = get_exotel_endpoint(f"Calls/{call_id}.json") response = requests.get(endpoint) status = response.json().get("Call", {}).get("Status") return status @@ -95,9 +95,7 @@ def get_call_status(call_id): @frappe.whitelist() def make_a_call(from_number, to_number, caller_id): endpoint = get_exotel_endpoint("Calls/connect.json?details=true") - response = requests.post( - endpoint, data={"From": from_number, "To": to_number, "CallerId": caller_id} - ) + response = requests.post(endpoint, data={"From": from_number, "To": to_number, "CallerId": caller_id}) return response.json() diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py index 2d9093b6e926..0535fc9e4ae5 100644 --- a/erpnext/erpnext_integrations/taxjar_integration.py +++ b/erpnext/erpnext_integrations/taxjar_integration.py @@ -113,9 +113,7 @@ def get_client(): def create_transaction(doc, method): - TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value( - "TaxJar Settings", "taxjar_create_transactions" - ) + TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") """Create an order transaction in TaxJar""" @@ -156,9 +154,7 @@ def create_transaction(doc, method): def delete_transaction(doc, method): """Delete an existing TaxJar order transaction""" - TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value( - "TaxJar Settings", "taxjar_create_transactions" - ) + TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") if not TAXJAR_CREATE_TRANSACTIONS: return @@ -258,7 +254,7 @@ def set_sales_tax(doc, method): if not tax_dict: # Remove existing tax rows if address is changed from a taxable state/country - setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD]) + doc.taxes = [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD] return # check if delivering within a nexus @@ -267,7 +263,7 @@ def set_sales_tax(doc, method): tax_data = validate_tax_request(tax_dict) if tax_data is not None: if not tax_data.amount_to_collect: - setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD]) + doc.taxes = [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD] elif tax_data.amount_to_collect > 0: # Loop through tax rows for existing Sales Tax entry # If none are found, add a row with the tax amount diff --git a/erpnext/erpnext_integrations/utils.py b/erpnext/erpnext_integrations/utils.py index 981486eb3094..55316f588acc 100644 --- a/erpnext/erpnext_integrations/utils.py +++ b/erpnext/erpnext_integrations/utils.py @@ -15,7 +15,9 @@ def innerfn(fn): if frappe.request and settings and settings.get(secret_key) and not frappe.flags.in_test: sig = base64.b64encode( - hmac.new(settings.get(secret_key).encode("utf8"), frappe.request.data, hashlib.sha256).digest() + hmac.new( + settings.get(secret_key).encode("utf8"), frappe.request.data, hashlib.sha256 + ).digest() ) if frappe.request.data and not sig == bytes(frappe.get_request_header(hmac_key).encode()): @@ -28,7 +30,7 @@ def innerfn(fn): def get_webhook_address(connector_name, method, exclude_uri=False, force_https=False): - endpoint = "erpnext.erpnext_integrations.connectors.{0}.{1}".format(connector_name, method) + endpoint = f"erpnext.erpnext_integrations.connectors.{connector_name}.{method}" if exclude_uri: return endpoint diff --git a/erpnext/hooks.py b/erpnext/hooks.py index da4c1974247e..021cf4deb637 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -253,9 +253,7 @@ {"name": "call-disconnect", "src": "/assets/erpnext/sounds/call-disconnect.mp3", "volume": 0.2}, ] -has_upload_permission = { - "Employee": "erpnext.setup.doctype.employee.employee.has_upload_permission" -} +has_upload_permission = {"Employee": "erpnext.setup.doctype.employee.employee.has_upload_permission"} has_website_permission = { "Sales Order": "erpnext.controllers.website_list_for_contact.has_website_permission", @@ -479,9 +477,7 @@ """ -get_translated_dict = { - ("doctype", "Global Defaults"): "frappe.geo.country_info.get_translated_dict" -} +get_translated_dict = {("doctype", "Global Defaults"): "frappe.geo.country_info.get_translated_dict"} bot_parsers = [ "erpnext.utilities.bot.FindItemBot", @@ -562,9 +558,7 @@ ) regional_overrides = { - "France": { - "erpnext.tests.test_regional.test_method": "erpnext.regional.france.utils.test_method" - }, + "France": {"erpnext.tests.test_regional.test_method": "erpnext.regional.france.utils.test_method"}, "United Arab Emirates": { "erpnext.controllers.taxes_and_totals.update_itemised_tax_data": "erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data", "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries": "erpnext.regional.united_arab_emirates.utils.make_regional_gl_entries", @@ -635,9 +629,7 @@ ], } -additional_timeline_content = { - "*": ["erpnext.telephony.doctype.call_log.call_log.get_linked_call_logs"] -} +additional_timeline_content = {"*": ["erpnext.telephony.doctype.call_log.call_log.get_linked_call_logs"]} extend_bootinfo = [ diff --git a/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py b/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py index aab3d8ccb575..52734375107b 100644 --- a/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py +++ b/erpnext/loan_management/dashboard_chart_source/top_10_pledged_loan_securities/top_10_pledged_loan_securities.py @@ -45,16 +45,14 @@ def get_data( unpledges = frappe._dict( frappe.db.sql( - """ + f""" SELECT u.loan_security, sum(u.qty) as qty FROM `tabLoan Security Unpledge` up, `tabUnpledge` u WHERE u.parent = up.name AND up.status = 'Approved' {conditions} GROUP BY u.loan_security - """.format( - conditions=conditions - ), + """, filters, as_list=1, ) @@ -62,16 +60,14 @@ def get_data( pledges = frappe._dict( frappe.db.sql( - """ + f""" SELECT p.loan_security, sum(p.qty) as qty FROM `tabLoan Security Pledge` lp, `tabPledge`p WHERE p.parent = lp.name AND lp.status = 'Pledged' {conditions} GROUP BY p.loan_security - """.format( - conditions=conditions - ), + """, filters, as_list=1, ) diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index 4a333df5a599..eb90cf3b8269 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -336,7 +336,6 @@ def get_sanctioned_amount_limit(applicant_type, applicant, company): def validate_repayment_method( repayment_method, loan_amount, monthly_repayment_amount, repayment_periods, is_term_loan ): - if is_term_loan and not repayment_method: frappe.throw(_("Repayment Method is mandatory for term loans")) diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index 388e65d9e585..1f4b44e7690e 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -184,7 +184,6 @@ def test_loan(self): self.assertEqual(flt(loan.total_payment, 0), 302712) def test_loan_with_security(self): - pledge = [ { "loan_security": "Test Security 1", @@ -266,13 +265,9 @@ def test_sanctioned_amount_limit(self): # Make First Loan pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant3, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant3, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant3, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant3, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() # Make second loan greater than the sanctioned amount @@ -284,14 +279,10 @@ def test_sanctioned_amount_limit(self): def test_regular_loan_repayment(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -311,18 +302,14 @@ def test_regular_loan_repayment(self): process_loan_interest_accrual_for_demand_loans(posting_date=last_date) - repayment_entry = create_repayment_entry( - loan.name, self.applicant2, add_days(last_date, 10), 111119 - ) + repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), 111119) repayment_entry.save() repayment_entry.submit() penalty_amount = (accrued_interest_amount * 5 * 25) / 100 self.assertEqual(flt(repayment_entry.penalty_amount, 0), flt(penalty_amount, 0)) - amounts = frappe.db.get_all( - "Loan Interest Accrual", {"loan": loan.name}, ["paid_interest_amount"] - ) + amounts = frappe.db.get_all("Loan Interest Accrual", {"loan": loan.name}, ["paid_interest_amount"]) loan.load_from_db() @@ -344,14 +331,10 @@ def test_regular_loan_repayment(self): def test_loan_closure(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -415,15 +398,11 @@ def test_loan_repayment_for_term_loan(self): loan.submit() - make_loan_disbursement_entry( - loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1) - ) + make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1)) process_loan_interest_accrual_for_term_loans(posting_date=nowdate()) - repayment_entry = create_repayment_entry( - loan.name, self.applicant2, add_days(nowdate(), 5), 89768.75 - ) + repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5), 89768.75) repayment_entry.submit() @@ -511,14 +490,10 @@ def test_security_shortfall(self): def test_loan_security_unpledge(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -571,14 +546,10 @@ def test_partial_loan_security_unpledge(self): {"loan_security": "Test Security 2", "qty": 4000.00}, ] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -589,9 +560,7 @@ def test_partial_loan_security_unpledge(self): make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual_for_demand_loans(posting_date=last_date) - repayment_entry = create_repayment_entry( - loan.name, self.applicant2, add_days(last_date, 5), 600000 - ) + repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5), 600000) repayment_entry.submit() unpledge_map = {"Test Security 2": 2000} @@ -607,14 +576,10 @@ def test_partial_loan_security_unpledge(self): def test_sanctioned_loan_security_unpledge(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -693,14 +658,10 @@ def test_disbursal_check_without_shortfall(self): def test_pending_loan_amount_after_closure_request(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -743,14 +704,10 @@ def test_pending_loan_amount_after_closure_request(self): def test_partial_unaccrued_interest_payment(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -807,12 +764,9 @@ def test_penalty_repayment(self): loan, dummy = create_loan_scenario_for_penalty(self) amounts = calculate_amounts(loan.name, "2019-11-30 00:00:00") - first_penalty = 10000 second_penalty = amounts["penalty_amount"] - 10000 - repayment_entry = create_repayment_entry( - loan.name, self.applicant2, "2019-11-30 00:00:00", 10000 - ) + repayment_entry = create_repayment_entry(loan.name, self.applicant2, "2019-11-30 00:00:00", 10000) repayment_entry.submit() amounts = calculate_amounts(loan.name, "2019-11-30 00:00:01") @@ -829,14 +783,10 @@ def test_penalty_repayment(self): def test_loan_write_off_limit(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -881,14 +831,10 @@ def test_loan_write_off_limit(self): def test_loan_repayment_against_partially_disbursed_loan(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() first_date = "2019-10-01" @@ -899,21 +845,15 @@ def test_loan_repayment_against_partially_disbursed_loan(self): loan.load_from_db() self.assertEqual(loan.status, "Partially Disbursed") - create_repayment_entry( - loan.name, self.applicant2, add_days(last_date, 5), flt(loan.loan_amount / 3) - ) + create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5), flt(loan.loan_amount / 3)) def test_loan_amount_write_off(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant2, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -1026,9 +966,7 @@ def create_loan_scenario_for_penalty(doc): loan_application = create_loan_application("_Test Company", doc.applicant2, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - doc.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(doc.applicant2, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() first_date = "2019-10-01" @@ -1040,9 +978,7 @@ def create_loan_scenario_for_penalty(doc): amounts = calculate_amounts(loan.name, add_days(last_date, 1)) paid_amount = amounts["interest_amount"] / 2 - repayment_entry = create_repayment_entry( - loan.name, doc.applicant2, add_days(last_date, 5), paid_amount - ) + repayment_entry = create_repayment_entry(loan.name, doc.applicant2, add_days(last_date, 5), paid_amount) repayment_entry.submit() @@ -1154,7 +1090,6 @@ def create_loan_type( repayment_schedule_type=None, repayment_date_on=None, ): - if not frappe.db.exists("Loan Type", loan_name): loan_type = frappe.get_doc( { @@ -1228,7 +1163,6 @@ def create_loan_security(): def create_loan_security_pledge(applicant, pledges, loan_application=None, loan=None): - lsp = frappe.new_doc("Loan Security Pledge") lsp.applicant_type = "Customer" lsp.applicant = applicant @@ -1248,7 +1182,6 @@ def create_loan_security_pledge(applicant, pledges, loan_application=None, loan= def make_loan_disbursement_entry(loan, amount, disbursement_date=None): - loan_disbursement_entry = frappe.get_doc( { "doctype": "Loan Disbursement", @@ -1267,14 +1200,12 @@ def make_loan_disbursement_entry(loan, amount, disbursement_date=None): def create_loan_security_price(loan_security, loan_security_price, uom, from_date, to_date): - if not frappe.db.get_value( "Loan Security Price", {"loan_security": loan_security, "valid_from": ("<=", from_date), "valid_upto": (">=", to_date)}, "name", ): - - lsp = frappe.get_doc( + frappe.get_doc( { "doctype": "Loan Security Price", "loan_security": loan_security, @@ -1287,7 +1218,6 @@ def create_loan_security_price(loan_security, loan_security_price, uom, from_dat def create_repayment_entry(loan, applicant, posting_date, paid_amount): - lr = frappe.get_doc( { "doctype": "Loan Repayment", @@ -1350,7 +1280,6 @@ def create_loan( repayment_start_date=None, posting_date=None, ): - loan = frappe.get_doc( { "doctype": "Loan", @@ -1408,7 +1337,6 @@ def create_loan_with_security( def create_demand_loan(applicant, loan_type, loan_application, posting_date=None): - loan = frappe.get_doc( { "doctype": "Loan", diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py index 5f040e22c974..c7dfb3e92bb8 100644 --- a/erpnext/loan_management/doctype/loan_application/loan_application.py +++ b/erpnext/loan_management/doctype/loan_application/loan_application.py @@ -53,9 +53,7 @@ def validate_loan_amount(self): maximum_loan_limit = frappe.db.get_value("Loan Type", self.loan_type, "maximum_loan_amount") if maximum_loan_limit and self.loan_amount > maximum_loan_limit: - frappe.throw( - _("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit) - ) + frappe.throw(_("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit)) if self.maximum_loan_amount and self.loan_amount > self.maximum_loan_amount: frappe.throw( @@ -83,7 +81,6 @@ def check_sanctioned_amount_limit(self): def set_pledge_amount(self): for proposed_pledge in self.proposed_pledges: - if not proposed_pledge.qty and not proposed_pledge.amount: frappe.throw(_("Qty or Amount is mandatroy for loan security")) @@ -98,7 +95,6 @@ def set_pledge_amount(self): ) def get_repayment_details(self): - if self.is_term_loan: if self.repayment_method == "Repay Over Number of Periods": self.repayment_amount = get_monthly_repayment_amount( @@ -110,9 +106,14 @@ def get_repayment_details(self): if monthly_interest_rate: min_repayment_amount = self.loan_amount * monthly_interest_rate if self.repayment_amount - min_repayment_amount <= 0: - frappe.throw(_("Repayment Amount must be greater than " + str(flt(min_repayment_amount, 2)))) + frappe.throw( + _("Repayment Amount must be greater than " + str(flt(min_repayment_amount, 2))) + ) self.repayment_periods = math.ceil( - (math.log(self.repayment_amount) - math.log(self.repayment_amount - min_repayment_amount)) + ( + math.log(self.repayment_amount) + - math.log(self.repayment_amount - min_repayment_amount) + ) / (math.log(1 + monthly_interest_rate)) ) else: @@ -206,7 +207,6 @@ def create_pledge(loan_application, loan=None): lsp.loan = loan for pledge in loan_application_doc.proposed_pledges: - lsp.append( "securities", { diff --git a/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py index 0a576d69692a..9099292c4fa6 100644 --- a/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py +++ b/erpnext/loan_management/doctype/loan_balance_adjustment/loan_balance_adjustment.py @@ -97,9 +97,9 @@ def get_values_on_submit(self, loan_details): def make_gl_entries(self, cancel=0, adv_adj=0): gle_map = [] loan_account = frappe.db.get_value("Loan", self.loan, "loan_account") - remarks = "{} against loan {}".format(self.adjustment_type.capitalize(), self.loan) + remarks = f"{self.adjustment_type.capitalize()} against loan {self.loan}" if self.reference_number: - remarks += "with reference no. {}".format(self.reference_number) + remarks += f"with reference no. {self.reference_number}" loan_entry = { "account": loan_account, diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py index ec117a12ad0e..3d649f3613d9 100644 --- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py +++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py @@ -182,18 +182,14 @@ def get_total_pledged_security_value(loan): ) ) - hair_cut_map = frappe._dict( - frappe.get_all("Loan Security", fields=["name", "haircut"], as_list=1) - ) + hair_cut_map = frappe._dict(frappe.get_all("Loan Security", fields=["name", "haircut"], as_list=1)) security_value = 0.0 pledged_securities = get_pledged_security_qty(loan) for security, qty in pledged_securities.items(): after_haircut_percentage = 100 - hair_cut_map.get(security) - security_value += ( - loan_security_price_map.get(security, 0) * qty * after_haircut_percentage - ) / 100 + security_value += (loan_security_price_map.get(security, 0) * qty * after_haircut_percentage) / 100 return security_value @@ -241,10 +237,7 @@ def get_disbursal_amount(loan, on_current_security_price=0): disbursal_amount = flt(security_value) - flt(pending_principal_amount) - if ( - loan_details.is_term_loan - and (disbursal_amount + loan_details.loan_amount) > loan_details.loan_amount - ): + if loan_details.is_term_loan and (disbursal_amount + loan_details.loan_amount) > loan_details.loan_amount: disbursal_amount = loan_details.loan_amount - loan_details.disbursed_amount return disbursal_amount diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py index 9cc6ec9d4b46..6df4ad233528 100644 --- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py +++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py @@ -8,7 +8,6 @@ add_days, add_to_date, date_diff, - flt, get_datetime, get_first_day, get_last_day, @@ -76,9 +75,7 @@ def setUp(self): def test_loan_topup(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant, "Demand Loan", pledge) create_pledge(loan_application) loan = create_demand_loan( @@ -92,18 +89,14 @@ def test_loan_topup(self): no_of_days = date_diff(last_date, first_date) + 1 - accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) / ( - days_in_year(get_datetime().year) * 100 - ) + (loan.loan_amount * loan.rate_of_interest * no_of_days) / (days_in_year(get_datetime().year) * 100) make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual_for_demand_loans(posting_date=add_days(last_date, 1)) # Should not be able to create loan disbursement entry before repayment - self.assertRaises( - frappe.ValidationError, make_loan_disbursement_entry, loan.name, 500000, first_date - ) + self.assertRaises(frappe.ValidationError, make_loan_disbursement_entry, loan.name, 500000, first_date) repayment_entry = create_repayment_entry( loan.name, self.applicant, add_days(get_last_day(nowdate()), 5), 611095.89 @@ -125,14 +118,10 @@ def test_loan_topup(self): def test_loan_topup_with_additional_pledge(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant, "Demand Loan", pledge) create_pledge(loan_application) - loan = create_demand_loan( - self.applicant, "Demand Loan", loan_application, posting_date="2019-10-01" - ) + loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date="2019-10-01") loan.submit() self.assertEqual(loan.loan_amount, 1000000) @@ -145,7 +134,7 @@ def test_loan_topup_with_additional_pledge(self): process_loan_interest_accrual_for_demand_loans(posting_date=last_date) amounts = calculate_amounts(loan.name, add_days(last_date, 1)) - previous_interest = amounts["interest_amount"] + amounts["interest_amount"] pledge1 = [{"loan_security": "Test Security 1", "qty": 2000.00}] @@ -157,6 +146,6 @@ def test_loan_topup_with_additional_pledge(self): amounts = calculate_amounts(loan.name, add_days(last_date, 15)) per_day_interest = get_per_day_interest(1500000, 13.5, "2019-10-30") - interest = per_day_interest * 15 + per_day_interest * 15 self.assertEqual(amounts["pending_principal_amount"], 1500000) diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py index e72d694b0f1c..a219aaefb16f 100644 --- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py @@ -72,7 +72,7 @@ def make_gl_entries(self, cancel=0, adv_adj=0): "credit_in_account_currency": self.interest_amount, "against_voucher_type": "Loan", "against_voucher": self.loan, - "remarks": ("Interest accrued from {0} to {1} against loan: {2}").format( + "remarks": ("Interest accrued from {} to {} against loan: {}").format( self.last_accrual_date, self.posting_date, self.loan ), "cost_center": cost_center, @@ -88,9 +88,7 @@ def make_gl_entries(self, cancel=0, adv_adj=0): # For Eg: If Loan disbursement date is '01-09-2019' and disbursed amount is 1000000 and # rate of interest is 13.5 then first loan interest accural will be on '01-10-2019' # which means interest will be accrued for 30 days which should be equal to 11095.89 -def calculate_accrual_amount_for_demand_loans( - loan, posting_date, process_loan_interest, accrual_type -): +def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type): from erpnext.loan_management.doctype.loan_repayment.loan_repayment import ( calculate_amounts, get_pending_principal_amount, @@ -104,9 +102,7 @@ def calculate_accrual_amount_for_demand_loans( pending_principal_amount = get_pending_principal_amount(loan) - interest_per_day = get_per_day_interest( - pending_principal_amount, loan.rate_of_interest, posting_date - ) + interest_per_day = get_per_day_interest(pending_principal_amount, loan.rate_of_interest, posting_date) payable_interest = interest_per_day * no_of_days pending_amounts = calculate_amounts(loan.name, posting_date, payment_type="Loan Closure") @@ -170,9 +166,7 @@ def make_accrual_interest_entry_for_demand_loans( ) for loan in open_loans: - calculate_accrual_amount_for_demand_loans( - loan, posting_date, process_loan_interest, accrual_type - ) + calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type) def make_accrual_interest_entry_for_term_loans( @@ -223,7 +217,7 @@ def get_term_loans(date, term_loan=None, loan_type=None): condition += " AND l.loan_type = %s" % frappe.db.escape(loan_type) term_loans = frappe.db.sql( - """SELECT l.name, l.total_payment, l.total_amount_paid, l.loan_account, + f"""SELECT l.name, l.total_payment, l.total_amount_paid, l.loan_account, l.interest_income_account, l.is_term_loan, l.disbursement_date, l.applicant_type, l.applicant, l.rate_of_interest, l.total_interest_payable, l.repayment_start_date, rs.name as payment_entry, rs.payment_date, rs.principal_amount, rs.interest_amount, rs.is_accrued , rs.balance_loan_amount @@ -232,12 +226,10 @@ def get_term_loans(date, term_loan=None, loan_type=None): AND l.docstatus=1 AND l.is_term_loan =1 AND rs.payment_date <= %s - AND rs.is_accrued=0 {0} + AND rs.is_accrued=0 {condition} AND rs.principal_amount > 0 AND l.status = 'Disbursed' - ORDER BY rs.payment_date""".format( - condition - ), + ORDER BY rs.payment_date""", (getdate(date)), as_dict=1, ) @@ -256,9 +248,7 @@ def make_loan_interest_accrual_entry(args): loan_interest_accrual.loan_account = args.loan_account loan_interest_accrual.pending_principal_amount = flt(args.pending_principal_amount, precision) loan_interest_accrual.interest_amount = flt(args.interest_amount, precision) - loan_interest_accrual.total_pending_interest_amount = flt( - args.total_pending_interest_amount, precision - ) + loan_interest_accrual.total_pending_interest_amount = flt(args.total_pending_interest_amount, precision) loan_interest_accrual.penalty_amount = flt(args.penalty_amount, precision) loan_interest_accrual.posting_date = args.posting_date or nowdate() loan_interest_accrual.process_loan_interest_accrual = args.process_loan_interest @@ -323,6 +313,4 @@ def get_per_day_interest(principal_amount, rate_of_interest, posting_date=None): if not posting_date: posting_date = getdate() - return flt( - (principal_amount * rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100) - ) + return flt((principal_amount * rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100)) diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py index fd59393b827f..ef209d340fa1 100644 --- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py @@ -60,9 +60,7 @@ def setUp(self): def test_loan_interest_accural(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant, "Demand Loan", pledge) create_pledge(loan_application) loan = create_demand_loan( self.applicant, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()) @@ -86,9 +84,7 @@ def test_loan_interest_accural(self): def test_accumulated_amounts(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] - loan_application = create_loan_application( - "_Test Company", self.applicant, "Demand Loan", pledge - ) + loan_application = create_loan_application("_Test Company", self.applicant, "Demand Loan", pledge) create_pledge(loan_application) loan = create_demand_loan( self.applicant, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()) diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index 0b057f85aa38..e11e30529831 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -70,7 +70,9 @@ def set_missing_values(self, amounts): shortfall_amount = flt( frappe.db.get_value( - "Loan Security Shortfall", {"loan": self.against_loan, "status": "Pending"}, "shortfall_amount" + "Loan Security Shortfall", + {"loan": self.against_loan, "status": "Pending"}, + "shortfall_amount", ) ) @@ -94,10 +96,10 @@ def check_future_entries(self): ) if future_repayment_date: - frappe.throw("Repayment already made till date {0}".format(get_datetime(future_repayment_date))) + frappe.throw(f"Repayment already made till date {get_datetime(future_repayment_date)}") def validate_amount(self): - precision = cint(frappe.db.get_default("currency_precision")) or 2 + cint(frappe.db.get_default("currency_precision")) or 2 if not self.amount_paid: frappe.throw(_("Amount paid cannot be zero")) @@ -115,7 +117,9 @@ def book_unaccrued_interest(self): ) no_of_days = ( - flt(flt(self.total_interest_paid - self.interest_payable, precision) / per_day_interest, 0) + flt( + flt(self.total_interest_paid - self.interest_payable, precision) / per_day_interest, 0 + ) - 1 ) @@ -139,7 +143,9 @@ def book_unaccrued_interest(self): "repayment_details", { "loan_interest_accrual": lia.name, - "paid_interest_amount": flt(self.total_interest_paid - self.interest_payable, precision), + "paid_interest_amount": flt( + self.total_interest_paid - self.interest_payable, precision + ), "paid_principal_amount": 0.0, "accrual_type": "Repayment", }, @@ -263,9 +269,7 @@ def check_future_accruals(self): if future_accrual_date: frappe.throw( - "Cannot cancel. Interest accruals already processed till {0}".format( - get_datetime(future_accrual_date) - ) + f"Cannot cancel. Interest accruals already processed till {get_datetime(future_accrual_date)}" ) def update_repayment_schedule(self, cancel=0): @@ -337,9 +341,7 @@ def allocate_interest_amount(self, interest_paid, repayment_details): return interest_paid, updated_entries - def allocate_principal_amount_for_term_loans( - self, interest_paid, repayment_details, updated_entries - ): + def allocate_principal_amount_for_term_loans(self, interest_paid, repayment_details, updated_entries): if interest_paid > 0: for lia, amounts in repayment_details.get("pending_accrual_entries", []).items(): paid_principal = 0 @@ -396,18 +398,16 @@ def allocate_excess_payment_for_demand_loans(self, interest_paid, repayment_deta def make_gl_entries(self, cancel=0, adv_adj=0): gle_map = [] if self.shortfall_amount and self.amount_paid > self.shortfall_amount: - remarks = "Shortfall repayment of {0}.
    Repayment against loan {1}".format( + remarks = "Shortfall repayment of {}.
    Repayment against loan {}".format( self.shortfall_amount, self.against_loan ) elif self.shortfall_amount: - remarks = "Shortfall repayment of {0} against loan {1}".format( - self.shortfall_amount, self.against_loan - ) + remarks = f"Shortfall repayment of {self.shortfall_amount} against loan {self.against_loan}" else: remarks = "Repayment against loan " + self.against_loan if self.reference_number: - remarks += "with reference no. {}".format(self.reference_number) + remarks += f"with reference no. {self.reference_number}" if hasattr(self, "repay_from_salary") and self.repay_from_salary: payment_account = self.payroll_payable_account @@ -513,7 +513,6 @@ def create_repayment_entry( payroll_payable_account=None, process_payroll_accounting_entry_based_on_employee=0, ): - lr = frappe.get_doc( { "doctype": "Loan Repayment", @@ -617,9 +616,7 @@ def regenerate_repayment_schedule(loan, cancel=0): balance_amount = get_pending_principal_amount(loan_doc) if loan_doc.repayment_method == "Repay Fixed Amount per Period": - monthly_repayment_amount = flt( - balance_amount / (original_repayment_schedule_len - accrued_entries) - ) + monthly_repayment_amount = flt(balance_amount / (original_repayment_schedule_len - accrued_entries)) else: repayment_period = loan_doc.repayment_periods - accrued_entries if not cancel and repayment_period > 0: @@ -718,9 +715,7 @@ def get_amounts(amounts, against_loan, posting_date): if ( no_of_late_days > 0 - and ( - not (hasattr(against_loan_doc, "repay_from_salary") and against_loan_doc.repay_from_salary) - ) + and (not (hasattr(against_loan_doc, "repay_from_salary") and against_loan_doc.repay_from_salary)) and entry.accrual_type == "Regular" ): penalty_amount += ( diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py index f0d595427530..238a9c9e5715 100644 --- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py +++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py @@ -74,7 +74,6 @@ def set_pledge_amount(self): maximum_loan_value = 0 for pledge in self.securities: - if not pledge.qty and not pledge.amount: frappe.throw(_("Qty or Amount is mandatory for loan security!")) diff --git a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py index 45c4459ac3fe..3bee111aab1f 100644 --- a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py +++ b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py @@ -13,7 +13,6 @@ def validate(self): self.validate_dates() def validate_dates(self): - if self.valid_from > self.valid_upto: frappe.throw(_("Valid From Time must be lesser than Valid Upto Time.")) diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py index b901e626b437..f3bcc60fc5b5 100644 --- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py +++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py @@ -47,9 +47,7 @@ def update_shortfall_status(loan, security_value, on_cancel=0): @frappe.whitelist() def add_security(loan): - loan_details = frappe.db.get_value( - "Loan", loan, ["applicant", "company", "applicant_type"], as_dict=1 - ) + loan_details = frappe.db.get_value("Loan", loan, ["applicant", "company", "applicant_type"], as_dict=1) loan_security_pledge = frappe.new_doc("Loan Security Pledge") loan_security_pledge.loan = loan @@ -61,7 +59,6 @@ def add_security(loan): def check_for_ltv_shortfall(process_loan_security_shortfall): - update_time = get_datetime() loan_security_price_map = frappe._dict( @@ -93,8 +90,6 @@ def check_for_ltv_shortfall(process_loan_security_shortfall): ) ) - loan_security_map = {} - for loan in loans: if loan.status == "Disbursed": outstanding_amount = ( diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py index 0ab7beb0fc76..b24a48b65218 100644 --- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py +++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py @@ -39,9 +39,7 @@ def validate_unpledge_qty(self): pledge_qty_map = get_pledged_security_qty(self.loan) - ltv_ratio_map = frappe._dict( - frappe.get_all("Loan Security Type", fields=["name", "loan_to_value_ratio"], as_list=1) - ) + frappe._dict(frappe.get_all("Loan Security Type", fields=["name", "loan_to_value_ratio"], as_list=1)) loan_security_price_map = frappe._dict( frappe.get_all( @@ -129,7 +127,7 @@ def update_loan_status(self, cancel=0): pledged_qty = 0 current_pledges = get_pledged_security_qty(self.loan) - for security, qty in current_pledges.items(): + for _security, qty in current_pledges.items(): pledged_qty += qty if not pledged_qty: @@ -138,7 +136,6 @@ def update_loan_status(self, cancel=0): @frappe.whitelist() def get_pledged_security_qty(loan): - current_pledges = {} unpledges = frappe._dict( diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py index 25c72d91a7c4..a1d9abdd35cc 100644 --- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py @@ -56,7 +56,6 @@ def process_loan_interest_accrual_for_demand_loans( def process_loan_interest_accrual_for_term_loans(posting_date=None, loan_type=None, loan=None): - if not term_loan_accrual_pending(posting_date or nowdate(), loan=loan): return diff --git a/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py b/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py index 02da8109ca90..2f1bcb1d8a70 100644 --- a/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py +++ b/erpnext/loan_management/report/applicant_wise_loan_security_exposure/applicant_wise_loan_security_exposure.py @@ -188,16 +188,14 @@ def get_applicant_wise_total_loan_security_qty(filters, loan_security_details): conditions = "AND company = %(company)s" unpledges = frappe.db.sql( - """ + f""" SELECT up.applicant, u.loan_security, sum(u.qty) as qty FROM `tabLoan Security Unpledge` up, `tabUnpledge` u WHERE u.parent = up.name AND up.status = 'Approved' {conditions} GROUP BY up.applicant, u.loan_security - """.format( - conditions=conditions - ), + """, filters, as_dict=1, ) @@ -206,16 +204,14 @@ def get_applicant_wise_total_loan_security_qty(filters, loan_security_details): applicant_wise_unpledges.setdefault((unpledge.applicant, unpledge.loan_security), unpledge.qty) pledges = frappe.db.sql( - """ + f""" SELECT lp.applicant_type, lp.applicant, p.loan_security, sum(p.qty) as qty FROM `tabLoan Security Pledge` lp, `tabPledge`p WHERE p.parent = lp.name AND lp.status = 'Pledged' {conditions} GROUP BY lp.applicant, p.loan_security - """.format( - conditions=conditions - ), + """, filters, as_dict=1, ) diff --git a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py index 58a7880a4592..9e1c496779c6 100644 --- a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py +++ b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py @@ -219,9 +219,7 @@ def get_active_loan_details(filters): def get_sanctioned_amount_map(): return frappe._dict( - frappe.get_all( - "Sanctioned Loan Amount", fields=["applicant", "sanctioned_amount_limit"], as_list=1 - ) + frappe.get_all("Sanctioned Loan Amount", fields=["applicant", "sanctioned_amount_limit"], as_list=1) ) @@ -309,9 +307,7 @@ def get_interest_accruals(loans, filters): def get_penal_interest_rate_map(): - return frappe._dict( - frappe.get_all("Loan Type", fields=["name", "penalty_interest_rate"], as_list=1) - ) + return frappe._dict(frappe.get_all("Loan Type", fields=["name", "penalty_interest_rate"], as_list=1)) def get_loan_wise_pledges(filters): @@ -324,16 +320,14 @@ def get_loan_wise_pledges(filters): conditions = "AND company = %(company)s" unpledges = frappe.db.sql( - """ + f""" SELECT up.loan, u.loan_security, sum(u.qty) as qty FROM `tabLoan Security Unpledge` up, `tabUnpledge` u WHERE u.parent = up.name AND up.status = 'Approved' {conditions} GROUP BY up.loan, u.loan_security - """.format( - conditions=conditions - ), + """, filters, as_dict=1, ) @@ -342,16 +336,14 @@ def get_loan_wise_pledges(filters): loan_wise_unpledges.setdefault((unpledge.loan, unpledge.loan_security), unpledge.qty) pledges = frappe.db.sql( - """ + f""" SELECT lp.loan, p.loan_security, sum(p.qty) as qty FROM `tabLoan Security Pledge` lp, `tabPledge`p WHERE p.parent = lp.name AND lp.status = 'Pledged' {conditions} GROUP BY lp.loan, p.loan_security - """.format( - conditions=conditions - ), + """, filters, as_dict=1, ) diff --git a/erpnext/loan_management/report/loan_security_status/loan_security_status.py b/erpnext/loan_management/report/loan_security_status/loan_security_status.py index 9a5a18001ead..acec5271ad14 100644 --- a/erpnext/loan_management/report/loan_security_status/loan_security_status.py +++ b/erpnext/loan_management/report/loan_security_status/loan_security_status.py @@ -61,12 +61,11 @@ def get_columns(filters): def get_data(filters): - data = [] conditions = get_conditions(filters) loan_security_pledges = frappe.db.sql( - """ + f""" SELECT p.name, p.applicant, p.loan, p.status, p.pledge_time, c.loan_security, c.qty, c.loan_security_price, c.amount @@ -77,9 +76,7 @@ def get_data(filters): AND c.parent = p.name AND p.company = %(company)s {conditions} - """.format( - conditions=conditions - ), + """, (filters), as_dict=1, ) # nosec diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py index 8e4af3ac172d..08e56e06c73a 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py @@ -126,7 +126,7 @@ def create_schedule_list(self, start_date, end_date, no_of_visit, sales_person): date_diff = (getdate(end_date) - getdate(start_date)).days add_by = date_diff / no_of_visit - for visit in range(cint(no_of_visit)): + for _visit in range(cint(no_of_visit)): if getdate(start_date_copy) < getdate(end_date): start_date_copy = add_days(start_date_copy, add_by) if len(schedule_list) < no_of_visit: @@ -153,9 +153,8 @@ def validate_schedule_date_for_holiday_list(self, schedule_date, sales_person): ) if not validated and holidays: - # max iterations = len(holidays) - for i in range(len(holidays)): + for _i in range(len(holidays)): if schedule_date in holidays: schedule_date = add_days(schedule_date, -1) else: @@ -214,7 +213,7 @@ def validate_items_table_change(self): doc_before_save = self.get_doc_before_save() if not doc_before_save: return - for prev_item, item in zip(doc_before_save.items, self.items): + for prev_item, item in zip(doc_before_save.items, self.items, strict=False): fields = [ "item_code", "start_date", @@ -279,9 +278,7 @@ def validate_serial_no(self, item_code, serial_nos, amc_start_date): ) ) - if sr_details.amc_expiry_date and getdate(sr_details.amc_expiry_date) >= getdate( - amc_start_date - ): + if sr_details.amc_expiry_date and getdate(sr_details.amc_expiry_date) >= getdate(amc_start_date): throw( _("Serial No {0} is under maintenance contract upto {1}").format( serial_no, sr_details.amc_expiry_date diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py index a0974e99040c..2254eb66f042 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py @@ -36,13 +36,17 @@ def validate_maintenance_date(self): self.mntc_date ) > get_datetime(end_date): frappe.throw( - _("Date must be between {0} and {1}").format(format_date(start_date), format_date(end_date)) + _("Date must be between {0} and {1}").format( + format_date(start_date), format_date(end_date) + ) ) else: for purpose in self.purposes: if purpose.maintenance_schedule_detail: item_ref = frappe.db.get_value( - "Maintenance Schedule Detail", purpose.maintenance_schedule_detail, "item_reference" + "Maintenance Schedule Detail", + purpose.maintenance_schedule_detail, + "item_reference", ) if item_ref: start_date, end_date = frappe.db.get_value( diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py index 83629092fa42..aaa127591fe9 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py @@ -161,7 +161,7 @@ def validate_against_blanket_order(order_doc): allowed_qty = remaining_qty + (remaining_qty * (allowance / 100)) if allowed_qty < item_data[item.item_code]: frappe.throw( - _("Item {0} cannot be ordered more than {1} against Blanket Order {2}.").format( - item.item_code, allowed_qty, bo_name - ) + _( + "Item {0} cannot be ordered more than {1} against Blanket Order {2}." + ).format(item.item_code, allowed_qty, bo_name) ) diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py index 3f3b6f092c08..a6eb18f47bc2 100644 --- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py @@ -98,9 +98,7 @@ def test_party_item_code(self): customer = "_Test Customer" supplier = "_Test Supplier" - if not frappe.db.exists( - "Item Customer Detail", {"customer_name": customer, "parent": item_code} - ): + if not frappe.db.exists("Item Customer Detail", {"customer_name": customer, "parent": item_code}): item_doc.append("customer_items", {"customer_name": customer, "ref_code": "CUST-REF-1"}) item_doc.save() diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 03190e7b965a..f18ca1f796a1 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -5,7 +5,6 @@ import re from collections import deque from operator import itemgetter -from typing import Dict, List import frappe from frappe import _ @@ -33,11 +32,9 @@ class BOMTree: # ref: https://docs.python.org/3/reference/datamodel.html#slots __slots__ = ["name", "child_items", "is_bom", "item_code", "qty", "exploded_qty", "bom_qty"] - def __init__( - self, name: str, is_bom: bool = True, exploded_qty: float = 1.0, qty: float = 1 - ) -> None: + def __init__(self, name: str, is_bom: bool = True, exploded_qty: float = 1.0, qty: float = 1) -> None: self.name = name # name of node, BOM number if is_bom else item_code - self.child_items: List["BOMTree"] = [] # list of child items + self.child_items: list["BOMTree"] = [] # list of child items self.is_bom = is_bom # true if the node is a BOM and not a leaf item self.item_code: str = None # item_code associated with node self.qty = qty # required unit quantity to make one unit of parent item. @@ -63,7 +60,7 @@ def __create_tree(self): BOMTree(item.item_code, is_bom=False, exploded_qty=exploded_qty, qty=qty) ) - def level_order_traversal(self) -> List["BOMTree"]: + def level_order_traversal(self) -> list["BOMTree"]: """Get level order traversal of tree. E.g. for following tree the traversal will return list of nodes in order from top to bottom. BOM: @@ -152,7 +149,7 @@ def autoname(self): self.name = name @staticmethod - def get_next_version_index(existing_boms: List[str]) -> int: + def get_next_version_index(existing_boms: list[str]) -> int: # split by "/" and "-" delimiters = ["/", "-"] pattern = "|".join(map(re.escape, delimiters)) @@ -341,10 +338,7 @@ def get_bom_material_detail(self, args=None): return ret_item def validate_bom_currency(self, item): - if ( - item.get("bom_no") - and frappe.db.get_value("BOM", item.get("bom_no"), "currency") != self.currency - ): + if item.get("bom_no") and frappe.db.get_value("BOM", item.get("bom_no"), "currency") != self.currency: frappe.throw( _("Row {0}: Currency of the BOM #{1} should be equal to the selected currency {2}").format( item.idx, item.bom_no, self.currency @@ -361,9 +355,9 @@ def get_rm_rate(self, arg): rate = get_valuation_rate(arg) elif arg: # Customer Provided parts and Supplier sourced parts will have zero rate - if not frappe.db.get_value( - "Item", arg["item_code"], "is_customer_provided_item" - ) and not arg.get("sourced_by_supplier"): + if not frappe.db.get_value("Item", arg["item_code"], "is_customer_provided_item") and not arg.get( + "sourced_by_supplier" + ): if arg.get("bom_no") and self.set_rate_of_sub_assembly_item_based_on_bom: rate = flt(self.get_bom_unitcost(arg["bom_no"])) * (arg.get("conversion_factor") or 1) else: @@ -379,7 +373,8 @@ def get_rm_rate(self, arg): ) else: frappe.msgprint( - _("{0} not found for item {1}").format(self.rm_cost_as_per, arg["item_code"]), alert=True + _("{0} not found for item {1}").format(self.rm_cost_as_per, arg["item_code"]), + alert=True, ) return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1) @@ -727,7 +722,7 @@ def calculate_exploded_cost(self): # Only db_update if changed row.db_update() - def get_rm_rate_map(self) -> Dict[str, float]: + def get_rm_rate_map(self) -> dict[str, float]: "Create Raw Material-Rate map for Exploded Items. Fetch rate from Items table or Subassembly BOM." rm_rate_map = {} @@ -1096,9 +1091,7 @@ def get_bom_items_as_dict( @frappe.whitelist() def get_bom_items(bom, company, qty=1, fetch_exploded=1): - items = get_bom_items_as_dict( - bom, company, qty, fetch_exploded, include_non_stock_items=True - ).values() + items = get_bom_items_as_dict(bom, company, qty, fetch_exploded, include_non_stock_items=True).values() items = list(items) items.sort(key=functools.cmp_to_key(lambda a, b: a.item_code > b.item_code and 1 or -1)) return items @@ -1230,9 +1223,7 @@ def add_operations_cost(stock_entry, work_order=None, expense_account=None): ) if work_order and work_order.additional_operating_cost and work_order.qty: - additional_operating_cost_per_unit = flt(work_order.additional_operating_cost) / flt( - work_order.qty - ) + additional_operating_cost_per_unit = flt(work_order.additional_operating_cost) / flt(work_order.qty) if additional_operating_cost_per_unit: stock_entry.append( @@ -1294,7 +1285,7 @@ def get_bom_diff(bom1, bom2): # check for deletions for d in old_value: - if not d.get(identifier) in new_row_by_identifier: + if d.get(identifier) not in new_row_by_identifier: out.removed.append([df.fieldname, d.as_dict()]) return out @@ -1309,14 +1300,12 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): order_by = "idx desc, name, item_name" fields = ["name", "item_name", "item_group", "description"] - fields.extend( - [field for field in searchfields if not field in ["name", "item_group", "description"]] - ) + fields.extend([field for field in searchfields if field not in ["name", "item_group", "description"]]) searchfields = searchfields + [ field for field in [searchfield or "name", "item_code", "item_group", "item_name"] - if not field in searchfields + if field not in searchfields ] query_filters = {"disabled": 0, "ifnull(end_of_life, '3099-12-31')": (">", today())} @@ -1324,12 +1313,12 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): or_cond_filters = {} if txt: for s_field in searchfields: - or_cond_filters[s_field] = ("like", "%{0}%".format(txt)) + or_cond_filters[s_field] = ("like", f"%{txt}%") barcodes = frappe.get_all( "Item Barcode", fields=["distinct parent as item_code"], - filters={"barcode": ("like", "%{0}%".format(txt))}, + filters={"barcode": ("like", f"%{txt}%")}, ) barcodes = [d.item_code for d in barcodes] @@ -1430,9 +1419,7 @@ def get_scrap_items_from_sub_assemblies(bom_no, company, qty, scrap_items=None): continue qty = flt(row.qty) * flt(qty) - items = get_bom_items_as_dict( - row.bom_no, company, qty=qty, fetch_exploded=0, fetch_scrap_items=1 - ) + items = get_bom_items_as_dict(row.bom_no, company, qty=qty, fetch_exploded=0, fetch_scrap_items=1) scrap_items.update(items) get_scrap_items_from_sub_assemblies(row.bom_no, company, qty, scrap_items) diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 2debf9191efb..d02b51ca6e7a 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -10,7 +10,6 @@ from frappe.utils import cstr, flt from erpnext.controllers.tests.test_subcontracting_controller import ( - make_stock_in_entry, set_backflush_based_on, ) from erpnext.manufacturing.doctype.bom.bom import BOMRecursionError, item_query, make_variant_bom @@ -200,9 +199,7 @@ def test_bom_cost_multi_uom_based_on_valuation_rate(self): reset_item_valuation_rate( item_code="_Test Item", - warehouse_list=frappe.get_all( - "Warehouse", {"is_group": 0, "company": bom.company}, pluck="name" - ), + warehouse_list=frappe.get_all("Warehouse", {"is_group": 0, "company": bom.company}, pluck="name"), qty=200, rate=200, ) @@ -344,7 +341,7 @@ def test_bom_tree_representation(self): self.assertEqual(len(reqd_order), len(created_order)) - for reqd_item, created_item in zip(reqd_order, created_order): + for reqd_item, created_item in zip(reqd_order, created_order, strict=False): self.assertEqual(reqd_item, created_item.item_code) @timeout @@ -383,7 +380,7 @@ def test_generated_variant_bom(self): self.assertEqual(len(reqd_order), len(created_order)) - for reqd_item, created_item in zip(reqd_order, created_order): + for reqd_item, created_item in zip(reqd_order, created_order, strict=False): self.assertEqual(reqd_item.item_code, created_item.item_code) self.assertEqual(reqd_item.qty, created_item.qty) self.assertEqual(reqd_item.exploded_qty, created_item.exploded_qty) @@ -452,9 +449,7 @@ def test_bom_item_query(self): test_items = query(txt="_Test") filtered = query(txt="_Test Item 2") - self.assertNotEqual( - len(test_items), len(filtered), msg="Item filtering showing excessive results" - ) + self.assertNotEqual(len(test_items), len(filtered), msg="Item filtering showing excessive results") self.assertTrue(0 < len(filtered) <= 3, msg="Item filtering showing excessive results") @timeout @@ -516,7 +511,6 @@ def test_bom_name_length(self): @timeout def test_version_index(self): - bom = frappe.new_doc("BOM") version_index_test_cases = [ @@ -571,7 +565,6 @@ def test_bom_versioning(self): @timeout def test_clear_inpection_quality(self): - bom = frappe.copy_doc(test_records[2], ignore_no_copy=True) bom.docstatus = 0 bom.is_default = 0 @@ -686,9 +679,7 @@ def test_bom_cost_update_flag(self): bom = make_bom(item=fg_item, raw_materials=[rm_item]) - create_stock_reconciliation( - item_code=rm_item, warehouse="_Test Warehouse - _TC", qty=100, rate=600 - ) + create_stock_reconciliation(item_code=rm_item, warehouse="_Test Warehouse - _TC", qty=100, rate=600) bom.load_from_db() bom.update_cost() @@ -699,8 +690,6 @@ def test_bom_cost_update_flag(self): self.assertFalse(bom.flags.cost_updated) def test_bom_with_service_item_cost(self): - from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry - rm_item = make_item(properties={"is_stock_item": 1, "valuation_rate": 1000.0}).name service_item = make_item(properties={"is_stock_item": 0}).name @@ -793,7 +782,9 @@ def create_items(bom_tree): for item_code, subtree in bom_tree.items(): bom_item_code = prefix + item_code if not frappe.db.exists("Item", bom_item_code): - frappe.get_doc(doctype="Item", item_code=bom_item_code, item_group="_Test Item Group").insert() + frappe.get_doc( + doctype="Item", item_code=bom_item_code, item_group="_Test Item Group" + ).insert() create_items(subtree) create_items(tree) 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 e9867468f98f..02c43a8beff3 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py @@ -1,7 +1,7 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt import json -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any import frappe from frappe import _ @@ -30,9 +30,7 @@ def clear_old_logs(days=None): table = DocType("BOM Update Log") frappe.db.delete( table, - filters=( - (table.modified < (Now() - Interval(days=days))) & (table.update_type == "Update Cost") - ), + filters=((table.modified < (Now() - Interval(days=days))) & (table.update_type == "Update Cost")), ) def validate(self): @@ -102,7 +100,7 @@ def on_submit(self): def run_replace_bom_job( doc: "BOMUpdateLog", - boms: Optional[Dict[str, str]] = None, + boms: dict[str, str] | None = None, ) -> None: try: doc.db_set("status", "In Progress") @@ -125,8 +123,8 @@ def run_replace_bom_job( def process_boms_cost_level_wise( - update_doc: "BOMUpdateLog", parent_boms: List[str] = None -) -> Union[None, Tuple]: + update_doc: "BOMUpdateLog", parent_boms: list[str] | None = None +) -> None | tuple: "Queue jobs at the start of new BOM Level in 'Update Cost' Jobs." current_boms = {} @@ -159,9 +157,7 @@ def process_boms_cost_level_wise( handle_exception(update_doc) -def queue_bom_cost_jobs( - current_boms_list: List[str], update_doc: "BOMUpdateLog", current_level: int -) -> None: +def queue_bom_cost_jobs(current_boms_list: list[str], update_doc: "BOMUpdateLog", current_level: int) -> None: "Queue batches of 20k BOMs of the same level to process parallelly" batch_no = 0 @@ -245,8 +241,8 @@ def resume_bom_cost_update_jobs(): def get_processed_current_boms( - log: Dict[str, Any], bom_batches: Dict[str, Any] -) -> Tuple[List[str], Dict[str, Any]]: + log: dict[str, Any], bom_batches: dict[str, Any] +) -> tuple[list[str], dict[str, Any]]: """ Aggregate all BOMs from BOM Update Batch rows into 'processed_boms' field and into current boms list. diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py index f013b88e9467..fed7a002e75a 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py +++ b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py @@ -4,7 +4,7 @@ import copy import json from collections import defaultdict -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from erpnext.manufacturing.doctype.bom_update_log.bom_update_log import BOMUpdateLog @@ -13,7 +13,7 @@ from frappe import _ -def replace_bom(boms: Dict, log_name: str) -> None: +def replace_bom(boms: dict, log_name: str) -> None: "Replace current BOM with new BOM in parent BOMs." current_bom = boms.get("current_bom") @@ -43,9 +43,7 @@ def replace_bom(boms: Dict, log_name: str) -> None: bom_obj.save_version() -def update_cost_in_level( - doc: "BOMUpdateLog", bom_list: List[str], batch_name: Union[int, str] -) -> None: +def update_cost_in_level(doc: "BOMUpdateLog", bom_list: list[str], batch_name: int | str) -> None: "Updates Cost for BOMs within a given level. Runs via background jobs." try: @@ -69,7 +67,7 @@ def update_cost_in_level( frappe.db.commit() # nosemgrep -def get_ancestor_boms(new_bom: str, bom_list: Optional[List] = None) -> List: +def get_ancestor_boms(new_bom: str, bom_list: list | None = None) -> list: "Recursively get all ancestors of BOM." bom_list = bom_list or [] @@ -101,9 +99,7 @@ def update_new_bom_in_bom_items(unit_cost: float, current_bom: str, new_bom: str .set(bom_item.bom_no, new_bom) .set(bom_item.rate, unit_cost) .set(bom_item.amount, (bom_item.stock_qty * unit_cost)) - .where( - (bom_item.bom_no == current_bom) & (bom_item.docstatus < 2) & (bom_item.parenttype == "BOM") - ) + .where((bom_item.bom_no == current_bom) & (bom_item.docstatus < 2) & (bom_item.parenttype == "BOM")) ).run() @@ -116,7 +112,7 @@ def get_bom_unit_cost(bom_name: str) -> float: return frappe.utils.flt(new_bom_unitcost[0][0]) -def update_cost_in_boms(bom_list: List[str]) -> None: +def update_cost_in_boms(bom_list: list[str]) -> None: "Updates cost in given BOMs. Returns current and total updated BOMs." for index, bom in enumerate(bom_list): @@ -128,9 +124,7 @@ def update_cost_in_boms(bom_list: List[str]) -> None: frappe.db.commit() # nosemgrep -def get_next_higher_level_boms( - child_boms: List[str], processed_boms: Dict[str, bool] -) -> List[str]: +def get_next_higher_level_boms(child_boms: list[str], processed_boms: dict[str, bool]) -> list[str]: "Generate immediate higher level dependants with no unresolved dependencies (children)." def _all_children_are_processed(parent_bom): @@ -156,7 +150,7 @@ def _all_children_are_processed(parent_bom): return list(resolved_dependants) -def get_leaf_boms() -> List[str]: +def get_leaf_boms() -> list[str]: "Get BOMs that have no dependencies." bom = frappe.qb.DocType("BOM") @@ -209,7 +203,7 @@ def _generate_dependence_map() -> defaultdict: return child_parent_map, parent_child_map -def set_values_in_log(log_name: str, values: Dict[str, Any], commit: bool = False) -> None: +def set_values_in_log(log_name: str, values: dict[str, Any], commit: bool = False) -> None: "Update BOM Update Log record." if not values: diff --git a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py index 30e6f5e2091c..13bf69f672f1 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py @@ -81,9 +81,7 @@ def test_bom_replace_for_root_bom(self): for item_code in items: remove_bom(item_code) - bom_tree = { - "B-Item A": {"B-Item B": {"B-Item C": {}}, "B-Item D": {"B-Item E": {"B-Item F": {}}}} - } + bom_tree = {"B-Item A": {"B-Item B": {"B-Item C": {}}, "B-Item D": {"B-Item E": {"B-Item F": {}}}}} root_bom = create_nested_bom(bom_tree, prefix="") 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 d16fcd083264..288b7be35ee0 100644 --- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py @@ -2,7 +2,7 @@ # For license information, please see license.txt import json -from typing import TYPE_CHECKING, Dict, Literal, Optional, Union +from typing import TYPE_CHECKING, Literal if TYPE_CHECKING: from erpnext.manufacturing.doctype.bom_update_log.bom_update_log import BOMUpdateLog @@ -16,9 +16,7 @@ class BOMUpdateTool(Document): @frappe.whitelist() -def enqueue_replace_bom( - boms: Optional[Union[Dict, str]] = None, args: Optional[Union[Dict, str]] = None -) -> "BOMUpdateLog": +def enqueue_replace_bom(boms: dict | str | None = None, args: dict | str | None = None) -> "BOMUpdateLog": """Returns a BOM Update Log (that queues a job) for BOM Replacement.""" boms = boms or args if isinstance(boms, str): @@ -48,7 +46,7 @@ def auto_update_latest_price_in_all_boms() -> None: def create_bom_update_log( - boms: Optional[Dict[str, str]] = None, + boms: dict[str, str] | None = None, update_type: Literal["Replace BOM", "Update Cost"] = "Replace BOM", ) -> "BOMUpdateLog": """Creates a BOM Update Log that handles the background job.""" diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 841055e2783f..8c562eff83fb 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -2,7 +2,6 @@ # For license information, please see license.txt import datetime import json -from typing import Optional import frappe from frappe import _, bold @@ -52,9 +51,7 @@ class JobCardOverTransferError(frappe.ValidationError): class JobCard(Document): def onload(self): - excess_transfer = frappe.db.get_single_value( - "Manufacturing Settings", "job_card_excess_transfer" - ) + excess_transfer = frappe.db.get_single_value("Manufacturing Settings", "job_card_excess_transfer") self.set_onload("job_card_excess_transfer", excess_transfer) self.set_onload("work_order_closed", self.is_work_order_closed()) self.set_onload("has_stock_entry", self.has_stock_entry()) @@ -83,9 +80,7 @@ def validate_job_card_qty(self): wo_qty = flt(frappe.get_cached_value("Work Order", self.work_order, "qty")) - completed_qty = flt( - frappe.db.get_value("Work Order Operation", self.operation_id, "completed_qty") - ) + completed_qty = flt(frappe.db.get_value("Work Order Operation", self.operation_id, "completed_qty")) over_production_percentage = flt( frappe.db.get_single_value("Manufacturing Settings", "overproduction_percentage_for_work_order") @@ -259,7 +254,7 @@ def has_overlap(self, production_capacity, time_logs): return True return overlap - def get_workstation_based_on_available_slot(self, existing) -> Optional[str]: + def get_workstation_based_on_available_slot(self, existing) -> str | None: workstations = get_workstations(self.workstation_type) if workstations: busy_workstations = [row.workstation for row in existing] @@ -339,7 +334,9 @@ def check_workstation_time(self, row): # If remaining time fit in workstation time logs else split hours as per workstation time if time_in_mins > row.remaining_time_in_mins: - row.planned_end_time = add_to_date(row.planned_start_time, minutes=row.remaining_time_in_mins) + row.planned_end_time = add_to_date( + row.planned_start_time, minutes=row.remaining_time_in_mins + ) row.remaining_time_in_mins = 0 else: row.planned_end_time = add_to_date(row.planned_start_time, minutes=time_in_mins) @@ -459,7 +456,9 @@ def update_sub_operation_status(self): row.completed_time = row.completed_time / len(set(operation_deatils.employee)) if operation_deatils.completed_qty: - row.completed_qty = operation_deatils.completed_qty / len(set(operation_deatils.employee)) + row.completed_qty = operation_deatils.completed_qty / len( + set(operation_deatils.employee) + ) else: row.status = "Pending" row.completed_time = 0.0 @@ -530,10 +529,7 @@ def validate_transfer_qty(self): ) def validate_job_card(self): - if ( - self.work_order - and frappe.get_cached_value("Work Order", self.work_order, "status") == "Stopped" - ): + if self.work_order and frappe.get_cached_value("Work Order", self.work_order, "status") == "Stopped": frappe.throw( _("Transaction not allowed against stopped Work Order {0}").format( get_link_to_form("Work Order", self.work_order) @@ -552,9 +548,7 @@ def validate_job_card(self): flt(self.total_completed_qty, precision) + flt(self.process_loss_qty, precision) ) - if self.for_quantity and flt(total_completed_qty, precision) != flt( - self.for_quantity, precision - ): + if self.for_quantity and flt(total_completed_qty, precision) != flt(self.for_quantity, precision): total_completed_qty_label = bold(_("Total Completed Qty")) qty_to_manufacture = bold(_("Qty to Manufacture")) @@ -588,9 +582,8 @@ def update_work_order(self): return for_quantity, time_in_mins, process_loss_qty = 0, 0, 0 - from_time_list, to_time_list = [], [] + _from_time_list, _to_time_list = [], [] - field = "operation_id" data = self.get_current_operation_data() if data and len(data) > 0: for_quantity = flt(data[0].completed_qty) @@ -626,9 +619,7 @@ def validate_produced_quantity(self, for_quantity, process_loss_qty, wo): if wo.produced_qty > for_quantity + process_loss_qty: first_part_msg = _( "The {0} {1} is used to calculate the valuation cost for the finished good {2}." - ).format( - frappe.bold(_("Job Card")), frappe.bold(self.name), frappe.bold(self.production_item) - ) + ).format(frappe.bold(_("Job Card")), frappe.bold(self.name), frappe.bold(self.production_item)) second_part_msg = _( "Kindly cancel the Manufacturing Entries first against the work order {0}." @@ -695,9 +686,7 @@ def _get_job_card_items_transferred_qty(ste_doc): from frappe.query_builder.functions import Sum job_card_items_transferred_qty = {} - job_card_items = [ - x.get("job_card_item") for x in ste_doc.get("items") if x.get("job_card_item") - ] + job_card_items = [x.get("job_card_item") for x in ste_doc.get("items") if x.get("job_card_item")] if job_card_items: se = frappe.qb.DocType("Stock Entry") @@ -822,9 +811,7 @@ def set_status(self, update_status=False): def set_wip_warehouse(self): if not self.wip_warehouse: - self.wip_warehouse = frappe.db.get_single_value( - "Manufacturing Settings", "default_wip_warehouse" - ) + self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse") def validate_operation_id(self): if ( @@ -864,7 +851,7 @@ def validate_sequence_id(self): order_by="sequence_id, idx", ) - message = "Job Card {0}: As per the sequence of the operations in the work order {1}".format( + message = "Job Card {}: As per the sequence of the operations in the work order {}".format( bold(self.name), bold(get_link_to_form("Work Order", self.work_order)) ) @@ -929,7 +916,7 @@ def get_operations(doctype, txt, searchfield, start, page_len, filters): return [] args = {"parent": filters.get("work_order")} if txt: - args["operation"] = ("like", "%{0}%".format(txt)) + args["operation"] = ("like", f"%{txt}%") return frappe.get_all( "Work Order Operation", @@ -1050,16 +1037,14 @@ def get_job_details(start, end, filters=None): conditions = get_filters_cond("Job Card", filters, []) job_cards = frappe.db.sql( - """ SELECT `tabJob Card`.name, `tabJob Card`.work_order, + f""" SELECT `tabJob Card`.name, `tabJob Card`.work_order, `tabJob Card`.status, ifnull(`tabJob Card`.remarks, ''), min(`tabJob Card Time Log`.from_time) as from_time, max(`tabJob Card Time Log`.to_time) as to_time FROM `tabJob Card` , `tabJob Card Time Log` WHERE - `tabJob Card`.name = `tabJob Card Time Log`.parent {0} - group by `tabJob Card`.name""".format( - conditions - ), + `tabJob Card`.name = `tabJob Card Time Log`.parent {conditions} + group by `tabJob Card`.name""", as_dict=1, ) diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py index e7fbcda7ab0d..d9a2046ea59a 100644 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.py +++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py @@ -59,7 +59,6 @@ def tearDown(self): frappe.db.rollback() def test_job_card_operations(self): - job_cards = frappe.get_all( "Job Card", filters={"work_order": self.work_order.name}, fields=["operation_id", "name"] ) @@ -252,7 +251,6 @@ def test_job_card_excess_material_transfer(self): @change_settings("Manufacturing Settings", {"job_card_excess_transfer": 0}) def test_job_card_excess_material_transfer_block(self): - self.transfer_material_against = "Job Card" self.source_warehouse = "Stores - _TC" @@ -276,7 +274,6 @@ def test_job_card_excess_material_transfer_block(self): @change_settings("Manufacturing Settings", {"job_card_excess_transfer": 0}) def test_job_card_excess_material_transfer_with_no_reference(self): - self.transfer_material_against = "Job Card" self.source_warehouse = "Stores - _TC" diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py index 730a85752474..fc885760ef54 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py @@ -14,8 +14,7 @@ class ManufacturingSettings(Document): def get_mins_between_operations(): return relativedelta( - minutes=cint(frappe.db.get_single_value("Manufacturing Settings", "mins_between_operations")) - or 10 + minutes=cint(frappe.db.get_single_value("Manufacturing Settings", "mins_between_operations")) or 10 ) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 7efc4f75e5bb..aedd25a05e01 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -311,9 +311,7 @@ def get_mr_items(self): if not self.get("material_requests") or not self.get_so_mr_list( "material_request", "material_requests" ): - frappe.throw( - _("Please fill the Material Requests table"), title=_("Material Requests Required") - ) + frappe.throw(_("Please fill the Material Requests table"), title=_("Material Requests Required")) mr_list = self.get_so_mr_list("material_request", "material_requests") @@ -591,7 +589,10 @@ def get_production_items(self): item_dict[(d.item_code, d.material_request_item, d.warehouse)] = item_details else: item_details.update( - {"qty": flt(item_dict.get(key, {}).get("qty")) + (flt(d.planned_qty) - flt(d.ordered_qty))} + { + "qty": flt(item_dict.get(key, {}).get("qty")) + + (flt(d.planned_qty) - flt(d.ordered_qty)) + } ) item_dict[key] = item_details @@ -617,7 +618,7 @@ def make_work_order(self): def make_work_order_for_finished_goods(self, wo_list, default_warehouses): items_data = self.get_production_items() - for key, item in items_data.items(): + for _key, item in items_data.items(): if self.sub_assembly_items: item["use_multi_level_bom"] = 0 @@ -753,7 +754,7 @@ def make_material_request(self): key = "{}:{}:{}".format(item.sales_order, material_request_type, item_doc.customer or "") schedule_date = item.schedule_date or add_days(nowdate(), cint(item_doc.lead_time_days)) - if not key in material_request_map: + if key not in material_request_map: # make a new MR for the combination material_request_map[key] = frappe.new_doc("Material Request") material_request = material_request_map[key] @@ -803,7 +804,7 @@ def make_material_request(self): if material_request_list: material_request_list = [ - """{1}""".format(m.name, m.name) + f"""{m.name}""" for m in material_request_list ] msgprint(_("{0} created").format(comma_and(material_request_list))) @@ -929,9 +930,7 @@ def combine_subassembly_items(self, sub_assembly_items_store): return sub_assembly_items_store def all_items_completed(self): - all_items_produced = all( - flt(d.planned_qty) - flt(d.produced_qty) < 0.000001 for d in self.po_items - ) + all_items_produced = all(flt(d.planned_qty) - flt(d.produced_qty) < 0.000001 for d in self.po_items) if not all_items_produced: return False @@ -974,9 +973,7 @@ def download_raw_materials(doc, warehouses=None): doc.warehouse = None frappe.flags.show_qty_in_stock_uom = 1 - items = get_items_for_material_requests( - doc, warehouses=warehouses, get_parent_warehouse_data=True - ) + items = get_items_for_material_requests(doc, warehouses=warehouses, get_parent_warehouse_data=True) for d in items: item_list.append( @@ -1020,9 +1017,7 @@ def download_raw_materials(doc, warehouses=None): build_csv_response(item_list, doc.name) -def get_exploded_items( - item_details, company, bom_no, include_non_stock_items, planned_qty=1, doc=None -): +def get_exploded_items(item_details, company, bom_no, include_non_stock_items, planned_qty=1, doc=None): bei = frappe.qb.DocType("BOM Explosion Item") bom = frappe.qb.DocType("BOM") item = frappe.qb.DocType("Item") @@ -1175,11 +1170,7 @@ def get_material_request_items( elif total_qty > bin_dict.get("projected_qty", 0): required_qty = total_qty - bin_dict.get("projected_qty", 0) - if ( - doc.get("consider_minimum_order_qty") - and required_qty > 0 - and required_qty < row["min_order_qty"] - ): + if doc.get("consider_minimum_order_qty") and required_qty > 0 and required_qty < row["min_order_qty"]: required_qty = row["min_order_qty"] item_group_defaults = get_item_group_defaults(row.item_code, company) @@ -1203,9 +1194,7 @@ def get_material_request_items( if include_safety_stock: required_qty += flt(row["safety_stock"]) - item_details = frappe.get_cached_value( - "Item", row.item_code, ["purchase_uom", "stock_uom"], as_dict=1 - ) + item_details = frappe.get_cached_value("Item", row.item_code, ["purchase_uom", "stock_uom"], as_dict=1) conversion_factor = 1.0 if ( @@ -1258,7 +1247,9 @@ def get_sales_orders(self): & (pi.parent_item == so_item.item_code) & ( ExistsCriterion( - frappe.qb.from_(bom).select(bom.name).where((bom.item == pi.item_code) & (bom.is_active == 1)) + frappe.qb.from_(bom) + .select(bom.name) + .where((bom.item == pi.item_code) & (bom.is_active == 1)) ) ) ) @@ -1301,7 +1292,7 @@ def get_sales_orders(self): ) open_so_query = open_so_query.where( - (ExistsCriterion(open_so_subquery1) | ExistsCriterion(open_so_subquery2)) + ExistsCriterion(open_so_subquery1) | ExistsCriterion(open_so_subquery2) ) open_so = open_so_query.run(as_dict=True) @@ -1423,9 +1414,7 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d data["include_exploded_items"] = 1 planned_qty = data.get("required_qty") or data.get("planned_qty") - ignore_existing_ordered_qty = ( - data.get("ignore_existing_ordered_qty") or ignore_existing_ordered_qty - ) + ignore_existing_ordered_qty = data.get("ignore_existing_ordered_qty") or ignore_existing_ordered_qty warehouse = doc.get("for_warehouse") item_details = {} @@ -1458,7 +1447,12 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d elif data.get("include_exploded_items") and include_subcontracted_items: # fetch exploded items from BOM item_details = get_exploded_items( - item_details, company, bom_no, include_non_stock_items, planned_qty=planned_qty, doc=doc + item_details, + company, + bom_no, + include_non_stock_items, + planned_qty=planned_qty, + doc=doc, ) else: item_details = get_subitems( @@ -1613,7 +1607,7 @@ def get_item_data(item_code): return { "bom_no": item_details.get("bom_no"), - "stock_uom": item_details.get("stock_uom") + "stock_uom": item_details.get("stock_uom"), # "description": item_details.get("description") } @@ -1656,7 +1650,9 @@ def get_sub_assembly_items(bom_no, bom_data, to_produce_qty, company, warehouse= ) if d.value: - get_sub_assembly_items(d.value, bom_data, stock_qty, company, warehouse, indent=indent + 1) + get_sub_assembly_items( + d.value, bom_data, stock_qty, company, warehouse, indent=indent + 1 + ) def set_default_warehouses(row, default_warehouses): @@ -1798,9 +1794,7 @@ def get_raw_materials_of_sub_assembly_items( @frappe.whitelist() -def sales_order_query( - doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None -): +def sales_order_query(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None): frappe.has_permission("Production Plan", throw=True) if not filters: diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 7e33eb80f7d5..31f34a837629 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -110,9 +110,7 @@ def test_production_plan_mr_creation(self): def test_production_plan_start_date(self): "Test if Work Order has same Planned Start Date as Prod Plan." planned_date = add_to_date(date=None, days=3) - plan = create_production_plan( - item_code="Test Production Item 1", planned_start_date=planned_date - ) + plan = create_production_plan(item_code="Test Production Item 1", planned_start_date=planned_date) plan.make_work_order() work_orders = frappe.get_all( @@ -213,9 +211,7 @@ def test_production_plan_sales_orders(self): ) wo_doc = frappe.get_doc("Work Order", work_order) - wo_doc.update( - {"wip_warehouse": "Work In Progress - _TC", "fg_warehouse": "Finished Goods - _TC"} - ) + wo_doc.update({"wip_warehouse": "Work In Progress - _TC", "fg_warehouse": "Finished Goods - _TC"}) wo_doc.submit() so_wo_qty = frappe.db.get_value("Sales Order Item", sales_order_item, "work_order_qty") @@ -400,7 +396,7 @@ def test_production_plan_subassembly_default_supplier(self): from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom bom_tree_1 = {"Test Laptop": {"Test Motherboard": {"Test Motherboard Wires": {}}}} - bom = create_nested_bom(bom_tree_1, prefix="") + create_nested_bom(bom_tree_1, prefix="") item_doc = frappe.get_doc("Item", "Test Motherboard") company = "_Test Company" @@ -504,14 +500,10 @@ def test_production_plan_combine_subassembly(self): def test_pp_to_mr_customer_provided(self): "Test Material Request from Production Plan for Customer Provided Item." - create_item( - "CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0 - ) + create_item("CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0) create_item("Production Item CUST") - for item, raw_materials in { - "Production Item CUST": ["Raw Material Item 1", "CUST-0987"] - }.items(): + for item, raw_materials in {"Production Item CUST": ["Raw Material Item 1", "CUST-0987"]}.items(): if not frappe.db.get_value("BOM", {"item": item}): make_bom(item=item, raw_materials=raw_materials) production_plan = create_production_plan(item_code="Production Item CUST") @@ -664,7 +656,7 @@ def create_work_order(item, pln, qty): items_data[(pln.po_items[0].name, item, None)]["qty"] = qty # Create and Submit Work Order for each item in items_data - for key, item in items_data.items(): + for _key, item in items_data.items(): if pln.sub_assembly_items: item["use_multi_level_bom"] = 0 @@ -833,7 +825,6 @@ def test_production_plan_planned_qty(self): self.assertEqual(pln.po_items[0].planned_qty, 0.55) def test_temporary_name_relinking(self): - pp = frappe.new_doc("Production Plan") # this can not be unittested so mocking data that would be expected @@ -849,7 +840,7 @@ def test_temporary_name_relinking(self): pp.append("sub_assembly_items", {"production_plan_item": po_item.temporary_name}) pp._rename_temporary_references() - for po_item, subassy_item in zip(pp.po_items, pp.sub_assembly_items): + for po_item, subassy_item in zip(pp.po_items, pp.sub_assembly_items, strict=False): self.assertEqual(po_item.name, subassy_item.production_plan_item) # bad links should be erased @@ -860,7 +851,7 @@ def test_temporary_name_relinking(self): # reattempting on same doc shouldn't change anything pp._rename_temporary_references() - for po_item, subassy_item in zip(pp.po_items, pp.sub_assembly_items): + for po_item, subassy_item in zip(pp.po_items, pp.sub_assembly_items, strict=False): self.assertEqual(po_item.name, subassy_item.production_plan_item) def test_produced_qty_for_multi_level_bom_item(self): @@ -1137,9 +1128,7 @@ def test_resered_qty_for_production_plan_for_material_requests_with_multi_UOM(se wo_doc.fg_warehouse = "_Test Warehouse - _TC" wo_doc.submit() - reserved_qty_after_mr = flt( - frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan") - ) + reserved_qty_after_mr = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) self.assertEqual(reserved_qty_after_mr, before_qty) def test_from_warehouse_for_purchase_material_request(self): @@ -1147,7 +1136,7 @@ def test_from_warehouse_for_purchase_material_request(self): from erpnext.stock.utils import get_or_make_bin create_item("RM-TEST-123 For Purchase", valuation_rate=100) - bin_name = get_or_make_bin("RM-TEST-123 For Purchase", "_Test Warehouse - _TC") + get_or_make_bin("RM-TEST-123 For Purchase", "_Test Warehouse - _TC") t_warehouse = create_warehouse("_Test Store - _TC") make_stock_entry( item_code="Raw Material Item 1", @@ -1157,9 +1146,7 @@ def test_from_warehouse_for_purchase_material_request(self): ) plan = create_production_plan(item_code="Test Production Item 1", do_not_save=1) - mr_items = get_items_for_material_requests( - plan.as_dict(), warehouses=[{"warehouse": t_warehouse}] - ) + mr_items = get_items_for_material_requests(plan.as_dict(), warehouses=[{"warehouse": t_warehouse}]) for d in mr_items: plan.append("mr_items", d) @@ -1457,9 +1444,7 @@ def test_material_request_qty_purchase_and_material_transfer(self): ) pln.for_warehouse = rm_warehouse - items = get_items_for_material_requests( - pln.as_dict(), warehouses=[{"warehouse": store_warehouse}] - ) + items = get_items_for_material_requests(pln.as_dict(), warehouses=[{"warehouse": store_warehouse}]) for row in items: self.assertEqual(row.get("quantity"), 10.0) @@ -1468,9 +1453,7 @@ def test_material_request_qty_purchase_and_material_transfer(self): self.assertEqual(row.get("from_warehouse"), store_warehouse) self.assertEqual(row.get("conversion_factor"), 1.0) - items = get_items_for_material_requests( - pln.as_dict(), warehouses=[{"warehouse": pln.for_warehouse}] - ) + items = get_items_for_material_requests(pln.as_dict(), warehouses=[{"warehouse": pln.for_warehouse}]) for row in items: self.assertEqual(row.get("quantity"), 1.0) @@ -1485,7 +1468,7 @@ def test_unreserve_qty_on_closing_of_pp(self): fg_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name rm_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name - store_warehouse = create_warehouse("Store Warehouse", company="_Test Company") + create_warehouse("Store Warehouse", company="_Test Company") rm_warehouse = create_warehouse("RM Warehouse", company="_Test Company") make_bom(item=fg_item, raw_materials=[rm_item], source_warehouse="_Test Warehouse - _TC") @@ -1521,7 +1504,6 @@ def test_unreserve_qty_on_closing_of_pp(self): def test_min_order_qty_in_pp(self): from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse - from erpnext.stock.utils import get_or_make_bin fg_item = make_item(properties={"is_stock_item": 1}).name rm_item = make_item(properties={"is_stock_item": 1, "min_order_qty": 1000}).name @@ -1543,9 +1525,6 @@ def test_min_order_qty_in_pp(self): self.assertEqual(d.get("quantity"), 1000.0) def test_fg_item_quantity(self): - from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse - from erpnext.stock.utils import get_or_make_bin - fg_item = make_item(properties={"is_stock_item": 1}).name rm_item = make_item(properties={"is_stock_item": 1}).name diff --git a/erpnext/manufacturing/doctype/routing/routing.py b/erpnext/manufacturing/doctype/routing/routing.py index d4c37cf79e79..701eaeb9ef39 100644 --- a/erpnext/manufacturing/doctype/routing/routing.py +++ b/erpnext/manufacturing/doctype/routing/routing.py @@ -32,9 +32,9 @@ def set_routing_id(self): row.sequence_id = sequence_id + 1 elif sequence_id and row.sequence_id and cint(sequence_id) > cint(row.sequence_id): frappe.throw( - _("At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2}").format( - row.idx, row.sequence_id, sequence_id - ) + _( + "At row #{0}: the sequence id {1} cannot be less than previous row sequence id {2}" + ).format(row.idx, row.sequence_id, sequence_id) ) sequence_id = row.sequence_id diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 8e24d4cd59a9..0d4539c52877 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -40,7 +40,6 @@ def tearDown(self): frappe.db.rollback() def check_planned_qty(self): - planned0 = ( frappe.db.get_value( "Bin", {"item_code": "_Test FG Item", "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty" @@ -129,9 +128,7 @@ def test_reserved_qty_for_partial_completion(self): # reserved qty for production is updated self.assertEqual(cint(bin1_at_start.reserved_qty_for_production) + 2, reserved_qty_on_submission) - test_stock_entry.make_stock_entry( - item_code="_Test Item", target=warehouse, qty=100, basic_rate=100 - ) + test_stock_entry.make_stock_entry(item_code="_Test Item", target=warehouse, qty=100, basic_rate=100) test_stock_entry.make_stock_entry( item_code="_Test Item Home Desktop 100", target=warehouse, qty=100, basic_rate=100 ) @@ -141,9 +138,7 @@ def test_reserved_qty_for_partial_completion(self): bin1_at_completion = get_bin(item, warehouse) - self.assertEqual( - cint(bin1_at_completion.reserved_qty_for_production), reserved_qty_on_submission - 1 - ) + self.assertEqual(cint(bin1_at_completion.reserved_qty_for_production), reserved_qty_on_submission - 1) def test_production_item(self): wo_order = make_wo_order_test_record(item="_Test FG Item", qty=1, do_not_save=True) @@ -178,9 +173,7 @@ def test_reserved_qty_for_production_submit(self): cint(self.bin1_at_start.reserved_qty_for_production) + 2, cint(self.bin1_on_submit.reserved_qty_for_production), ) - self.assertEqual( - cint(self.bin1_at_start.projected_qty), cint(self.bin1_on_submit.projected_qty) + 2 - ) + self.assertEqual(cint(self.bin1_at_start.projected_qty), cint(self.bin1_on_submit.projected_qty) + 2) def test_reserved_qty_for_production_cancel(self): self.test_reserved_qty_for_production_submit() @@ -234,7 +227,6 @@ def test_reserved_qty_for_production_on_stock_entry(self): ) def test_reserved_qty_for_production_closed(self): - wo1 = make_wo_order_test_record(item="_Test FG Item", qty=2, source_warehouse=self.warehouse) item = wo1.required_items[0].item_code bin_before = get_bin(item, self.warehouse) @@ -366,7 +358,9 @@ def test_scrap_material_qty(self): for item in s.items: if item.bom_no and item.item_code in scrap_item_details: self.assertEqual(wo_order_details.scrap_warehouse, item.t_warehouse) - self.assertEqual(flt(wo_order_details.qty) * flt(scrap_item_details[item.item_code]), item.qty) + self.assertEqual( + flt(wo_order_details.qty) * flt(scrap_item_details[item.item_code]), item.qty + ) def test_allow_overproduction(self): allow_overproduction("overproduction_percentage_for_work_order", 0) @@ -480,7 +474,7 @@ def test_job_card(self): ) self.assertEqual(len(job_cards), len(bom.operations)) - for i, job_card in enumerate(job_cards): + for _i, job_card in enumerate(job_cards): doc = frappe.get_doc("Job Card", job_card) doc.time_logs[0].completed_qty = 1 doc.submit() @@ -571,9 +565,7 @@ def test_operation_time_with_batch_size(self): for item in ["Test Batch Size Item For BOM", "Test Batch Size Item RM 1 For BOM"]: make_item(item, {"include_item_in_manufacturing": 1, "is_stock_item": 1}) - bom_name = frappe.db.get_value( - "BOM", {"item": fg_item, "is_active": 1, "with_operations": 1}, "name" - ) + bom_name = frappe.db.get_value("BOM", {"item": fg_item, "is_active": 1, "with_operations": 1}, "name") if not bom_name: bom = make_bom(item=fg_item, rate=1000, raw_materials=[rm1], do_not_save=True) @@ -625,9 +617,7 @@ def test_batch_size_for_fg_item(self): make_item(item, item_args) - bom_name = frappe.db.get_value( - "BOM", {"item": fg_item, "is_active": 1, "with_operations": 1}, "name" - ) + bom_name = frappe.db.get_value("BOM", {"item": fg_item, "is_active": 1, "with_operations": 1}, "name") if not bom_name: bom = make_bom(item=fg_item, rate=1000, raw_materials=[rm1], do_not_save=True) @@ -847,7 +837,6 @@ def test_wo_completion_with_pl_bom(self): ) qty = 10 - scrap_qty = 0.25 # bom item qty = 1, consider as 25% of FG source_warehouse = "Stores - _TC" wip_warehouse = "_Test Warehouse - _TC" fg_item_non_whole, _, bom_item = create_process_loss_bom_items() @@ -1189,7 +1178,9 @@ def test_auto_serial_no_creation(self): for row in stock_entry.items: if row.item_code == fg_item: self.assertTrue(row.serial_no) - self.assertEqual(sorted(get_serial_nos(row.serial_no)), sorted(get_serial_nos(serial_nos))) + self.assertEqual( + sorted(get_serial_nos(row.serial_no)), sorted(get_serial_nos(serial_nos)) + ) except frappe.MandatoryError: self.fail("Batch generation causing failing in Work Order") @@ -1663,9 +1654,7 @@ def test_job_card_extra_qty(self): job_card2 = frappe.copy_doc(job_card_doc) self.assertRaises(frappe.ValidationError, job_card2.save) - frappe.db.set_single_value( - "Manufacturing Settings", "overproduction_percentage_for_work_order", 100 - ) + frappe.db.set_single_value("Manufacturing Settings", "overproduction_percentage_for_work_order", 100) job_card2 = frappe.copy_doc(job_card_doc) job_card2.time_logs = [] @@ -1729,9 +1718,7 @@ def test_make_serial_no_batch_from_work_order_for_serial_no(self): def test_op_cost_and_scrap_based_on_sub_assemblies(self): # Make Sub Assembly BOM 1 - frappe.db.set_single_value( - "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 1 - ) + frappe.db.set_single_value("Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 1) items = { "Test Final FG Item": 0, @@ -1747,7 +1734,7 @@ def test_op_cost_and_scrap_based_on_sub_assemblies(self): if not frappe.db.exists("Item", item): item_properties = {"is_stock_item": 1, "valuation_rate": items[item]} - make_item(item_code=item, properties=item_properties), + (make_item(item_code=item, properties=item_properties),) prepare_boms_for_sub_assembly_test() @@ -1768,15 +1755,11 @@ def test_op_cost_and_scrap_based_on_sub_assemblies(self): if item.is_scrap_item: scrap_items.append(item.item_code) - self.assertEqual( - sorted(scrap_items), sorted(["Test Final Scrap Item 1", "Test Final Scrap Item 2"]) - ) + self.assertEqual(sorted(scrap_items), sorted(["Test Final Scrap Item 1", "Test Final Scrap Item 2"])) for row in se_doc.additional_costs: self.assertEqual(row.amount, 3000) - frappe.db.set_single_value( - "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 0 - ) + frappe.db.set_single_value("Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 0) def test_capcity_planning_for_workstation(self): frappe.db.set_single_value( diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index abaec0f9d4c6..6bb03310389c 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -154,9 +154,7 @@ def check_sales_order_on_hold_or_close(self): def set_default_warehouse(self): if not self.wip_warehouse and not self.skip_transfer: - self.wip_warehouse = frappe.db.get_single_value( - "Manufacturing Settings", "default_wip_warehouse" - ) + self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse") if not self.fg_warehouse: self.fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse") @@ -216,9 +214,7 @@ def validate_work_order_against_so(self): so_qty = flt(so_item_qty) + flt(dnpi_qty) allowance_percentage = flt( - frappe.db.get_single_value( - "Manufacturing Settings", "overproduction_percentage_for_sales_order" - ) + frappe.db.get_single_value("Manufacturing Settings", "overproduction_percentage_for_sales_order") ) if total_qty > so_qty + (allowance_percentage / 100 * so_qty): @@ -354,9 +350,7 @@ def update_production_plan_status(self): produced_qty = total_qty[0][0] if total_qty else 0 self.update_status() - production_plan.run_method( - "update_produced_pending_qty", produced_qty, self.production_plan_item - ) + production_plan.run_method("update_produced_pending_qty", produced_qty, self.production_plan_item) def before_submit(self): self.create_serial_no_batch_no() @@ -534,9 +528,7 @@ def set_operation_start_end_time(self, idx, row): get_datetime(self.operations[idx - 1].planned_end_time) + get_mins_between_operations() ) - row.planned_end_time = get_datetime(row.planned_start_time) + relativedelta( - minutes=row.time_in_mins - ) + row.planned_end_time = get_datetime(row.planned_start_time) + relativedelta(minutes=row.time_in_mins) if row.planned_start_time == row.planned_end_time: frappe.throw(_("Capacity Planning Error, planned start time can not be same as end time")) @@ -603,11 +595,7 @@ def set_produced_qty_for_sub_assembly_item(self): ) def update_ordered_qty(self): - if ( - self.production_plan - and self.production_plan_item - and not self.production_plan_sub_assembly_item - ): + if self.production_plan and self.production_plan_item and not self.production_plan_sub_assembly_item: table = frappe.qb.DocType("Work Order") query = ( @@ -647,11 +635,9 @@ def update_work_order_qty_in_so(self): cond = "product_bundle_item = %s" if self.product_bundle_item else "production_item = %s" qty = frappe.db.sql( - """ select sum(qty) from - `tabWork Order` where sales_order = %s and docstatus = 1 and {0} - """.format( - cond - ), + f""" select sum(qty) from + `tabWork Order` where sales_order = %s and docstatus = 1 and {cond} + """, (self.sales_order, (self.product_bundle_item or self.production_item)), as_list=1, ) @@ -801,9 +787,7 @@ def update_operation_status(self): def set_actual_dates(self): if self.get("operations"): - actual_start_dates = [ - d.actual_start_time for d in self.get("operations") if d.actual_start_time - ] + actual_start_dates = [d.actual_start_time for d in self.get("operations") if d.actual_start_time] if actual_start_dates: self.actual_start_date = min(actual_start_dates) @@ -848,11 +832,7 @@ def validate_qty(self): if not self.qty > 0: frappe.throw(_("Quantity to Manufacture must be greater than 0.")) - if ( - self.production_plan - and self.production_plan_item - and not self.production_plan_sub_assembly_item - ): + if self.production_plan and self.production_plan_item and not self.production_plan_sub_assembly_item: qty_dict = frappe.db.get_value( "Production Plan Item", self.production_plan_item, ["planned_qty", "ordered_qty"], as_dict=1 ) @@ -988,7 +968,7 @@ def update_transferred_qty_for_required_items(self): query = ( frappe.qb.from_(ste) .inner_join(ste_child) - .on((ste_child.parent == ste.name)) + .on(ste_child.parent == ste.name) .select( ste_child.item_code, ste_child.original_item, @@ -1018,7 +998,7 @@ def update_returned_qty(self): query = ( frappe.qb.from_(ste) .inner_join(ste_child) - .on((ste_child.parent == ste.name)) + .on(ste_child.parent == ste.name) .select( ste_child.item_code, ste_child.original_item, @@ -1286,9 +1266,7 @@ def make_stock_entry(work_order_id, purpose, qty=None): ) if work_order.bom_no: - stock_entry.inspection_required = frappe.db.get_value( - "BOM", work_order.bom_no, "inspection_required" - ) + stock_entry.inspection_required = frappe.db.get_value("BOM", work_order.bom_no, "inspection_required") if purpose == "Material Transfer for Manufacture": stock_entry.to_warehouse = wip_warehouse @@ -1394,9 +1372,7 @@ def close_work_order(work_order, status): def split_qty_based_on_batch_size(wo_doc, row, qty): - if not cint( - frappe.db.get_value("Operation", row.operation, "create_job_card_based_on_batch_size") - ): + if not cint(frappe.db.get_value("Operation", row.operation, "create_job_card_based_on_batch_size")): row.batch_size = row.get("qty") or wo_doc.qty row.job_card_qty = row.batch_size @@ -1476,9 +1452,7 @@ def create_job_card(work_order, row, enable_capacity_planning=False, auto_create doc.schedule_time_logs(row) doc.insert() - frappe.msgprint( - _("Job card {0} created").format(get_link_to_form("Job Card", doc.name)), alert=True - ) + frappe.msgprint(_("Job card {0} created").format(get_link_to_form("Job Card", doc.name)), alert=True) if enable_capacity_planning: # automatically added scheduling rows shouldn't change status to WIP @@ -1541,7 +1515,7 @@ def update_item_quantity(source, target, source_parent): def get_reserved_qty_for_production( item_code: str, warehouse: str, - non_completed_production_plans: list = None, + non_completed_production_plans: list | None = None, check_production_plan: bool = False, ) -> float: """Get total reserved quantity for any item in specified warehouse""" diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py index 0eb9906a2ab4..fe2cbc89b486 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation.py +++ b/erpnext/manufacturing/doctype/workstation/workstation.py @@ -88,7 +88,8 @@ def validate_overlap_for_operation_timings(self): if existing: frappe.throw( - _("Row #{0}: Timings conflicts with row {1}").format(d.idx, comma_and(existing)), OverlapError + _("Row #{0}: Timings conflicts with row {1}").format(d.idx, comma_and(existing)), + OverlapError, ) def update_bom_operation(self): @@ -128,10 +129,7 @@ def get_default_holiday_list(): def check_if_within_operating_hours(workstation, operation, from_datetime, to_datetime): if from_datetime and to_datetime: - - if not cint( - frappe.db.get_value("Manufacturing Settings", "None", "allow_production_on_holidays") - ): + if not cint(frappe.db.get_value("Manufacturing Settings", "None", "allow_production_on_holidays")): check_workstation_for_holiday(workstation, from_datetime, to_datetime) if not cint(frappe.db.get_value("Manufacturing Settings", None, "allow_overtime")): @@ -174,7 +172,9 @@ def check_workstation_for_holiday(workstation, from_datetime, to_datetime): if applicable_holidays: frappe.throw( - _("Workstation is closed on the following dates as per Holiday List: {0}").format(holiday_list) + _("Workstation is closed on the following dates as per Holiday List: {0}").format( + holiday_list + ) + "\n" + "\n".join(applicable_holidays), WorkstationHolidayError, diff --git a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py index 550445c1f77f..6bc05a468f14 100644 --- a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py +++ b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py @@ -33,9 +33,7 @@ def get_report_data(last_purchase_rate, required_qty, row, manufacture_details): row.item_code, row.description, comma_and(manufacture_details.get(row.item_code, {}).get("manufacturer", []), add_quotes=False), - comma_and( - manufacture_details.get(row.item_code, {}).get("manufacturer_part", []), add_quotes=False - ), + comma_and(manufacture_details.get(row.item_code, {}).get("manufacturer_part", []), add_quotes=False), qty_per_unit, row.actual_qty, required_qty, diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py index 3573a3a93d88..48ffbac58202 100644 --- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py +++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py @@ -44,9 +44,7 @@ def get_bom_stock(filters): else: bom_item_table = "BOM Item" - warehouse_details = frappe.db.get_value( - "Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1 - ) + warehouse_details = frappe.db.get_value("Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1) BOM = frappe.qb.DocType("BOM") BOM_ITEM = frappe.qb.DocType(bom_item_table) diff --git a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py index 481fe51d739d..a86df3194412 100644 --- a/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py +++ b/erpnext/manufacturing/report/cost_of_poor_quality_report/cost_of_poor_quality_report.py @@ -20,9 +20,7 @@ def get_data(report_filters): job_card = frappe.qb.DocType("Job Card") - operating_cost = ((job_card.hour_rate) * (job_card.total_time_in_mins) / 60.0).as_( - "operating_cost" - ) + operating_cost = ((job_card.hour_rate) * (job_card.total_time_in_mins) / 60.0).as_("operating_cost") item_code = (job_card.production_item).as_("item_code") query = ( @@ -64,7 +62,7 @@ def append_filters(query, report_filters, operations, job_card): ): if report_filters.get(field): if field == "serial_no": - query = query.where(job_card[field].like("%{}%".format(report_filters.get(field)))) + query = query.where(job_card[field].like(f"%{report_filters.get(field)}%")) elif field == "operation": query = query.where(job_card[field].isin(operations)) else: diff --git a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py index d3bce8315518..26b933c52dd7 100644 --- a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py +++ b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py @@ -15,9 +15,9 @@ def execute(filters=None): return ForecastingReport(filters).execute_report() -class ExponentialSmoothingForecast(object): +class ExponentialSmoothingForecast: def forecast_future_data(self): - for key, value in self.period_wise_data.items(): + for _key, value in self.period_wise_data.items(): forecast_data = [] for period in self.period_list: forecast_key = "forecast_" + period.key @@ -183,7 +183,6 @@ def get_columns(self): "Half-Yearly", "Quarterly", ] or period.from_date >= getdate(self.filters.from_date): - forecast_key = period.key label = _(period.label) if period.from_date >= getdate(self.filters.from_date): diff --git a/erpnext/manufacturing/report/process_loss_report/process_loss_report.py b/erpnext/manufacturing/report/process_loss_report/process_loss_report.py index c3dd9cf9b1a4..51efc6e655f5 100644 --- a/erpnext/manufacturing/report/process_loss_report/process_loss_report.py +++ b/erpnext/manufacturing/report/process_loss_report/process_loss_report.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from typing import Dict, List, Tuple import frappe from frappe import _ @@ -9,12 +8,12 @@ Filters = frappe._dict Row = frappe._dict -Data = List[Row] -Columns = List[Dict[str, str]] -QueryArgs = Dict[str, str] +Data = list[Row] +Columns = list[dict[str, str]] +QueryArgs = dict[str, str] -def execute(filters: Filters) -> Tuple[Columns, Data]: +def execute(filters: Filters) -> tuple[Columns, Data]: filters = frappe._dict(filters or {}) columns = get_columns() data = get_data(filters) diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.py b/erpnext/manufacturing/report/production_analytics/production_analytics.py index 12b5d19ba870..c02c1e6fcd38 100644 --- a/erpnext/manufacturing/report/production_analytics/production_analytics.py +++ b/erpnext/manufacturing/report/production_analytics/production_analytics.py @@ -20,13 +20,10 @@ def get_columns(filters): ranges = get_period_date_ranges(filters) - for dummy, end_date in ranges: - + for _dummy, end_date in ranges: period = get_period(end_date, filters) - columns.append( - {"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120} - ) + columns.append({"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120}) return columns @@ -110,7 +107,7 @@ def get_data(filters, columns): for label in labels: work = {} work["Status"] = label - for dummy, end_date in ranges: + for _dummy, end_date in ranges: period = get_period(end_date, filters) if periodic_data.get(label).get(period): work[scrub(period)] = periodic_data.get(label).get(period) diff --git a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py index 076690ff0907..5bc9236c1d5c 100644 --- a/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py +++ b/erpnext/manufacturing/report/production_plan_summary/production_plan_summary.py @@ -56,14 +56,10 @@ def get_production_plan_item_details(filters, data, order_details): } ) - get_production_plan_sub_assembly_item_details( - filters, row, production_plan_doc, data, order_details - ) + get_production_plan_sub_assembly_item_details(filters, row, production_plan_doc, data, order_details) -def get_production_plan_sub_assembly_item_details( - filters, row, production_plan_doc, data, order_details -): +def get_production_plan_sub_assembly_item_details(filters, row, production_plan_doc, data, order_details): for item in production_plan_doc.sub_assembly_items: if row.name == item.production_plan_item: subcontracted_item = item.type_of_manufacturing == "Subcontract" @@ -76,7 +72,9 @@ def get_production_plan_sub_assembly_item_details( ) else: docname = frappe.get_value( - "Work Order", {"production_plan_sub_assembly_item": item.name, "docstatus": ("<", 2)}, "name" + "Work Order", + {"production_plan_sub_assembly_item": item.name, "docstatus": ("<", 2)}, + "name", ) data.append( @@ -88,7 +86,9 @@ def get_production_plan_sub_assembly_item_details( "document_type": "Work Order" if not subcontracted_item else "Purchase Order", "document_name": docname or "", "bom_level": item.bom_level, - "produced_qty": order_details.get((docname, item.production_item), {}).get("produced_qty", 0), + "produced_qty": order_details.get((docname, item.production_item), {}).get( + "produced_qty", 0 + ), "pending_qty": flt(item.qty) - flt(order_details.get((docname, item.production_item), {}).get("produced_qty", 0)), } diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py index 109d9ab656bc..63af3e5cbe67 100644 --- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py +++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py @@ -13,7 +13,7 @@ def execute(filters=None): return ProductionPlanReport(filters).execute_report() -class ProductionPlanReport(object): +class ProductionPlanReport: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) self.raw_materials_dict = {} @@ -79,7 +79,10 @@ def get_open_orders(self): query = query.where(child.parent.isin(self.filters.docnames)) if doctype == "Sales Order": - query = query.select(child.delivery_date, parent.base_grand_total,).where( + query = query.select( + child.delivery_date, + parent.base_grand_total, + ).where( (child.stock_qty > child.produced_qty) & (parent.per_delivered < 100.0) & (parent.status.notin(["Completed", "Closed"])) @@ -91,7 +94,9 @@ def get_open_orders(self): query = query.orderby(parent.base_grand_total, order=Order.desc) elif doctype == "Material Request": - query = query.select(child.schedule_date,).where( + query = query.select( + child.schedule_date, + ).where( (parent.per_ordered < 100) & (parent.material_request_type == "Manufacture") & (parent.status != "Stopped") @@ -280,9 +285,7 @@ def update_raw_materials(self, data, key): d.remaining_qty = d.required_qty self.pick_materials_from_warehouses(d, data, warehouses) - if ( - d.remaining_qty and self.filters.raw_material_warehouse and d.remaining_qty != d.required_qty - ): + if d.remaining_qty and self.filters.raw_material_warehouse and d.remaining_qty != d.required_qty: row = self.get_args() d.warehouse = self.filters.raw_material_warehouse d.required_qty = d.remaining_qty diff --git a/erpnext/manufacturing/report/test_reports.py b/erpnext/manufacturing/report/test_reports.py index e436fdca646f..3e20f310ff9b 100644 --- a/erpnext/manufacturing/report/test_reports.py +++ b/erpnext/manufacturing/report/test_reports.py @@ -1,5 +1,4 @@ import unittest -from typing import List, Tuple import frappe @@ -13,7 +12,7 @@ } -REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [ +REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [ ("BOM Explorer", {"bom": frappe.get_last_doc("BOM").name}), ("BOM Operations Time", {}), ("BOM Stock Calculated", {"bom": frappe.get_last_doc("BOM").name, "qty_to_make": 2}), diff --git a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py index 14e97d3dd781..64363e20e394 100644 --- a/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py +++ b/erpnext/manufacturing/report/work_order_consumed_materials/work_order_consumed_materials.py @@ -22,7 +22,7 @@ def get_data(report_filters): wo_items = {} work_orders = frappe.get_all("Work Order", filters=filters, fields=fields) - returned_materials = get_returned_materials(work_orders) + get_returned_materials(work_orders) for d in work_orders: d.extra_consumed_qty = 0.0 @@ -33,7 +33,7 @@ def get_data(report_filters): wo_items.setdefault((d.name, d.production_item), []).append(d) data = [] - for key, wo_data in wo_items.items(): + for _key, wo_data in wo_items.items(): for index, row in enumerate(wo_data): if index != 0: # If one work order has multiple raw materials then show parent data in the first row only diff --git a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py index e2d0943d724a..b98e7ab4bf64 100644 --- a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py +++ b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py @@ -12,9 +12,7 @@ def execute(): if "barcode" not in frappe.db.get_table_columns("Item"): return - items_barcode = frappe.db.sql( - "select name, barcode from tabItem where barcode is not null", as_dict=True - ) + items_barcode = frappe.db.sql("select name, barcode from tabItem where barcode is not null", as_dict=True) frappe.reload_doc("stock", "doctype", "item") for item in items_barcode: diff --git a/erpnext/patches/v10_0/set_currency_in_pricing_rule.py b/erpnext/patches/v10_0/set_currency_in_pricing_rule.py index d68148eec1c3..08f5ed166ab7 100644 --- a/erpnext/patches/v10_0/set_currency_in_pricing_rule.py +++ b/erpnext/patches/v10_0/set_currency_in_pricing_rule.py @@ -9,6 +9,4 @@ def execute(): if doc.company: currency = frappe.get_cached_value("Company", doc.company, "default_currency") - frappe.db.sql( - """update `tabPricing Rule` set currency = %s where name = %s""", (currency, doc.name) - ) + frappe.db.sql("""update `tabPricing Rule` set currency = %s where name = %s""", (currency, doc.name)) diff --git a/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py b/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py index 87151c102b14..375c0109fc81 100644 --- a/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py +++ b/erpnext/patches/v10_1/transfer_subscription_to_auto_repeat.py @@ -52,7 +52,6 @@ def drop_columns_from_subscription(): "status", "amended_from", ]: - if field in frappe.db.get_table_columns("Subscription"): fields_to_drop["Subscription"].append(field) diff --git a/erpnext/patches/v11_0/create_department_records_for_each_company.py b/erpnext/patches/v11_0/create_department_records_for_each_company.py index 84be2bee9dce..a4ba154b3e59 100644 --- a/erpnext/patches/v11_0/create_department_records_for_each_company.py +++ b/erpnext/patches/v11_0/create_department_records_for_each_company.py @@ -53,11 +53,10 @@ def update_records(doctype, comp_dict): for department in records: when_then.append( - """ - WHEN company = "%s" and department = "%s" - THEN "%s" + f""" + WHEN company = "{company}" and department = "{department}" + THEN "{records[department]}" """ - % (company, department, records[department]) ) if not when_then: @@ -66,11 +65,10 @@ def update_records(doctype, comp_dict): frappe.db.sql( """ update - `tab%s` + `tab{}` set - department = CASE %s END - """ - % (doctype, " ".join(when_then)) + department = CASE {} END + """.format(doctype, " ".join(when_then)) ) @@ -83,11 +81,10 @@ def update_instructors(comp_dict): for department in records: when_then.append( - """ - WHEN employee = "%s" and department = "%s" - THEN "%s" + f""" + WHEN employee = "{employee.name}" and department = "{department}" + THEN "{records[department]}" """ - % (employee.name, department, records[department]) ) if not when_then: diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py index 1b9793df80b0..05c7b8a1e0c8 100644 --- a/erpnext/patches/v11_0/make_italian_localization_fields.py +++ b/erpnext/patches/v11_0/make_italian_localization_fields.py @@ -20,19 +20,17 @@ def execute(): # Set state codes condition = "" for state, code in state_codes.items(): - condition += " when {0} then {1}".format(frappe.db.escape(state), frappe.db.escape(code)) + condition += f" when {frappe.db.escape(state)} then {frappe.db.escape(code)}" if condition: - condition = "state_code = (case state {0} end),".format(condition) + condition = f"state_code = (case state {condition} end)," frappe.db.sql( - """ + f""" UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code from `tabCountry` where name = `tabAddress`.country), '')) where country_code is null and state_code is null - """.format( - condition=condition - ) + """ ) frappe.db.sql( diff --git a/erpnext/patches/v11_0/merge_land_unit_with_location.py b/erpnext/patches/v11_0/merge_land_unit_with_location.py index c1afef67785e..92d0bc90c586 100644 --- a/erpnext/patches/v11_0/merge_land_unit_with_location.py +++ b/erpnext/patches/v11_0/merge_land_unit_with_location.py @@ -29,9 +29,9 @@ def execute(): rename_field("Linked Location", "land_unit", "location") if not frappe.db.exists("Location", "All Land Units"): - frappe.get_doc( - {"doctype": "Location", "is_group": True, "location_name": "All Land Units"} - ).insert(ignore_permissions=True) + frappe.get_doc({"doctype": "Location", "is_group": True, "location_name": "All Land Units"}).insert( + ignore_permissions=True + ) if frappe.db.table_exists("Land Unit"): land_units = frappe.get_all("Land Unit", fields=["*"], order_by="lft") diff --git a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py index 37c07799ddc9..418bb1378d59 100644 --- a/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py +++ b/erpnext/patches/v11_0/move_item_defaults_to_child_table_for_multicompany.py @@ -106,8 +106,6 @@ def execute(): `expense_account`, `income_account`, `buying_cost_center`, `selling_cost_center` ) VALUES {} - """.format( - ", ".join(["%s"] * len(to_insert_data)) - ), + """.format(", ".join(["%s"] * len(to_insert_data))), tuple(to_insert_data), ) diff --git a/erpnext/patches/v11_0/refactor_naming_series.py b/erpnext/patches/v11_0/refactor_naming_series.py index 9cfb082c1f22..53c293cae817 100644 --- a/erpnext/patches/v11_0/refactor_naming_series.py +++ b/erpnext/patches/v11_0/refactor_naming_series.py @@ -124,9 +124,7 @@ def get_series(): def get_series_to_preserve(doctype): series_to_preserve = frappe.db.sql_list( - """select distinct naming_series from `tab{doctype}` where ifnull(naming_series, '') != ''""".format( - doctype=doctype - ) + f"""select distinct naming_series from `tab{doctype}` where ifnull(naming_series, '') != ''""" ) series_to_preserve.sort() return series_to_preserve diff --git a/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py b/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py index c444c16a59bd..206e7f5ebef1 100644 --- a/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py +++ b/erpnext/patches/v11_0/rename_asset_adjustment_doctype.py @@ -6,8 +6,6 @@ def execute(): - if frappe.db.table_exists("Asset Adjustment") and not frappe.db.table_exists( - "Asset Value Adjustment" - ): + if frappe.db.table_exists("Asset Adjustment") and not frappe.db.table_exists("Asset Value Adjustment"): frappe.rename_doc("DocType", "Asset Adjustment", "Asset Value Adjustment", force=True) frappe.reload_doc("assets", "doctype", "asset_value_adjustment") diff --git a/erpnext/patches/v11_0/rename_bom_wo_fields.py b/erpnext/patches/v11_0/rename_bom_wo_fields.py index fb25eeb6fccb..2132ff319174 100644 --- a/erpnext/patches/v11_0/rename_bom_wo_fields.py +++ b/erpnext/patches/v11_0/rename_bom_wo_fields.py @@ -9,9 +9,7 @@ def execute(): # updating column value to handle field change from Data to Currency changed_field = "base_scrap_material_cost" - frappe.db.sql( - f"update `tabBOM` set {changed_field} = '0' where trim(coalesce({changed_field}, ''))= ''" - ) + frappe.db.sql(f"update `tabBOM` set {changed_field} = '0' where trim(coalesce({changed_field}, ''))= ''") for doctype in ["BOM Explosion Item", "BOM Item", "Work Order Item", "Item"]: if frappe.db.has_column(doctype, "allow_transfer_for_manufacture"): diff --git a/erpnext/patches/v11_0/rename_production_order_to_work_order.py b/erpnext/patches/v11_0/rename_production_order_to_work_order.py index b58ac4e72f1c..31a9c88d4eb7 100644 --- a/erpnext/patches/v11_0/rename_production_order_to_work_order.py +++ b/erpnext/patches/v11_0/rename_production_order_to_work_order.py @@ -21,14 +21,10 @@ def execute(): rename_field("Timesheet", "production_order", "work_order") rename_field("Stock Entry", "production_order", "work_order") - frappe.rename_doc( - "Report", "Production Orders in Progress", "Work Orders in Progress", force=True - ) + frappe.rename_doc("Report", "Production Orders in Progress", "Work Orders in Progress", force=True) frappe.rename_doc("Report", "Completed Production Orders", "Completed Work Orders", force=True) frappe.rename_doc("Report", "Open Production Orders", "Open Work Orders", force=True) frappe.rename_doc( "Report", "Issued Items Against Production Order", "Issued Items Against Work Order", force=True ) - frappe.rename_doc( - "Report", "Production Order Stock Report", "Work Order Stock Report", force=True - ) + frappe.rename_doc("Report", "Production Order Stock Report", "Work Order Stock Report", force=True) diff --git a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py index 96daba7d368c..9aa0d67804d6 100644 --- a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py +++ b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py @@ -25,10 +25,8 @@ def execute(): def build_tree(): frappe.db.sql( - """update `tabSupplier Group` set parent_supplier_group = '{0}' - where is_group = 0""".format( - _("All Supplier Groups") - ) + """update `tabSupplier Group` set parent_supplier_group = '{}' + where is_group = 0""".format(_("All Supplier Groups")) ) if not frappe.db.exists("Supplier Group", _("All Supplier Groups")): diff --git a/erpnext/patches/v11_0/set_department_for_doctypes.py b/erpnext/patches/v11_0/set_department_for_doctypes.py index b784772576fa..70e9c8cbba6b 100644 --- a/erpnext/patches/v11_0/set_department_for_doctypes.py +++ b/erpnext/patches/v11_0/set_department_for_doctypes.py @@ -4,7 +4,6 @@ def execute(): - doctypes_to_update = { "projects": ["Activity Cost", "Timesheet"], "setup": ["Sales Person"], diff --git a/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py b/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py index 548a7cb158c8..b6fc1a630a2c 100644 --- a/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py +++ b/erpnext/patches/v11_0/set_update_field_and_value_in_workflow_state.py @@ -4,7 +4,6 @@ def execute(): for doctype in ["Expense Claim", "Leave Application"]: - active_workflow = get_workflow_name(doctype) if not active_workflow: continue diff --git a/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py b/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py index a7351d275950..3f59747391a2 100644 --- a/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py +++ b/erpnext/patches/v11_0/update_allow_transfer_for_manufacture.py @@ -16,12 +16,10 @@ def execute(): frappe.reload_doc("manufacturing", "doctype", frappe.scrub(doctype)) frappe.db.sql( - """ update `tab{0}` child, tabItem item + f""" update `tab{doctype}` child, tabItem item set child.include_item_in_manufacturing = 1 where child.item_code = item.name and ifnull(item.is_stock_item, 0) = 1 - """.format( - doctype - ) + """ ) diff --git a/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py b/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py index 51ba706dcf07..9d7d45489875 100644 --- a/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py +++ b/erpnext/patches/v11_0/update_backflush_subcontract_rm_based_on_bom.py @@ -7,9 +7,7 @@ def execute(): frappe.reload_doc("buying", "doctype", "buying_settings") - frappe.db.set_value( - "Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM" - ) + frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM") frappe.reload_doc("stock", "doctype", "stock_entry_detail") frappe.db.sql( diff --git a/erpnext/patches/v11_0/update_department_lft_rgt.py b/erpnext/patches/v11_0/update_department_lft_rgt.py index 778392ec5fca..9104e36ece8d 100644 --- a/erpnext/patches/v11_0/update_department_lft_rgt.py +++ b/erpnext/patches/v11_0/update_department_lft_rgt.py @@ -12,10 +12,8 @@ def execute(): ).insert(ignore_permissions=True, ignore_mandatory=True) frappe.db.sql( - """update `tabDepartment` set parent_department = '{0}' - where is_group = 0""".format( - _("All Departments") - ) + """update `tabDepartment` set parent_department = '{}' + where is_group = 0""".format(_("All Departments")) ) rebuild_tree("Department", "parent_department") diff --git a/erpnext/patches/v11_0/update_sales_partner_type.py b/erpnext/patches/v11_0/update_sales_partner_type.py index 72fd424b2452..ced77d972769 100644 --- a/erpnext/patches/v11_0/update_sales_partner_type.py +++ b/erpnext/patches/v11_0/update_sales_partner_type.py @@ -16,7 +16,7 @@ def execute(): # get partner type in existing forms (customized) # and create a document if not created for d in ["Sales Partner"]: - partner_type = frappe.db.sql_list("select distinct partner_type from `tab{0}`".format(d)) + partner_type = frappe.db.sql_list(f"select distinct partner_type from `tab{d}`") for s in partner_type: if s and s not in default_sales_partner_type: insert_sales_partner_type(s) diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py index 09fcdb8723d0..3ed7c834a46a 100644 --- a/erpnext/patches/v11_0/update_total_qty_field.py +++ b/erpnext/patches/v11_0/update_total_qty_field.py @@ -24,16 +24,14 @@ def execute(): for doctype in doctypes: total_qty = frappe.db.sql( - """ + f""" SELECT parent, SUM(qty) as qty FROM - `tab{0} Item` - where parenttype = '{0}' + `tab{doctype} Item` + where parenttype = '{doctype}' GROUP BY parent - """.format( - doctype - ), + """, as_dict=True, ) @@ -53,13 +51,11 @@ def execute(): # This is probably never used anywhere else as of now, but should be values = [] for d in batch_transactions: - values.append("({0}, {1})".format(frappe.db.escape(d.parent), d.qty)) + values.append(f"({frappe.db.escape(d.parent)}, {d.qty})") conditions = ",".join(values) frappe.db.sql( - """ - INSERT INTO `tab{}` (name, total_qty) VALUES {} + f""" + INSERT INTO `tab{doctype}` (name, total_qty) VALUES {conditions} ON DUPLICATE KEY UPDATE name = VALUES(name), total_qty = VALUES(total_qty) - """.format( - doctype, conditions - ) + """ ) diff --git a/erpnext/patches/v11_1/make_job_card_time_logs.py b/erpnext/patches/v11_1/make_job_card_time_logs.py index beb2c4e53415..14bc4ee2a6d2 100644 --- a/erpnext/patches/v11_1/make_job_card_time_logs.py +++ b/erpnext/patches/v11_1/make_job_card_time_logs.py @@ -8,9 +8,7 @@ def execute(): frappe.reload_doc("manufacturing", "doctype", "job_card_time_log") - if frappe.db.table_exists("Job Card") and frappe.get_meta("Job Card").has_field( - "actual_start_date" - ): + if frappe.db.table_exists("Job Card") and frappe.get_meta("Job Card").has_field("actual_start_date"): time_logs = [] for d in frappe.get_all( "Job Card", @@ -37,9 +35,7 @@ def execute(): `tabJob Card Time Log` (from_time, to_time, time_in_mins, completed_qty, parent, parenttype, parentfield, name) values {values} - """.format( - values=",".join(["%s"] * len(time_logs)) - ), + """.format(values=",".join(["%s"] * len(time_logs))), tuple(time_logs), ) diff --git a/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py b/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py index b681f25d84ec..b4095ee4e84c 100644 --- a/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py +++ b/erpnext/patches/v11_1/move_customer_lead_to_dynamic_column.py @@ -8,14 +8,10 @@ def execute(): frappe.reload_doctype("Quotation") frappe.db.sql(""" UPDATE `tabQuotation` set party_name = lead WHERE quotation_to = 'Lead' """) - frappe.db.sql( - """ UPDATE `tabQuotation` set party_name = customer WHERE quotation_to = 'Customer' """ - ) + frappe.db.sql(""" UPDATE `tabQuotation` set party_name = customer WHERE quotation_to = 'Customer' """) frappe.reload_doctype("Opportunity") - frappe.db.sql( - """ UPDATE `tabOpportunity` set party_name = lead WHERE opportunity_from = 'Lead' """ - ) + frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = lead WHERE opportunity_from = 'Lead' """) frappe.db.sql( """ UPDATE `tabOpportunity` set party_name = customer WHERE opportunity_from = 'Customer' """ ) diff --git a/erpnext/patches/v11_1/set_missing_opportunity_from.py b/erpnext/patches/v11_1/set_missing_opportunity_from.py index ae5f62001458..fd3bf7ef4459 100644 --- a/erpnext/patches/v11_1/set_missing_opportunity_from.py +++ b/erpnext/patches/v11_1/set_missing_opportunity_from.py @@ -2,7 +2,6 @@ def execute(): - frappe.reload_doctype("Opportunity") if frappe.db.has_column("Opportunity", "enquiry_from"): frappe.db.sql( @@ -10,9 +9,7 @@ def execute(): where ifnull(opportunity_from, '') = '' and ifnull(enquiry_from, '') != ''""" ) - if frappe.db.has_column("Opportunity", "lead") and frappe.db.has_column( - "Opportunity", "enquiry_from" - ): + if frappe.db.has_column("Opportunity", "lead") and frappe.db.has_column("Opportunity", "enquiry_from"): frappe.db.sql( """ UPDATE `tabOpportunity` set party_name = lead where enquiry_from = 'Lead' and ifnull(party_name, '') = '' and ifnull(lead, '') != ''""" diff --git a/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py b/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py index 284b616bbdae..0029074da94a 100644 --- a/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py +++ b/erpnext/patches/v12_0/add_default_buying_selling_terms_in_company.py @@ -11,9 +11,7 @@ def execute(): if frappe.db.has_column("Company", "default_terms"): rename_field("Company", "default_terms", "default_selling_terms") - for company in frappe.get_all( - "Company", ["name", "default_selling_terms", "default_buying_terms"] - ): + for company in frappe.get_all("Company", ["name", "default_selling_terms", "default_buying_terms"]): if company.default_selling_terms and not company.default_buying_terms: frappe.db.set_value( "Company", company.name, "default_buying_terms", company.default_selling_terms diff --git a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py index 744ea1ccd8a6..c3bf4a0f39e1 100644 --- a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py +++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py @@ -3,7 +3,6 @@ def execute(): - frappe.reload_doc("accounts", "doctype", "accounting_dimension") accounting_dimensions = frappe.db.sql( @@ -17,7 +16,6 @@ def execute(): count = 1 for d in accounting_dimensions: - if count % 2 == 0: insert_after_field = "dimension_col_break" else: @@ -31,7 +29,6 @@ def execute(): "Expense Claim Detail", "Expense Taxes and Charges", ]: - field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname}) if field: diff --git a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py index 80e9047cf067..8c7f6bd225f8 100644 --- a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py +++ b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py @@ -4,7 +4,6 @@ def execute(): - frappe.reload_doc("accounts", "doctype", "allowed_to_transact_with", force=True) frappe.reload_doc("accounts", "doctype", "pricing_rule_detail", force=True) frappe.reload_doc("crm", "doctype", "lost_reason_detail", force=True) diff --git a/erpnext/patches/v12_0/fix_quotation_expired_status.py b/erpnext/patches/v12_0/fix_quotation_expired_status.py index 285183bfa256..5d9c8102481b 100644 --- a/erpnext/patches/v12_0/fix_quotation_expired_status.py +++ b/erpnext/patches/v12_0/fix_quotation_expired_status.py @@ -16,9 +16,7 @@ def execute(): and qo.valid_till < so.transaction_date""" # check if SO was created after quotation expired frappe.db.sql( - """UPDATE `tabQuotation` qo SET qo.status = 'Expired' WHERE {cond} and exists({invalid_so_against_quo})""".format( - cond=cond, invalid_so_against_quo=invalid_so_against_quo - ) + f"""UPDATE `tabQuotation` qo SET qo.status = 'Expired' WHERE {cond} and exists({invalid_so_against_quo})""" ) valid_so_against_quo = """ @@ -31,7 +29,5 @@ def execute(): and qo.valid_till >= so.transaction_date""" # check if SO was created before quotation expired frappe.db.sql( - """UPDATE `tabQuotation` qo SET qo.status = 'Closed' WHERE {cond} and exists({valid_so_against_quo})""".format( - cond=cond, valid_so_against_quo=valid_so_against_quo - ) + f"""UPDATE `tabQuotation` qo SET qo.status = 'Closed' WHERE {cond} and exists({valid_so_against_quo})""" ) diff --git a/erpnext/patches/v12_0/make_item_manufacturer.py b/erpnext/patches/v12_0/make_item_manufacturer.py index 3f233659d016..67d6f974005d 100644 --- a/erpnext/patches/v12_0/make_item_manufacturer.py +++ b/erpnext/patches/v12_0/make_item_manufacturer.py @@ -30,8 +30,6 @@ def execute(): """ INSERT INTO `tabItem Manufacturer` (`name`, `item_code`, `manufacturer`, `manufacturer_part_no`, `creation`, `owner`) - VALUES {}""".format( - ", ".join(["%s"] * len(item_manufacturer)) - ), + VALUES {}""".format(", ".join(["%s"] * len(item_manufacturer))), tuple(item_manufacturer), ) diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py index 671dfd116d21..e6f522b8c94a 100644 --- a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py +++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py @@ -16,7 +16,7 @@ def execute(): SET b.swift_number = ba.swift_number WHERE b.name = ba.bank """ ) - except Exception as e: + except Exception: frappe.log_error("Bank to Bank Account patch migration failed") frappe.reload_doc("accounts", "doctype", "bank_account") diff --git a/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py b/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py index 17c1966624ec..67fe5db516e0 100644 --- a/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py +++ b/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py @@ -29,12 +29,10 @@ def move_credit_limit_to_child_table(): fields = ", bypass_credit_limit_check_at_sales_order" credit_limit_records = frappe.db.sql( - """ - SELECT name, credit_limit {0} - FROM `tab{1}` where credit_limit > 0 - """.format( - fields, doctype - ), + f""" + SELECT name, credit_limit {fields} + FROM `tab{doctype}` where credit_limit > 0 + """, as_dict=1, ) # nosec diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py index c4c3b692e238..8ac1991d4438 100644 --- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py +++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py @@ -80,11 +80,9 @@ def execute(): for dt in doctypes: for d in frappe.db.sql( - """select name, parenttype, parent, item_code, item_tax_rate from `tab{0} Item` + f"""select name, parenttype, parent, item_code, item_tax_rate from `tab{dt} Item` where ifnull(item_tax_rate, '') not in ('', '{{}}') - and item_tax_template is NULL""".format( - dt - ), + and item_tax_template is NULL""", as_dict=1, ): item_tax_map = json.loads(d.item_tax_rate) @@ -145,13 +143,23 @@ def get_item_tax_template( if not parent_account: parent_account = frappe.db.get_value( "Account", - filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, + filters={ + "account_type": "Tax", + "root_type": "Liability", + "is_group": 0, + "company": company, + }, fieldname="parent_account", ) if not parent_account: parent_account = frappe.db.get_value( "Account", - filters={"account_type": "Tax", "root_type": "Liability", "is_group": 1, "company": company}, + filters={ + "account_type": "Tax", + "root_type": "Liability", + "is_group": 1, + "company": company, + }, ) filters = { "account_name": account_name, diff --git a/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py b/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py index 71926107bd50..ffd8ddcf3081 100644 --- a/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py +++ b/erpnext/patches/v12_0/move_target_distribution_from_parent_to_child.py @@ -18,9 +18,7 @@ def execute(): WHERE `tab{child_doc}`.parent = `tab{parent_doc}`.name and `tab{parent_doc}`.distribution_id is not null and `tab{parent_doc}`.distribution_id != '' - """.format( - parent_doc=d, child_doc="Target Detail" - ) + """.format(parent_doc=d, child_doc="Target Detail") ) frappe.delete_doc("Report", "Sales Partner-wise Transaction Summary") diff --git a/erpnext/patches/v12_0/purchase_receipt_status.py b/erpnext/patches/v12_0/purchase_receipt_status.py index 3b828d69cb22..2869e2bcd0aa 100644 --- a/erpnext/patches/v12_0/purchase_receipt_status.py +++ b/erpnext/patches/v12_0/purchase_receipt_status.py @@ -17,16 +17,14 @@ def execute(): if not affected_purchase_receipts: return - logger.info( - "purchase_receipt_status: begin patch, PR count: {}".format(len(affected_purchase_receipts)) - ) + logger.info(f"purchase_receipt_status: begin patch, PR count: {len(affected_purchase_receipts)}") frappe.reload_doc("stock", "doctype", "Purchase Receipt") frappe.reload_doc("stock", "doctype", "Purchase Receipt Item") for pr in affected_purchase_receipts: pr_name = pr[0] - logger.info("purchase_receipt_status: patching PR - {}".format(pr_name)) + logger.info(f"purchase_receipt_status: patching PR - {pr_name}") pr_doc = frappe.get_doc("Purchase Receipt", pr_name) diff --git a/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py b/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py index e2a3887b9ac5..dfc23669e0ef 100644 --- a/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py +++ b/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py @@ -6,12 +6,8 @@ def _rename_single_field(**kwargs): count = frappe.db.sql( - "SELECT COUNT(*) FROM tabSingles WHERE doctype='{doctype}' AND field='{new_name}';".format( - **kwargs - ) - )[0][ - 0 - ] # nosec + "SELECT COUNT(*) FROM tabSingles WHERE doctype='{doctype}' AND field='{new_name}';".format(**kwargs) + )[0][0] # nosec if count == 0: frappe.db.sql( "UPDATE tabSingles SET field='{new_name}' WHERE doctype='{doctype}' AND field='{old_name}';".format( @@ -22,7 +18,5 @@ def _rename_single_field(**kwargs): def execute(): _rename_single_field(doctype="Bank Clearance", old_name="bank_account", new_name="account") - _rename_single_field( - doctype="Bank Clearance", old_name="bank_account_no", new_name="bank_account" - ) + _rename_single_field(doctype="Bank Clearance", old_name="bank_account_no", new_name="bank_account") frappe.reload_doc("Accounts", "doctype", "Bank Clearance") diff --git a/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py index a4a85871ea2e..69ddb603d7d5 100644 --- a/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py +++ b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py @@ -41,35 +41,29 @@ def execute(): cond = " AND parent_doc.update_stock = 1" data = frappe.db.sql( - """ SELECT parent_doc.name as name, child_doc.name as child_name + f""" SELECT parent_doc.name as name, child_doc.name as child_name FROM `tab{doctype}` parent_doc, `tab{doctype} Item` child_doc WHERE parent_doc.name = child_doc.parent AND parent_doc.docstatus < 2 AND child_doc.target_warehouse is not null AND child_doc.target_warehouse != '' AND child_doc.creation > '2020-04-16' {cond} - """.format( - doctype=doctype, cond=cond - ), + """, as_dict=1, ) if data: names = [d.child_name for d in data] frappe.db.sql( - """ UPDATE `tab{0} Item` set target_warehouse = null - WHERE name in ({1}) """.format( - doctype, ",".join(["%s"] * len(names)) - ), + """ UPDATE `tab{} Item` set target_warehouse = null + WHERE name in ({}) """.format(doctype, ",".join(["%s"] * len(names))), tuple(names), ) frappe.db.sql( """ UPDATE `tabPacked Item` set target_warehouse = null - WHERE parenttype = '{0}' and parent_detail_docname in ({1}) - """.format( - doctype, ",".join(["%s"] * len(names)) - ), + WHERE parenttype = '{}' and parent_detail_docname in ({}) + """.format(doctype, ",".join(["%s"] * len(names))), tuple(names), ) diff --git a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py index d88593b49847..5d1cb64bf6ba 100644 --- a/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py +++ b/erpnext/patches/v12_0/set_against_blanket_order_in_sales_and_purchase_order.py @@ -2,17 +2,14 @@ def execute(): - frappe.reload_doc("selling", "doctype", "sales_order_item", force=True) frappe.reload_doc("buying", "doctype", "purchase_order_item", force=True) for doctype in ("Sales Order Item", "Purchase Order Item"): frappe.db.sql( - """ - UPDATE `tab{0}` + f""" + UPDATE `tab{doctype}` SET against_blanket_order = 1 WHERE ifnull(blanket_order, '') != '' - """.format( - doctype - ) + """ ) diff --git a/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py b/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py index 37af989549fa..8f29fc888e04 100644 --- a/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py +++ b/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py @@ -4,6 +4,4 @@ def execute(): frappe.reload_doc("accounts", "doctype", "accounts_settings") - frappe.db.set_value( - "Accounts Settings", None, "automatically_process_deferred_accounting_entry", 1 - ) + frappe.db.set_value("Accounts Settings", None, "automatically_process_deferred_accounting_entry", 1) diff --git a/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py b/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py index 562ebed757bd..a5b9f43da8f6 100644 --- a/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py +++ b/erpnext/patches/v12_0/set_produced_qty_field_in_sales_order_for_work_order.py @@ -12,6 +12,5 @@ def execute(): fields=["sales_order", "sales_order_item"], filters={"sales_order": ("!=", ""), "sales_order_item": ("!=", "")}, ): - # update produced qty in sales order update_produced_qty_in_so_item(d.sales_order, d.sales_order_item) diff --git a/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py b/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py index 2edf0f54fcfe..e8207316baf9 100644 --- a/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py +++ b/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py @@ -4,7 +4,6 @@ def execute(): - frappe.reload_doc("stock", "doctype", "delivery_note_item", force=True) frappe.reload_doc("stock", "doctype", "purchase_receipt_item", force=True) @@ -50,14 +49,12 @@ def make_return_document_map(doctype, return_document_map): Format => { 'document' : ['return_document_1','return_document_2'] }""" return_against_documents = frappe.db.sql( - """ + f""" SELECT return_against as document, name as return_document FROM `tab{doctype}` WHERE - is_return = 1 and docstatus = 1""".format( - doctype=doctype - ), + is_return = 1 and docstatus = 1""", as_dict=1, ) # nosec @@ -72,7 +69,7 @@ def set_document_detail_in_return_document(doctype): return_document_map = defaultdict(list) detail_field = "purchase_receipt_item" if doctype == "Purchase Receipt" else "dn_detail" - child_doc = frappe.scrub("{0} Item".format(doctype)) + child_doc = frappe.scrub(f"{doctype} Item") frappe.reload_doc("stock", "doctype", child_doc) return_document_map = make_return_document_map(doctype, return_document_map) @@ -89,7 +86,8 @@ def set_document_detail_in_return_document(doctype): for return_item in return_doc_items: for doc_item in doc_items: if ( - row_is_mappable(doc_item, return_item, detail_field) and doc_item.get("name") not in mapped + row_is_mappable(doc_item, return_item, detail_field) + and doc_item.get("name") not in mapped ): map_rows(doc_item, return_item, detail_field, doctype) mapped.append(doc_item.get("name")) diff --git a/erpnext/patches/v12_0/set_quotation_status.py b/erpnext/patches/v12_0/set_quotation_status.py index bebedd3a498a..edfb4a4544a7 100644 --- a/erpnext/patches/v12_0/set_quotation_status.py +++ b/erpnext/patches/v12_0/set_quotation_status.py @@ -2,7 +2,6 @@ def execute(): - frappe.db.sql( """ UPDATE `tabQuotation` set status = 'Open' where docstatus = 1 and status = 'Submitted' """ diff --git a/erpnext/patches/v12_0/set_task_status.py b/erpnext/patches/v12_0/set_task_status.py index 1c6654e57acd..27810d7abe98 100644 --- a/erpnext/patches/v12_0/set_task_status.py +++ b/erpnext/patches/v12_0/set_task_status.py @@ -10,7 +10,7 @@ def execute(): ) if property_setter_name: property_setter = frappe.get_doc("Property Setter", property_setter_name) - if not "Completed" in property_setter.value: + if "Completed" not in property_setter.value: property_setter.value = property_setter.value + "\nCompleted" property_setter.save() diff --git a/erpnext/patches/v12_0/stock_entry_enhancements.py b/erpnext/patches/v12_0/stock_entry_enhancements.py index db099a304cf6..75749a499727 100644 --- a/erpnext/patches/v12_0/stock_entry_enhancements.py +++ b/erpnext/patches/v12_0/stock_entry_enhancements.py @@ -28,7 +28,6 @@ def create_stock_entry_types(): "Repack", "Send to Subcontractor", ]: - ste_type = frappe.get_doc({"doctype": "Stock Entry Type", "name": purpose, "purpose": purpose}) try: diff --git a/erpnext/patches/v12_0/update_bom_in_so_mr.py b/erpnext/patches/v12_0/update_bom_in_so_mr.py index 114f65d100e2..88ac90d9f973 100644 --- a/erpnext/patches/v12_0/update_bom_in_so_mr.py +++ b/erpnext/patches/v12_0/update_bom_in_so_mr.py @@ -11,14 +11,12 @@ def execute(): condition = " and doc.per_ordered < 100 and doc.material_request_type = 'Manufacture'" frappe.db.sql( - """ UPDATE `tab{doc}` as doc, `tab{doc} Item` as child_doc, tabItem as item + f""" UPDATE `tab{doctype}` as doc, `tab{doctype} Item` as child_doc, tabItem as item SET child_doc.bom_no = item.default_bom WHERE child_doc.item_code = item.name and child_doc.docstatus < 2 and child_doc.parent = doc.name - and item.default_bom is not null and item.default_bom != '' {cond} - """.format( - doc=doctype, cond=condition - ) + and item.default_bom is not null and item.default_bom != '' {condition} + """ ) diff --git a/erpnext/patches/v12_0/update_is_cancelled_field.py b/erpnext/patches/v12_0/update_is_cancelled_field.py index 398dd700eda5..ea9a06bdcd8f 100644 --- a/erpnext/patches/v12_0/update_is_cancelled_field.py +++ b/erpnext/patches/v12_0/update_is_cancelled_field.py @@ -17,20 +17,16 @@ def execute(): continue frappe.db.sql( - """ + f""" UPDATE `tab{doctype}` SET is_cancelled = 0 - where is_cancelled in ('', 'No') or is_cancelled is NULL""".format( - doctype=doctype - ) + where is_cancelled in ('', 'No') or is_cancelled is NULL""" ) frappe.db.sql( - """ + f""" UPDATE `tab{doctype}` SET is_cancelled = 1 - where is_cancelled = 'Yes'""".format( - doctype=doctype - ) + where is_cancelled = 'Yes'""" ) frappe.reload_doc(module, "doctype", frappe.scrub(doctype)) diff --git a/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py b/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py index 7dc0af9a1aa1..26db58dffe8b 100644 --- a/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py +++ b/erpnext/patches/v12_0/update_owner_fields_in_acc_dimension_custom_fields.py @@ -19,8 +19,7 @@ def execute(): """ UPDATE `tabCustom Field` SET owner = 'Administrator' - WHERE fieldname = %s - AND dt IN (%s)""" - % ("%s", ", ".join(["%s"] * len(doclist))), # nosec - tuple([dimension.fieldname] + doclist), + WHERE fieldname = {} + AND dt IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec + tuple([dimension.fieldname, *doclist]), ) diff --git a/erpnext/patches/v12_0/update_pricing_rule_fields.py b/erpnext/patches/v12_0/update_pricing_rule_fields.py index 8da06b0bda06..f4eee85dd25a 100644 --- a/erpnext/patches/v12_0/update_pricing_rule_fields.py +++ b/erpnext/patches/v12_0/update_pricing_rule_fields.py @@ -8,7 +8,6 @@ def execute(): - if not frappe.get_all("Pricing Rule", limit=1): return @@ -33,20 +32,16 @@ def execute(): child_doctype = doctype + " Item" frappe.db.sql( - """ UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule + f""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' - """.format( - child_doctype=child_doctype - ) + """ ) data = frappe.db.sql( - """ SELECT pricing_rule, name, parent, + f""" SELECT pricing_rule, name, parent, parenttype, creation, modified, docstatus, modified_by, owner, name - FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null - and pricing_rule != ''""".format( - child_doc=child_doctype - ), + FROM `tab{child_doctype}` where docstatus < 2 and pricing_rule is not null + and pricing_rule != ''""", as_dict=1, ) @@ -73,9 +68,7 @@ def execute(): """ INSERT INTO `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) - VALUES {values} """.format( - values=", ".join(["%s"] * len(values)) - ), + VALUES {values} """.format(values=", ".join(["%s"] * len(values))), tuple(values), ) @@ -116,8 +109,6 @@ def execute(): """ INSERT INTO `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, owner, modified_by, name) - VALUES {values} """.format( - doctype=doctype, field=field, values=", ".join(["%s"] * len(values)) - ), + VALUES {values} """.format(doctype=doctype, field=field, values=", ".join(["%s"] * len(values))), tuple(values), ) diff --git a/erpnext/patches/v13_0/add_bin_unique_constraint.py b/erpnext/patches/v13_0/add_bin_unique_constraint.py index 7ad2bec85989..92fc7024d8d2 100644 --- a/erpnext/patches/v13_0/add_bin_unique_constraint.py +++ b/erpnext/patches/v13_0/add_bin_unique_constraint.py @@ -21,7 +21,6 @@ def delete_broken_bins(): def delete_and_patch_duplicate_bins(): - duplicate_bins = frappe.db.sql( """ SELECT diff --git a/erpnext/patches/v13_0/add_cost_center_in_loans.py b/erpnext/patches/v13_0/add_cost_center_in_loans.py index e293cf2874ea..f4c29150865c 100644 --- a/erpnext/patches/v13_0/add_cost_center_in_loans.py +++ b/erpnext/patches/v13_0/add_cost_center_in_loans.py @@ -7,6 +7,4 @@ def execute(): for company in frappe.get_all("Company", pluck="name"): default_cost_center = frappe.db.get_value("Company", company, "cost_center") - frappe.qb.update(loan).set(loan.cost_center, default_cost_center).where( - loan.company == company - ).run() + frappe.qb.update(loan).set(loan.cost_center, default_cost_center).where(loan.company == company).run() diff --git a/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py b/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py index ddbb7fd0f1b8..fb7540e1a008 100644 --- a/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py +++ b/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py @@ -13,9 +13,7 @@ def execute(): return frappe.reload_doc("manufacturing", "doctype", "manufacturing_settings") - if cint( - frappe.db.get_single_value("Manufacturing Settings", "make_serial_no_batch_from_work_order") - ): + if cint(frappe.db.get_single_value("Manufacturing Settings", "make_serial_no_batch_from_work_order")): return frappe.reload_doc("manufacturing", "doctype", "work_order") @@ -76,9 +74,7 @@ def execute(): def set_expense_account(doc): for row in doc.items: if row.is_finished_item and not row.expense_account: - row.expense_account = frappe.get_cached_value( - "Company", doc.company, "stock_adjustment_account" - ) + row.expense_account = frappe.get_cached_value("Company", doc.company, "stock_adjustment_account") def repost_stock_entry(doc): diff --git a/erpnext/patches/v13_0/add_po_to_global_search.py b/erpnext/patches/v13_0/add_po_to_global_search.py index 514cd343900a..c07b6d91181f 100644 --- a/erpnext/patches/v13_0/add_po_to_global_search.py +++ b/erpnext/patches/v13_0/add_po_to_global_search.py @@ -4,9 +4,7 @@ def execute(): global_search_settings = frappe.get_single("Global Search Settings") - if "Purchase Order" in ( - dt.document_type for dt in global_search_settings.allowed_in_global_search - ): + if "Purchase Order" in (dt.document_type for dt in global_search_settings.allowed_in_global_search): return global_search_settings.append("allowed_in_global_search", {"document_type": "Purchase Order"}) diff --git a/erpnext/patches/v13_0/agriculture_deprecation_warning.py b/erpnext/patches/v13_0/agriculture_deprecation_warning.py index 512444ef657f..053710bfc984 100644 --- a/erpnext/patches/v13_0/agriculture_deprecation_warning.py +++ b/erpnext/patches/v13_0/agriculture_deprecation_warning.py @@ -2,7 +2,6 @@ def execute(): - click.secho( "Agriculture Domain is moved to a separate app and will be removed from ERPNext in version-14.\n" "Please install the app to continue using the Agriculture domain: https://github.com/frappe/agriculture", diff --git a/erpnext/patches/v13_0/change_default_item_manufacturer_fieldtype.py b/erpnext/patches/v13_0/change_default_item_manufacturer_fieldtype.py index 0b00188e6a8d..5baec0c67da5 100644 --- a/erpnext/patches/v13_0/change_default_item_manufacturer_fieldtype.py +++ b/erpnext/patches/v13_0/change_default_item_manufacturer_fieldtype.py @@ -2,7 +2,6 @@ def execute(): - # Erase all default item manufacturers that dont exist. item = frappe.qb.DocType("Item") manufacturer = frappe.qb.DocType("Manufacturer") 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 08ddbbf3375b..d0bde56cb050 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 @@ -6,9 +6,7 @@ def execute(): params = set() # get all parameters from QI readings table - for (p,) in frappe.db.get_all( - "Quality Inspection Reading", fields=["specification"], as_list=True - ): + for (p,) in frappe.db.get_all("Quality Inspection Reading", fields=["specification"], as_list=True): params.add(p.strip()) # get all parameters from QI Template as some may be unused in QI diff --git a/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py b/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py index 1bac0fdbf0b5..b3e9593bd2cb 100644 --- a/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py +++ b/erpnext/patches/v13_0/convert_to_website_item_in_item_card_group_template.py @@ -1,5 +1,4 @@ import json -from typing import List, Union import frappe @@ -42,7 +41,7 @@ def execute(): ) -def generate_fields_to_edit() -> List: +def generate_fields_to_edit() -> list: fields = [] for i in range(1, 13): fields.append(f"card_{i}_item") # fields like 'card_1_item', etc. @@ -50,7 +49,7 @@ def generate_fields_to_edit() -> List: return fields -def make_new_website_item(item: str) -> Union[str, None]: +def make_new_website_item(item: str) -> str | None: try: doc = frappe.get_doc("Item", item) web_item = make_website_item(doc) # returns [website_item.name, item_name] diff --git a/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py b/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py index e8d0b593e6fa..59ca96bd0bd1 100644 --- a/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py +++ b/erpnext/patches/v13_0/copy_custom_field_filters_to_website_item.py @@ -84,11 +84,9 @@ def get_table_multiselect_data(docfield): move_table_multiselect_data(df) else: frappe.db.sql( # nosemgrep - """ + f""" UPDATE `tabWebsite Item` wi, `tabItem` i - SET wi.{0} = i.{0} + SET wi.{row.fieldname} = i.{row.fieldname} WHERE wi.item_code = i.item_code - """.format( - row.fieldname - ) + """ ) diff --git a/erpnext/patches/v13_0/create_accounting_dimensions_in_orders.py b/erpnext/patches/v13_0/create_accounting_dimensions_in_orders.py index 8e6bce66fe4b..84b17a5515e7 100644 --- a/erpnext/patches/v13_0/create_accounting_dimensions_in_orders.py +++ b/erpnext/patches/v13_0/create_accounting_dimensions_in_orders.py @@ -12,14 +12,12 @@ def execute(): count = 1 for d in accounting_dimensions: - if count % 2 == 0: insert_after_field = "dimension_col_break" else: insert_after_field = "accounting_dimensions_section" for doctype in ["Purchase Order", "Purchase Receipt", "Sales Order"]: - field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname}) if field: @@ -36,7 +34,7 @@ def execute(): try: create_custom_field(doctype, df, ignore_validate=True) frappe.clear_cache(doctype=doctype) - except Exception as e: + except Exception: pass count += 1 diff --git a/erpnext/patches/v13_0/create_accounting_dimensions_in_pos_doctypes.py b/erpnext/patches/v13_0/create_accounting_dimensions_in_pos_doctypes.py index 51ab0e8b65c8..b9e703373c56 100644 --- a/erpnext/patches/v13_0/create_accounting_dimensions_in_pos_doctypes.py +++ b/erpnext/patches/v13_0/create_accounting_dimensions_in_pos_doctypes.py @@ -15,14 +15,12 @@ def execute(): count = 1 for d in accounting_dimensions: - if count % 2 == 0: insert_after_field = "dimension_col_break" else: insert_after_field = "accounting_dimensions_section" for doctype in ["POS Invoice", "POS Invoice Item"]: - field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname}) if field: diff --git a/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py b/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py index 66aae9a30af6..d28f8c95f6d5 100644 --- a/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py +++ b/erpnext/patches/v13_0/create_uae_pos_invoice_fields.py @@ -8,9 +8,7 @@ def execute(): - company = frappe.get_all( - "Company", filters={"country": ["in", ["Saudi Arabia", "United Arab Emirates"]]} - ) + company = frappe.get_all("Company", filters={"country": ["in", ["Saudi Arabia", "United Arab Emirates"]]}) if not company: return diff --git a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py index 5cbd0b5fcb56..e748f52521a1 100644 --- a/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py +++ b/erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py @@ -9,9 +9,7 @@ def execute(): if not company: return - TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value( - "TaxJar Settings", "taxjar_create_transactions" - ) + TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions") TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax") TAXJAR_SANDBOX_MODE = frappe.db.get_single_value("TaxJar Settings", "is_sandbox") diff --git a/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py b/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py index c53eb794378a..46946a8a0e78 100644 --- a/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py +++ b/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py @@ -6,9 +6,7 @@ def execute(): - if frappe.db.exists("DocType", "Bank Reconciliation Detail") and frappe.db.exists( "DocType", "Bank Clearance Detail" ): - frappe.delete_doc("DocType", "Bank Reconciliation Detail", force=1) diff --git a/erpnext/patches/v13_0/enable_provisional_accounting.py b/erpnext/patches/v13_0/enable_provisional_accounting.py index dd18167b7186..6edb423cfc46 100644 --- a/erpnext/patches/v13_0/enable_provisional_accounting.py +++ b/erpnext/patches/v13_0/enable_provisional_accounting.py @@ -11,6 +11,4 @@ def execute(): company.enable_perpetual_inventory_for_non_stock_items, ).set(company.default_provisional_account, company.service_received_but_not_billed).where( company.enable_perpetual_inventory_for_non_stock_items == 1 - ).where( - company.service_received_but_not_billed.isnotnull() - ).run() + ).where(company.service_received_but_not_billed.isnotnull()).run() diff --git a/erpnext/patches/v13_0/fix_additional_cost_in_mfg_stock_entry.py b/erpnext/patches/v13_0/fix_additional_cost_in_mfg_stock_entry.py index aeb8d8eb5888..e305b375c7fb 100644 --- a/erpnext/patches/v13_0/fix_additional_cost_in_mfg_stock_entry.py +++ b/erpnext/patches/v13_0/fix_additional_cost_in_mfg_stock_entry.py @@ -1,4 +1,4 @@ -from typing import List, NewType +from typing import NewType import frappe @@ -13,7 +13,7 @@ def execute(): create_repost_item_valuation(patched_stock_entry) -def find_broken_stock_entries() -> List[StockEntryCode]: +def find_broken_stock_entries() -> list[StockEntryCode]: period_closing_date = frappe.db.get_value( "Period Closing Voucher", {"docstatus": 1}, "posting_date", order_by="posting_date desc" ) diff --git a/erpnext/patches/v13_0/fix_invoice_statuses.py b/erpnext/patches/v13_0/fix_invoice_statuses.py index 253b425c58b6..dc15a019a383 100644 --- a/erpnext/patches/v13_0/fix_invoice_statuses.py +++ b/erpnext/patches/v13_0/fix_invoice_statuses.py @@ -41,7 +41,7 @@ def execute(): ("Overdue", "Overdue and Discounted", "Partly Paid", "Partly Paid and Discounted"), ), "outstanding_amount": (">", 0), - "modified": (">", "2021-01-01") + "modified": (">", "2021-01-01"), # an assumption is being made that only invoices modified # after 2021 got affected as incorrectly overdue. # required for performance reasons. diff --git a/erpnext/patches/v13_0/healthcare_deprecation_warning.py b/erpnext/patches/v13_0/healthcare_deprecation_warning.py index c6fba59371cf..3fff235f446d 100644 --- a/erpnext/patches/v13_0/healthcare_deprecation_warning.py +++ b/erpnext/patches/v13_0/healthcare_deprecation_warning.py @@ -2,7 +2,6 @@ def execute(): - click.secho( "Healthcare Module is moved to a separate app and will be removed from ERPNext in version-14.\n" "Please install the app to continue using the module: https://github.com/frappe/healthcare", diff --git a/erpnext/patches/v13_0/hospitality_deprecation_warning.py b/erpnext/patches/v13_0/hospitality_deprecation_warning.py index 2708b2ccd3bf..641665145627 100644 --- a/erpnext/patches/v13_0/hospitality_deprecation_warning.py +++ b/erpnext/patches/v13_0/hospitality_deprecation_warning.py @@ -2,7 +2,6 @@ def execute(): - click.secho( "Hospitality domain is moved to a separate app and will be removed from ERPNext in version-14.\n" "When upgrading to ERPNext version-14, please install the app to continue using the Hospitality domain: https://github.com/frappe/hospitality", diff --git a/erpnext/patches/v13_0/item_naming_series_not_mandatory.py b/erpnext/patches/v13_0/item_naming_series_not_mandatory.py index 0235a621ce04..d25da7accb1d 100644 --- a/erpnext/patches/v13_0/item_naming_series_not_mandatory.py +++ b/erpnext/patches/v13_0/item_naming_series_not_mandatory.py @@ -4,7 +4,6 @@ def execute(): - stock_settings = frappe.get_doc("Stock Settings") set_by_naming_series( diff --git a/erpnext/patches/v13_0/move_branch_code_to_bank_account.py b/erpnext/patches/v13_0/move_branch_code_to_bank_account.py index 240612714840..79c79ffb5923 100644 --- a/erpnext/patches/v13_0/move_branch_code_to_bank_account.py +++ b/erpnext/patches/v13_0/move_branch_code_to_bank_account.py @@ -6,13 +6,10 @@ def execute(): - frappe.reload_doc("accounts", "doctype", "bank_account") frappe.reload_doc("accounts", "doctype", "bank") - if frappe.db.has_column("Bank", "branch_code") and frappe.db.has_column( - "Bank Account", "branch_code" - ): + if frappe.db.has_column("Bank", "branch_code") and frappe.db.has_column("Bank Account", "branch_code"): frappe.db.sql( """UPDATE `tabBank` b, `tabBank Account` ba SET ba.branch_code = b.branch_code diff --git a/erpnext/patches/v13_0/non_profit_deprecation_warning.py b/erpnext/patches/v13_0/non_profit_deprecation_warning.py index 5b54b25a5bc4..173664625ad6 100644 --- a/erpnext/patches/v13_0/non_profit_deprecation_warning.py +++ b/erpnext/patches/v13_0/non_profit_deprecation_warning.py @@ -2,7 +2,6 @@ def execute(): - click.secho( "Non Profit Domain is moved to a separate app and will be removed from ERPNext in version-14.\n" "When upgrading to ERPNext version-14, please install the app to continue using the Non Profit domain: https://github.com/frappe/non_profit", diff --git a/erpnext/patches/v13_0/rename_issue_doctype_fields.py b/erpnext/patches/v13_0/rename_issue_doctype_fields.py index a9b6df709853..dfa76a78dc3e 100644 --- a/erpnext/patches/v13_0/rename_issue_doctype_fields.py +++ b/erpnext/patches/v13_0/rename_issue_doctype_fields.py @@ -57,7 +57,11 @@ def execute(): for entry in opportunities: mins_to_first_response = convert_to_seconds(entry.mins_to_first_response, "Minutes") frappe.db.set_value( - "Opportunity", entry.name, "first_response_time", mins_to_first_response, update_modified=False + "Opportunity", + entry.name, + "first_response_time", + mins_to_first_response, + update_modified=False, ) # commit after every 100 updates count += 1 diff --git a/erpnext/patches/v13_0/requeue_failed_reposts.py b/erpnext/patches/v13_0/requeue_failed_reposts.py index 752490da3049..c7dfaa256a37 100644 --- a/erpnext/patches/v13_0/requeue_failed_reposts.py +++ b/erpnext/patches/v13_0/requeue_failed_reposts.py @@ -3,7 +3,6 @@ def execute(): - reposts = frappe.get_all( "Repost Item Valuation", {"status": "Failed", "modified": [">", "2021-10-05"]}, diff --git a/erpnext/patches/v13_0/set_per_billed_in_return_delivery_note.py b/erpnext/patches/v13_0/set_per_billed_in_return_delivery_note.py index a4d701244925..40df73ee14b6 100644 --- a/erpnext/patches/v13_0/set_per_billed_in_return_delivery_note.py +++ b/erpnext/patches/v13_0/set_per_billed_in_return_delivery_note.py @@ -20,9 +20,9 @@ def execute(): .run(as_dict=True) ) - frappe.qb.update(dn_item).inner_join(dn).on(dn.name == dn_item.parent).set( - dn_item.returned_qty, 0 - ).where(dn.is_return == 1).where(dn_item.returned_qty > 0).run() + frappe.qb.update(dn_item).inner_join(dn).on(dn.name == dn_item.parent).set(dn_item.returned_qty, 0).where( + dn.is_return == 1 + ).where(dn_item.returned_qty > 0).run() for d in dn_list: dn_doc = frappe.get_doc("Delivery Note", d.get("name")) diff --git a/erpnext/patches/v13_0/set_work_order_qty_in_so_from_mr.py b/erpnext/patches/v13_0/set_work_order_qty_in_so_from_mr.py index 1adf0d84538e..be30fb12515a 100644 --- a/erpnext/patches/v13_0/set_work_order_qty_in_so_from_mr.py +++ b/erpnext/patches/v13_0/set_work_order_qty_in_so_from_mr.py @@ -28,9 +28,7 @@ def execute(): results = query.run(as_dict=True) for row in results: - so_item = frappe.get_value( - "Material Request Item", row.material_request_item, "sales_order_item" - ) + so_item = frappe.get_value("Material Request Item", row.material_request_item, "sales_order_item") frappe.db.set_value("Work Order", row.name, "sales_order_item", so_item) if so_item: diff --git a/erpnext/patches/v13_0/shopify_deprecation_warning.py b/erpnext/patches/v13_0/shopify_deprecation_warning.py index 245d1a962507..274c35faafec 100644 --- a/erpnext/patches/v13_0/shopify_deprecation_warning.py +++ b/erpnext/patches/v13_0/shopify_deprecation_warning.py @@ -2,7 +2,6 @@ def execute(): - click.secho( "Shopify Integration is moved to a separate app and will be removed from ERPNext in version-14.\n" "Please install the app to continue using the integration: https://github.com/frappe/ecommerce_integrations", diff --git a/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py b/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py index 35710a9bb4a2..41c3358e76bb 100644 --- a/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py +++ b/erpnext/patches/v13_0/shopping_cart_to_ecommerce.py @@ -3,7 +3,6 @@ def execute(): - frappe.delete_doc("DocType", "Shopping Cart Settings", ignore_missing=True) frappe.delete_doc("DocType", "Products Settings", ignore_missing=True) frappe.delete_doc("DocType", "Supplier Item Group", ignore_missing=True) @@ -13,7 +12,6 @@ def execute(): def notify_users(): - click.secho( "Shopping cart and Product settings are merged into E-commerce settings.\n" "Checkout the documentation to learn more:" diff --git a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py index b69a408e65bc..182711afda5f 100644 --- a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py +++ b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py @@ -38,9 +38,7 @@ def execute(): if correct_sr_no == sle.serial_no: continue - frappe.db.set_value( - "Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False - ) + frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False) broken_serial_nos.update(serial_no_list) if not broken_serial_nos: diff --git a/erpnext/patches/v13_0/update_accounts_in_loan_docs.py b/erpnext/patches/v13_0/update_accounts_in_loan_docs.py index bf98e9ea4207..c073ba4fb18f 100644 --- a/erpnext/patches/v13_0/update_accounts_in_loan_docs.py +++ b/erpnext/patches/v13_0/update_accounts_in_loan_docs.py @@ -14,6 +14,4 @@ def execute(): lr.payment_account, loan.payment_account ).set(lr.loan_account, loan.loan_account).set( lr.penalty_income_account, loan.penalty_income_account - ).where( - lr.docstatus < 2 - ).run() + ).where(lr.docstatus < 2).run() diff --git a/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py b/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py index 3c6c5b5b75f7..2c41a2976e98 100644 --- a/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py +++ b/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py @@ -29,7 +29,7 @@ def execute(): ) if not doc.planned_end_date: - planned_end_date = add_to_date(doc.planned_start_date, minutes=doc.lead_time) + add_to_date(doc.planned_start_date, minutes=doc.lead_time) doc.db_set("planned_end_date", doc.actual_start_date, update_modified=False) frappe.db.sql( diff --git a/erpnext/patches/v13_0/update_disbursement_account.py b/erpnext/patches/v13_0/update_disbursement_account.py index d6aba4720eeb..c980f63a40b0 100644 --- a/erpnext/patches/v13_0/update_disbursement_account.py +++ b/erpnext/patches/v13_0/update_disbursement_account.py @@ -2,7 +2,6 @@ def execute(): - frappe.reload_doc("loan_management", "doctype", "loan_type") frappe.reload_doc("loan_management", "doctype", "loan") diff --git a/erpnext/patches/v13_0/update_job_card_status.py b/erpnext/patches/v13_0/update_job_card_status.py index f2d12da119af..0f5469261fcd 100644 --- a/erpnext/patches/v13_0/update_job_card_status.py +++ b/erpnext/patches/v13_0/update_job_card_status.py @@ -5,7 +5,6 @@ def execute(): - job_card = frappe.qb.DocType("Job Card") ( frappe.qb.update(job_card) diff --git a/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py b/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py index 136d34e6ff1b..183cd790ae66 100644 --- a/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py +++ b/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py @@ -13,8 +13,6 @@ def execute(): frappe.qb.update(mv).join(mvp).on(mvp.parent == mv.name).set( mv.maintenance_schedule, Coalesce(mvp.prevdoc_docname, "") - ).where( - (mv.maintenance_type == "Scheduled") & (mvp.prevdoc_docname.notnull()) & (mv.docstatus < 2) - ).run( + ).where((mv.maintenance_type == "Scheduled") & (mvp.prevdoc_docname.notnull()) & (mv.docstatus < 2)).run( as_dict=1 ) diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py index 30db996e7365..638db8a1573b 100644 --- a/erpnext/patches/v13_0/update_old_loans.py +++ b/erpnext/patches/v13_0/update_old_loans.py @@ -13,7 +13,6 @@ def execute(): - # Create a penalty account for loan types frappe.reload_doc("loan_management", "doctype", "loan_type") @@ -111,9 +110,7 @@ def execute(): loan_type_name = create_loan_type(loan, loan_type_name, penalty_account) # update loan type in loan - frappe.db.sql( - "UPDATE `tabLoan` set loan_type = %s where name = %s", (loan_type_name, loan.name) - ) + frappe.db.sql("UPDATE `tabLoan` set loan_type = %s where name = %s", (loan_type_name, loan.name)) loan_type = loan_type_name if loan_type_name not in updated_loan_types: diff --git a/erpnext/patches/v13_0/update_reserved_qty_closed_wo.py b/erpnext/patches/v13_0/update_reserved_qty_closed_wo.py index 72e77fe21613..4bba7b96c835 100644 --- a/erpnext/patches/v13_0/update_reserved_qty_closed_wo.py +++ b/erpnext/patches/v13_0/update_reserved_qty_closed_wo.py @@ -4,7 +4,6 @@ def execute(): - wo = frappe.qb.DocType("Work Order") wo_item = frappe.qb.DocType("Work Order Item") diff --git a/erpnext/patches/v13_0/update_sane_transfer_against.py b/erpnext/patches/v13_0/update_sane_transfer_against.py index 45691e2ded7d..0f58775d9cbf 100644 --- a/erpnext/patches/v13_0/update_sane_transfer_against.py +++ b/erpnext/patches/v13_0/update_sane_transfer_against.py @@ -5,7 +5,5 @@ def execute(): bom = frappe.qb.DocType("BOM") ( - frappe.qb.update(bom) - .set(bom.transfer_material_against, "Work Order") - .where(bom.with_operations == 0) + frappe.qb.update(bom).set(bom.transfer_material_against, "Work Order").where(bom.with_operations == 0) ).run() diff --git a/erpnext/patches/v13_0/update_schedule_type_in_loans.py b/erpnext/patches/v13_0/update_schedule_type_in_loans.py index e5b5f643604f..757758b5bf99 100644 --- a/erpnext/patches/v13_0/update_schedule_type_in_loans.py +++ b/erpnext/patches/v13_0/update_schedule_type_in_loans.py @@ -9,6 +9,6 @@ def execute(): loan_type.repayment_schedule_type, "Monthly as per repayment start date" ).where(loan_type.is_term_loan == 1).run() - frappe.qb.update(loan).set( - loan.repayment_schedule_type, "Monthly as per repayment start date" - ).where(loan.is_term_loan == 1).run() + frappe.qb.update(loan).set(loan.repayment_schedule_type, "Monthly as per repayment start date").where( + loan.is_term_loan == 1 + ).run() diff --git a/erpnext/patches/v13_0/update_sla_enhancements.py b/erpnext/patches/v13_0/update_sla_enhancements.py index 84c683acd2c8..8464fa8acbc6 100644 --- a/erpnext/patches/v13_0/update_sla_enhancements.py +++ b/erpnext/patches/v13_0/update_sla_enhancements.py @@ -39,14 +39,16 @@ def execute(): for priority in priorities: if priority.parenttype == "Service Level Agreement": response_time = convert_to_seconds(priority.response_time, priority.response_time_period) - resolution_time = convert_to_seconds(priority.resolution_time, priority.resolution_time_period) + resolution_time = convert_to_seconds( + priority.resolution_time, priority.resolution_time_period + ) frappe.db.set_value( "Service Level Priority", priority.name, {"response_time": response_time, "resolution_time": resolution_time}, ) if priority.parenttype == "Service Level": - if not priority.parent in priority_dict: + if priority.parent not in priority_dict: priority_dict[priority.parent] = [] priority_dict[priority.parent].append(priority) @@ -86,7 +88,9 @@ def execute(): { "priority": priority.priority, "default_priority": priority.default_priority, - "response_time": convert_to_seconds(priority.response_time, priority.response_time_period), + "response_time": convert_to_seconds( + priority.response_time, priority.response_time_period + ), "resolution_time": convert_to_seconds( priority.resolution_time, priority.resolution_time_period ), diff --git a/erpnext/patches/v13_0/update_subscription.py b/erpnext/patches/v13_0/update_subscription.py index 66b3def79c46..96bd14621da9 100644 --- a/erpnext/patches/v13_0/update_subscription.py +++ b/erpnext/patches/v13_0/update_subscription.py @@ -6,7 +6,6 @@ def execute(): - frappe.reload_doc("accounts", "doctype", "subscription") frappe.reload_doc("accounts", "doctype", "subscription_invoice") frappe.reload_doc("accounts", "doctype", "subscription_plan") diff --git a/erpnext/patches/v13_0/update_timesheet_changes.py b/erpnext/patches/v13_0/update_timesheet_changes.py index 02654c11d300..c54b4cbe1038 100644 --- a/erpnext/patches/v13_0/update_timesheet_changes.py +++ b/erpnext/patches/v13_0/update_timesheet_changes.py @@ -20,12 +20,10 @@ def execute(): ) frappe.db.sql( - """UPDATE `tabTimesheet` - SET currency = '{0}', + f"""UPDATE `tabTimesheet` + SET currency = '{base_currency}', exchange_rate = 1.0, base_total_billable_amount = total_billable_amount, base_total_billed_amount = total_billed_amount, - base_total_costing_amount = total_costing_amount""".format( - base_currency - ) + base_total_costing_amount = total_costing_amount""" ) diff --git a/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py b/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py index 693d06dc1a0b..280635c41bc3 100644 --- a/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py +++ b/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py @@ -2,7 +2,6 @@ def execute(): - doctype = "Stock Reconciliation Item" if not frappe.db.has_column(doctype, "current_serial_no"): @@ -11,6 +10,4 @@ def execute(): sr_item = frappe.qb.DocType(doctype) - ( - frappe.qb.update(sr_item).set(sr_item.current_serial_no, None).where(sr_item.current_qty == 0) - ).run() + (frappe.qb.update(sr_item).set(sr_item.current_serial_no, None).where(sr_item.current_qty == 0)).run() diff --git a/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py b/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py index 9b07ba846f42..a044bb0d9ab5 100644 --- a/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py +++ b/erpnext/patches/v14_0/change_is_subcontracted_fieldtype.py @@ -7,20 +7,16 @@ def execute(): for doctype in ["Purchase Order", "Purchase Receipt", "Purchase Invoice", "Supplier Quotation"]: frappe.db.sql( - """ + f""" UPDATE `tab{doctype}` SET is_subcontracted = 0 - where is_subcontracted in ('', 'No') or is_subcontracted is null""".format( - doctype=doctype - ) + where is_subcontracted in ('', 'No') or is_subcontracted is null""" ) frappe.db.sql( - """ + f""" UPDATE `tab{doctype}` SET is_subcontracted = 1 - where is_subcontracted = 'Yes'""".format( - doctype=doctype - ) + where is_subcontracted = 'Yes'""" ) frappe.reload_doc(frappe.get_meta(doctype).module, "doctype", frappe.scrub(doctype)) diff --git a/erpnext/patches/v14_0/copy_is_subcontracted_value_to_is_old_subcontracting_flow.py b/erpnext/patches/v14_0/copy_is_subcontracted_value_to_is_old_subcontracting_flow.py index 607ef69538ed..40a408b96a6b 100644 --- a/erpnext/patches/v14_0/copy_is_subcontracted_value_to_is_old_subcontracting_flow.py +++ b/erpnext/patches/v14_0/copy_is_subcontracted_value_to_is_old_subcontracting_flow.py @@ -7,6 +7,4 @@ def execute(): for doctype in ["Purchase Order", "Purchase Receipt", "Purchase Invoice"]: tab = frappe.qb.DocType(doctype).as_("tab") - frappe.qb.update(tab).set(tab.is_old_subcontracting_flow, 1).where( - tab.is_subcontracted == 1 - ).run() + frappe.qb.update(tab).set(tab.is_old_subcontracting_flow, 1).where(tab.is_subcontracted == 1).run() diff --git a/erpnext/patches/v14_0/correct_asset_value_if_je_with_workflow.py b/erpnext/patches/v14_0/correct_asset_value_if_je_with_workflow.py index aededa2287d6..dba27b4044dc 100644 --- a/erpnext/patches/v14_0/correct_asset_value_if_je_with_workflow.py +++ b/erpnext/patches/v14_0/correct_asset_value_if_je_with_workflow.py @@ -39,9 +39,7 @@ def correct_value_for_assets_with_manual_depr_entries(): asset.opening_accumulated_depreciation.as_("opening_accumulated_depreciation"), Sum(gle.debit).as_("depr_amount"), ) - .where( - gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account) - ) + .where(gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account)) .where(gle.debit != 0) .where(gle.is_cancelled == 0) .where(asset.docstatus == 1) @@ -80,9 +78,7 @@ def correct_value_for_assets_with_auto_depr(fb_name=None): asset.opening_accumulated_depreciation.as_("opening_accumulated_depreciation"), Sum(gle.debit).as_("depr_amount"), ) - .where( - gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account) - ) + .where(gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account)) .where(gle.debit != 0) .where(gle.is_cancelled == 0) .where(asset.docstatus == 1) diff --git a/erpnext/patches/v14_0/create_accounting_dimensions_in_subcontracting_doctypes.py b/erpnext/patches/v14_0/create_accounting_dimensions_in_subcontracting_doctypes.py index b349c07f6df2..aedf2f176fdc 100644 --- a/erpnext/patches/v14_0/create_accounting_dimensions_in_subcontracting_doctypes.py +++ b/erpnext/patches/v14_0/create_accounting_dimensions_in_subcontracting_doctypes.py @@ -12,7 +12,6 @@ def execute(): count = 1 for d in accounting_dimensions: - if count % 2 == 0: insert_after_field = "dimension_col_break" else: @@ -24,7 +23,6 @@ def execute(): "Subcontracting Receipt", "Subcontracting Receipt Item", ]: - field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname}) if field: diff --git a/erpnext/patches/v14_0/crm_ux_cleanup.py b/erpnext/patches/v14_0/crm_ux_cleanup.py index b2df36ff3517..186ccf8bb3ba 100644 --- a/erpnext/patches/v14_0/crm_ux_cleanup.py +++ b/erpnext/patches/v14_0/crm_ux_cleanup.py @@ -45,7 +45,8 @@ def add_calendar_event_for_leads(): "owner": d.lead_owner, "subject": ("Contact " + cstr(d.lead_name)), "description": ( - ("Contact " + cstr(d.lead_name)) + (("
    By: " + cstr(d.contact_by)) if d.contact_by else "") + ("Contact " + cstr(d.lead_name)) + + (("
    By: " + cstr(d.contact_by)) if d.contact_by else "") ), "starts_on": d.contact_date, "ends_on": d.ends_on, @@ -87,8 +88,6 @@ def add_calendar_event_for_opportunities(): } ) - event.append( - "event_participants", {"reference_doctype": "Opportunity", "reference_docname": d.name} - ) + event.append("event_participants", {"reference_doctype": "Opportunity", "reference_docname": d.name}) event.insert(ignore_permissions=True) diff --git a/erpnext/patches/v14_0/delete_agriculture_doctypes.py b/erpnext/patches/v14_0/delete_agriculture_doctypes.py index 8ec0c33090d9..c8f9c93d2793 100644 --- a/erpnext/patches/v14_0/delete_agriculture_doctypes.py +++ b/erpnext/patches/v14_0/delete_agriculture_doctypes.py @@ -13,9 +13,7 @@ def execute(): for report in reports: frappe.delete_doc("Report", report, ignore_missing=True, force=True) - dashboards = frappe.get_all( - "Dashboard", {"module": "agriculture", "is_standard": 1}, pluck="name" - ) + dashboards = frappe.get_all("Dashboard", {"module": "agriculture", "is_standard": 1}, pluck="name") for dashboard in dashboards: frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True) diff --git a/erpnext/patches/v14_0/delete_education_doctypes.py b/erpnext/patches/v14_0/delete_education_doctypes.py index 55b64eaabd87..1d636f99a7ba 100644 --- a/erpnext/patches/v14_0/delete_education_doctypes.py +++ b/erpnext/patches/v14_0/delete_education_doctypes.py @@ -16,9 +16,7 @@ def execute(): for report in reports: frappe.delete_doc("Report", report, ignore_missing=True, force=True) - print_formats = frappe.get_all( - "Print Format", {"module": "education", "standard": "Yes"}, pluck="name" - ) + print_formats = frappe.get_all("Print Format", {"module": "education", "standard": "Yes"}, pluck="name") for print_format in print_formats: frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True) @@ -31,9 +29,7 @@ def execute(): for dashboard in dashboards: frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True) - dashboards = frappe.get_all( - "Dashboard Chart", {"module": "education", "is_standard": 1}, pluck="name" - ) + dashboards = frappe.get_all("Dashboard Chart", {"module": "education", "is_standard": 1}, pluck="name") for dashboard in dashboards: frappe.delete_doc("Dashboard Chart", dashboard, ignore_missing=True, force=True) diff --git a/erpnext/patches/v14_0/delete_healthcare_doctypes.py b/erpnext/patches/v14_0/delete_healthcare_doctypes.py index 896a4409507e..b4dde5b58993 100644 --- a/erpnext/patches/v14_0/delete_healthcare_doctypes.py +++ b/erpnext/patches/v14_0/delete_healthcare_doctypes.py @@ -15,9 +15,7 @@ def execute(): for report in reports: frappe.delete_doc("Report", report, ignore_missing=True, force=True) - print_formats = frappe.get_all( - "Print Format", {"module": "healthcare", "standard": "Yes"}, pluck="name" - ) + print_formats = frappe.get_all("Print Format", {"module": "healthcare", "standard": "Yes"}, pluck="name") for print_format in print_formats: frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True) @@ -30,9 +28,7 @@ def execute(): for dashboard in dashboards: frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True) - dashboards = frappe.get_all( - "Dashboard Chart", {"module": "healthcare", "is_standard": 1}, pluck="name" - ) + dashboards = frappe.get_all("Dashboard Chart", {"module": "healthcare", "is_standard": 1}, pluck="name") for dashboard in dashboards: frappe.delete_doc("Dashboard Chart", dashboard, ignore_missing=True, force=True) diff --git a/erpnext/patches/v14_0/delete_hub_doctypes.py b/erpnext/patches/v14_0/delete_hub_doctypes.py index 08f4445fe2ec..451880d5b757 100644 --- a/erpnext/patches/v14_0/delete_hub_doctypes.py +++ b/erpnext/patches/v14_0/delete_hub_doctypes.py @@ -2,7 +2,6 @@ def execute(): - doctypes = frappe.get_all("DocType", {"module": "Hub Node", "custom": 0}, pluck="name") for doctype in doctypes: frappe.delete_doc("DocType", doctype, ignore_missing=True) diff --git a/erpnext/patches/v14_0/delete_non_profit_doctypes.py b/erpnext/patches/v14_0/delete_non_profit_doctypes.py index e9ea8b19e129..74a73fdce90b 100644 --- a/erpnext/patches/v14_0/delete_non_profit_doctypes.py +++ b/erpnext/patches/v14_0/delete_non_profit_doctypes.py @@ -6,9 +6,7 @@ def execute(): frappe.delete_doc("Workspace", "Non Profit", ignore_missing=True, force=True) - print_formats = frappe.get_all( - "Print Format", {"module": "Non Profit", "standard": "Yes"}, pluck="name" - ) + print_formats = frappe.get_all("Print Format", {"module": "Non Profit", "standard": "Yes"}, pluck="name") for print_format in print_formats: frappe.delete_doc("Print Format", print_format, ignore_missing=True, force=True) diff --git a/erpnext/patches/v14_0/fix_crm_no_of_employees.py b/erpnext/patches/v14_0/fix_crm_no_of_employees.py index 268eb95732ea..29c8b05c79fc 100644 --- a/erpnext/patches/v14_0/fix_crm_no_of_employees.py +++ b/erpnext/patches/v14_0/fix_crm_no_of_employees.py @@ -15,12 +15,10 @@ def execute(): frappe.reload_doctype(doctype) for key, value in options.items(): frappe.db.sql( - """ + f""" update `tab{doctype}` set no_of_employees = %s where no_of_employees = %s - """.format( - doctype=doctype - ), + """, (value, key), ) diff --git a/erpnext/patches/v14_0/migrate_cost_center_allocations.py b/erpnext/patches/v14_0/migrate_cost_center_allocations.py index 48f4e6d98938..03e2b0289dc5 100644 --- a/erpnext/patches/v14_0/migrate_cost_center_allocations.py +++ b/erpnext/patches/v14_0/migrate_cost_center_allocations.py @@ -44,8 +44,6 @@ def get_existing_cost_center_allocations(): cc_allocations = frappe._dict() for d in records: - cc_allocations.setdefault(d.name, frappe._dict()).setdefault( - d.cost_center, d.percentage_allocation - ) + cc_allocations.setdefault(d.name, frappe._dict()).setdefault(d.cost_center, d.percentage_allocation) return cc_allocations diff --git a/erpnext/patches/v14_0/migrate_gl_to_payment_ledger.py b/erpnext/patches/v14_0/migrate_gl_to_payment_ledger.py index 72c8c074d2c9..56694065bcf9 100644 --- a/erpnext/patches/v14_0/migrate_gl_to_payment_ledger.py +++ b/erpnext/patches/v14_0/migrate_gl_to_payment_ledger.py @@ -152,7 +152,8 @@ def execute(): gl.star, ConstantColumn(1).as_("docstatus"), IfNull( - ifelse(gl.against_voucher_type == "", None, gl.against_voucher_type), gl.voucher_type + ifelse(gl.against_voucher_type == "", None, gl.against_voucher_type), + gl.voucher_type, ).as_("against_voucher_type"), IfNull(ifelse(gl.against_voucher == "", None, gl.against_voucher), gl.voucher_no).as_( "against_voucher_no" diff --git a/erpnext/patches/v14_0/remove_hr_and_payroll_modules.py b/erpnext/patches/v14_0/remove_hr_and_payroll_modules.py index 4d01fcb42166..3d01f1422e41 100644 --- a/erpnext/patches/v14_0/remove_hr_and_payroll_modules.py +++ b/erpnext/patches/v14_0/remove_hr_and_payroll_modules.py @@ -33,9 +33,7 @@ def execute(): ]: frappe.delete_doc("Report", report, ignore_missing=True, force=True) - doctypes = frappe.get_all( - "DocType", {"module": ("in", ["HR", "Payroll"]), "custom": 0}, pluck="name" - ) + doctypes = frappe.get_all("DocType", {"module": ("in", ["HR", "Payroll"]), "custom": 0}, pluck="name") for doctype in doctypes: frappe.delete_doc("DocType", doctype, ignore_missing=True, force=True) @@ -51,9 +49,7 @@ def execute(): frappe.delete_doc("User Type", "Employee Self Service", ignore_missing=True, force=True) for dt in ["Web Form", "Dashboard", "Dashboard Chart", "Number Card"]: - records = frappe.get_all( - dt, {"module": ("in", ["HR", "Payroll"]), "is_standard": 1}, pluck="name" - ) + records = frappe.get_all(dt, {"module": ("in", ["HR", "Payroll"]), "is_standard": 1}, pluck="name") for record in records: frappe.delete_doc(dt, record, ignore_missing=True, force=True) diff --git a/erpnext/patches/v14_0/update_asset_value_for_manual_depr_entries.py b/erpnext/patches/v14_0/update_asset_value_for_manual_depr_entries.py index 5d7b5cf19c18..9bdcda09d3c9 100644 --- a/erpnext/patches/v14_0/update_asset_value_for_manual_depr_entries.py +++ b/erpnext/patches/v14_0/update_asset_value_for_manual_depr_entries.py @@ -17,9 +17,7 @@ def execute(): .join(company) .on(company.name == asset.company) .select(Sum(gle.debit).as_("value"), asset.name.as_("asset_name")) - .where( - gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account) - ) + .where(gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account)) .where(gle.debit != 0) .where(gle.is_cancelled == 0) .where(asset.docstatus == 1) @@ -31,8 +29,4 @@ def execute(): asset_total_depr_value_map.asset_name == asset.name ).set( asset.value_after_depreciation, asset.value_after_depreciation - asset_total_depr_value_map.value - ).where( - asset.docstatus == 1 - ).where( - asset.calculate_depreciation == 0 - ).run() + ).where(asset.docstatus == 1).where(asset.calculate_depreciation == 0).run() diff --git a/erpnext/patches/v14_0/update_closing_balances.py b/erpnext/patches/v14_0/update_closing_balances.py index 2c842814839c..cfc29c87fa11 100644 --- a/erpnext/patches/v14_0/update_closing_balances.py +++ b/erpnext/patches/v14_0/update_closing_balances.py @@ -22,7 +22,6 @@ def execute(): filters={"docstatus": 1, "company": company}, order_by="posting_date", ): - company_wise_order.setdefault(pcv.company, []) if pcv.posting_date not in company_wise_order[pcv.company]: pcv_doc = frappe.get_doc("Period Closing Voucher", pcv.name) diff --git a/erpnext/patches/v14_0/update_flag_for_return_invoices.py b/erpnext/patches/v14_0/update_flag_for_return_invoices.py index bea99575425b..ca1b2967c535 100644 --- a/erpnext/patches/v14_0/update_flag_for_return_invoices.py +++ b/erpnext/patches/v14_0/update_flag_for_return_invoices.py @@ -22,7 +22,7 @@ def execute(): .where( (si.creation.gte(creation_date)) & (si.docstatus == 1) - & (si.is_return == True) + & (si.is_return is True) & (si.return_against.notnull()) ) .run() @@ -51,7 +51,7 @@ def execute(): .where( (pi.creation.gte(creation_date)) & (pi.docstatus == 1) - & (pi.is_return == True) + & (pi.is_return is True) & (pi.return_against.notnull()) ) .run() diff --git a/erpnext/patches/v14_0/update_partial_tds_fields.py b/erpnext/patches/v14_0/update_partial_tds_fields.py index 5ccc2dc3aa27..991201395f3f 100644 --- a/erpnext/patches/v14_0/update_partial_tds_fields.py +++ b/erpnext/patches/v14_0/update_partial_tds_fields.py @@ -14,32 +14,20 @@ def execute(): frappe.qb.update(purchase_invoice).set( purchase_invoice.tax_withholding_net_total, purchase_invoice.net_total - ).set( - purchase_invoice.base_tax_withholding_net_total, purchase_invoice.base_net_total - ).where( + ).set(purchase_invoice.base_tax_withholding_net_total, purchase_invoice.base_net_total).where( purchase_invoice.company == company.name - ).where( - purchase_invoice.apply_tds == 1 - ).where( + ).where(purchase_invoice.apply_tds == 1).where( purchase_invoice.posting_date >= fiscal_year_details.year_start_date - ).where( - purchase_invoice.docstatus == 1 - ).run() + ).where(purchase_invoice.docstatus == 1).run() purchase_order = frappe.qb.DocType("Purchase Order") frappe.qb.update(purchase_order).set( purchase_order.tax_withholding_net_total, purchase_order.net_total - ).set( - purchase_order.base_tax_withholding_net_total, purchase_order.base_net_total - ).where( + ).set(purchase_order.base_tax_withholding_net_total, purchase_order.base_net_total).where( purchase_order.company == company.name - ).where( - purchase_order.apply_tds == 1 - ).where( + ).where(purchase_order.apply_tds == 1).where( purchase_order.transaction_date >= fiscal_year_details.year_start_date - ).where( - purchase_order.docstatus == 1 - ).run() + ).where(purchase_order.docstatus == 1).run() except FiscalYearError: pass diff --git a/erpnext/portal/doctype/homepage/homepage.py b/erpnext/portal/doctype/homepage/homepage.py index 0d2e36078818..be90776cca3c 100644 --- a/erpnext/portal/doctype/homepage/homepage.py +++ b/erpnext/portal/doctype/homepage/homepage.py @@ -20,7 +20,6 @@ def setup_items(self): filters={"published": 1}, limit=3, ): - doc = frappe.get_doc("Website Item", d.name) if not doc.route: # set missing route diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 8704147cd22f..29a288ef6711 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -17,7 +17,7 @@ class Project(Document): def get_feed(self): - return "{0}: {1}".format(_(self.status), frappe.safe_decode(self.project_name)) + return f"{_(self.status)}: {frappe.safe_decode(self.project_name)}" def onload(self): self.set_onload( @@ -49,7 +49,6 @@ def copy_from_template(self): Copy tasks from template """ if self.project_template and not frappe.db.get_all("Task", dict(project=self.name), limit=1): - # has a template, and no loaded tasks, so lets create if not self.expected_start_date: # project starts today @@ -120,7 +119,9 @@ def check_depends_on_value(self, template_task, project_task, project_tasks): for child_task in template_task.get("depends_on"): if project_template_map and project_template_map.get(child_task.task): project_task.reload() # reload, as it might have been updated in the previous iteration - project_task.append("depends_on", {"task": project_template_map.get(child_task.task).name}) + project_task.append( + "depends_on", {"task": project_template_map.get(child_task.task).name} + ) project_task.save() def check_for_parent_tasks(self, template_task, project_task, project_tasks): @@ -274,7 +275,7 @@ def after_rename(self, old_name, new_name, merge=False): frappe.db.set_value("Project", new_name, "copied_from", new_name) def send_welcome_email(self): - url = get_url("/project/?name={0}".format(self.name)) + url = get_url(f"/project/?name={self.name}") messages = ( _("You have been invited to collaborate on the project: {0}").format(self.name), url, @@ -289,7 +290,9 @@ def send_welcome_email(self): for user in self.users: if user.welcome_email_sent == 0: frappe.sendmail( - user.user, subject=_("Project Collaboration Invitation"), content=content.format(*messages) + user.user, + subject=_("Project Collaboration Invitation"), + content=content.format(*messages), ) user.welcome_email_sent = 1 @@ -308,9 +311,7 @@ def get_timeline_data(doctype, name): ) -def get_project_list( - doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified" -): +def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified"): meta = frappe.get_meta(doctype) if not filters: filters = [] @@ -594,9 +595,7 @@ def update_project_sales_billing(): return # Else simply fallback to Daily - exists_query = ( - "(SELECT 1 from `tab{doctype}` where docstatus = 1 and project = `tabProject`.name)" - ) + exists_query = "(SELECT 1 from `tab{doctype}` where docstatus = 1 and project = `tabProject`.name)" project_map = {} for project_details in frappe.db.sql( """ @@ -639,7 +638,7 @@ def set_project_status(project, status): """ set status for project and all related tasks """ - if not status in ("Completed", "Cancelled"): + if status not in ("Completed", "Cancelled"): frappe.throw(_("Status must be Cancelled or Completed")) project = frappe.get_doc("Project", project) @@ -659,9 +658,7 @@ def get_holiday_list(company=None): holiday_list = frappe.get_cached_value("Company", company, "default_holiday_list") if not holiday_list: frappe.throw( - _("Please set a default Holiday List for Company {0}").format( - frappe.bold(get_default_company()) - ) + _("Please set a default Holiday List for Company {0}").format(frappe.bold(get_default_company())) ) return holiday_list diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py index b8340ffe1936..1b7460f7a2a0 100644 --- a/erpnext/projects/doctype/project/test_project.py +++ b/erpnext/projects/doctype/project/test_project.py @@ -30,9 +30,7 @@ def test_project_with_template_having_no_parent_and_depend_tasks(self): priority="High", ) - template = make_project_template( - "Test Project Template - No Parent and Dependend Tasks", [task1] - ) + template = make_project_template("Test Project Template - No Parent and Dependend Tasks", [task1]) project = get_project(project_name, template) tasks = frappe.get_all( "Task", @@ -185,9 +183,7 @@ def test_project_with_template_tasks_having_common_name(self): template_parent_task3, template_task3, ] - project_template = make_project_template( - "Project template with common Task Subject", template_tasks - ) + project_template = make_project_template("Project template with common Task Subject", template_tasks) # Step - 4: Create Project against the Project Template project = get_project("Project with common Task Subject", project_template) @@ -196,7 +192,7 @@ def test_project_with_template_tasks_having_common_name(self): ) # Test - 1: No. of Project Tasks should be equal to No. of Template Tasks - self.assertEquals(len(project_tasks), len(template_tasks)) + self.assertEqual(len(project_tasks), len(template_tasks)) # Test - 2: All child Project Tasks should have Parent Task linked for pt in project_tasks: @@ -205,7 +201,6 @@ def test_project_with_template_tasks_having_common_name(self): def get_project(name, template): - project = frappe.get_doc( dict( doctype="Project", diff --git a/erpnext/projects/doctype/project_template/test_project_template.py b/erpnext/projects/doctype/project_template/test_project_template.py index 4fd24bf78a28..382ffd5aa4cf 100644 --- a/erpnext/projects/doctype/project_template/test_project_template.py +++ b/erpnext/projects/doctype/project_template/test_project_template.py @@ -12,7 +12,9 @@ class TestProjectTemplate(unittest.TestCase): pass -def make_project_template(project_template_name, project_tasks=[]): +def make_project_template(project_template_name, project_tasks=None): + if project_tasks is None: + project_tasks = [] if not frappe.db.exists("Project Template", project_template_name): project_tasks = project_tasks or [ create_task(subject="_Test Template Task 1", is_template=1, begin=0, duration=3), diff --git a/erpnext/projects/doctype/project_update/project_update.py b/erpnext/projects/doctype/project_update/project_update.py index 175f787a303d..7390621860d7 100644 --- a/erpnext/projects/doctype/project_update/project_update.py +++ b/erpnext/projects/doctype/project_update/project_update.py @@ -34,13 +34,8 @@ def daily_reminder(): email_sending(project_name, frequency, date_start, date_end, progress, number_of_drafts, update) -def email_sending( - project_name, frequency, date_start, date_end, progress, number_of_drafts, update -): - - holiday = frappe.db.sql( - """SELECT holiday_date FROM `tabHoliday` where holiday_date = CURRENT_DATE;""" - ) +def email_sending(project_name, frequency, date_start, date_end, progress, number_of_drafts, update): + holiday = frappe.db.sql("""SELECT holiday_date FROM `tabHoliday` where holiday_date = CURRENT_DATE;""") msg = ( "

    Project Name: " + project_name @@ -87,8 +82,6 @@ def email_sending( if len(holiday) == 0: email = frappe.db.sql("""SELECT user from `tabProject User` WHERE parent = %s;""", project_name) for emails in email: - frappe.sendmail( - recipients=emails, subject=frappe._(project_name + " " + "Summary"), message=msg - ) + frappe.sendmail(recipients=emails, subject=frappe._(project_name + " " + "Summary"), message=msg) else: pass diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 1a7834257caf..b051494a6515 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -24,7 +24,7 @@ class Task(NestedSet): nsm_parent_field = "parent_task" def get_feed(self): - return "{0}: {1}".format(_(self.status), self.subject) + return f"{_(self.status)}: {self.subject}" def get_customer_details(self): cust = frappe.db.sql("select customer_name from `tabCustomer` where name=%s", self.customer) @@ -118,14 +118,14 @@ def validate_dependencies_for_template_task(self): def validate_parent_template_task(self): if self.parent_task: if not frappe.db.get_value("Task", self.parent_task, "is_template"): - parent_task_format = """{0}""".format(self.parent_task) + parent_task_format = f"""{self.parent_task}""" frappe.throw(_("Parent Task {0} is not a Template Task").format(parent_task_format)) def validate_depends_on_tasks(self): if self.depends_on: for task in self.depends_on: if not frappe.db.get_value("Task", task.task, "is_template"): - dependent_task_format = """{0}""".format(task.task) + dependent_task_format = f"""{task.task}""" frappe.throw(_("Dependent Task {0} is not a Template Task").format(dependent_task_format)) def validate_completed_on(self): @@ -184,7 +184,7 @@ def check_recursion(self): task_list, count = [self.name], 0 while len(task_list) > count: tasks = frappe.db.sql( - " select %s from `tabTask Depends On` where %s = %s " % (d[0], d[1], "%s"), + " select {} from `tabTask Depends On` where {} = {} ".format(d[0], d[1], "%s"), cstr(task_list[count]), ) count = count + 1 @@ -276,14 +276,12 @@ def get_project(doctype, txt, searchfield, start, page_len, filters): search_cond = " or " + " or ".join(field + " like %(txt)s" for field in searchfields) return frappe.db.sql( - """ select name {search_columns} from `tabProject` + f""" select name {search_columns} from `tabProject` where %(key)s like %(txt)s %(mcond)s - {search_condition} + {search_cond} order by name - limit %(page_len)s offset %(start)s""".format( - search_columns=search_columns, search_condition=search_cond - ), + limit %(page_len)s offset %(start)s""", { "key": searchfield, "txt": "%" + txt + "%", @@ -343,7 +341,6 @@ def set_missing_values(source, target): @frappe.whitelist() def get_children(doctype, parent, task=None, project=None, is_root=False): - filters = [["docstatus", "<", "2"]] if task: diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index ea7d6edcdf91..b0194b08dfae 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -131,9 +131,7 @@ def create_task( task.exp_start_date = start or nowdate() task.exp_end_date = end or nowdate() task.project = ( - project or None - if is_template - else frappe.get_value("Project", {"project_name": "_Test Project"}) + project or None if is_template else frappe.get_value("Project", {"project_name": "_Test Project"}) ) task.is_template = is_template task.start = begin diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 828a55e7bc13..da042f36aef1 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -5,7 +5,7 @@ import unittest import frappe -from frappe.utils import add_months, add_to_date, now_datetime, nowdate +from frappe.utils import add_to_date, now_datetime, nowdate from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.projects.doctype.timesheet.timesheet import OverlapError, make_sales_invoice @@ -40,9 +40,7 @@ def test_sales_invoice_from_timesheet(self): emp = make_employee("test_employee_6@salary.com") timesheet = make_timesheet(emp, simulate=True, is_billable=1) - sales_invoice = make_sales_invoice( - timesheet.name, "_Test Item", "_Test Customer", currency="INR" - ) + sales_invoice = make_sales_invoice(timesheet.name, "_Test Item", "_Test Customer", currency="INR") sales_invoice.due_date = nowdate() sales_invoice.submit() timesheet = frappe.get_doc("Timesheet", timesheet.name) @@ -211,9 +209,7 @@ def make_timesheet( timesheet_detail.activity_type = activity_type timesheet_detail.from_time = now_datetime() timesheet_detail.hours = 2 - timesheet_detail.to_time = timesheet_detail.from_time + datetime.timedelta( - hours=timesheet_detail.hours - ) + timesheet_detail.to_time = timesheet_detail.from_time + datetime.timedelta(hours=timesheet_detail.hours) timesheet_detail.project = project timesheet_detail.task = task diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 4db647eb3e29..e67841e0358f 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -293,12 +293,10 @@ def get_projectwise_timesheet_data(project=None, parent=None, from_time=None, to @frappe.whitelist() def get_timesheet_detail_rate(timelog, currency): timelog_detail = frappe.db.sql( - """SELECT tsd.billing_amount as billing_amount, + f"""SELECT tsd.billing_amount as billing_amount, ts.currency as currency FROM `tabTimesheet Detail` tsd INNER JOIN `tabTimesheet` ts ON ts.name=tsd.parent - WHERE tsd.name = '{0}'""".format( - timelog - ), + WHERE tsd.name = '{timelog}'""", as_dict=1, )[0] @@ -320,14 +318,12 @@ def get_timesheet(doctype, txt, searchfield, start, page_len, filters): condition = "and tsd.project = %(project)s" return frappe.db.sql( - """select distinct tsd.parent from `tabTimesheet Detail` tsd, + f"""select distinct tsd.parent from `tabTimesheet Detail` tsd, `tabTimesheet` ts where ts.status in ('Submitted', 'Payslip') and tsd.parent = ts.name and tsd.docstatus = 1 and ts.total_billable_amount > 0 and tsd.parent LIKE %(txt)s {condition} - order by tsd.parent limit %(page_len)s offset %(start)s""".format( - condition=condition - ), + order by tsd.parent limit %(page_len)s offset %(start)s""", { "txt": "%" + txt + "%", "start": start, @@ -452,18 +448,14 @@ def get_events(start, end, filters=None): where `tabTimesheet Detail`.parent = `tabTimesheet`.name and `tabTimesheet`.docstatus < 2 and (from_time <= %(end)s and to_time >= %(start)s) {conditions} {match_cond} - """.format( - conditions=conditions, match_cond=get_match_cond("Timesheet") - ), + """.format(conditions=conditions, match_cond=get_match_cond("Timesheet")), {"start": start, "end": end}, as_dict=True, update={"allDay": 0}, ) -def get_timesheets_list( - doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified" -): +def get_timesheets_list(doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified"): user = frappe.session.user # find customer name from contact. customer = "" @@ -482,7 +474,7 @@ def get_timesheets_list( projects = [d.name for d in frappe.get_all("Project", filters={"customer": customer})] # Return timesheet related data to web portal. timesheets = frappe.db.sql( - """ + f""" SELECT ts.name, tsd.activity_type, ts.status, ts.total_billable_hours, COALESCE(ts.sales_invoice, tsd.sales_invoice) AS sales_invoice, tsd.project @@ -494,10 +486,8 @@ def get_timesheets_list( tsd.project IN %(projects)s ) ORDER BY `end_date` ASC - LIMIT {1} offset {0} - """.format( - limit_start, limit_page_length - ), + LIMIT {limit_page_length} offset {limit_start} + """, dict(sales_invoices=sales_invoices, projects=projects), as_dict=True, ) # nosec diff --git a/erpnext/projects/report/billing_summary.py b/erpnext/projects/report/billing_summary.py index ac1524a49ddc..ab8d38389215 100644 --- a/erpnext/projects/report/billing_summary.py +++ b/erpnext/projects/report/billing_summary.py @@ -50,9 +50,7 @@ def get_data(filters): timesheets = get_timesheets(filters) filters.from_date = frappe.utils.get_datetime(filters.from_date) - filters.to_date = frappe.utils.add_to_date( - frappe.utils.get_datetime(filters.to_date), days=1, seconds=-1 - ) + filters.to_date = frappe.utils.add_to_date(frappe.utils.get_datetime(filters.to_date), days=1, seconds=-1) timesheet_details = get_timesheet_details(filters, timesheets.keys()) diff --git a/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py b/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py index 91a0607b17ce..c288125ac11c 100644 --- a/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py +++ b/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py @@ -31,14 +31,14 @@ def test_delayed_tasks_summary(self): {"subject": "_Test Task 98", "status": "Completed", "priority": "Low", "delay": -1}, ] report = execute(filters) - data = list(filter(lambda x: x.subject == "_Test Task 99", report[1]))[0] + data = next(filter(lambda x: x.subject == "_Test Task 99", report[1])) for key in ["subject", "status", "priority", "delay"]: self.assertEqual(expected_data[0].get(key), data.get(key)) filters.status = "Completed" report = execute(filters) - data = list(filter(lambda x: x.subject == "_Test Task 98", report[1]))[0] + data = next(filter(lambda x: x.subject == "_Test Task 98", report[1])) for key in ["subject", "status", "priority", "delay"]: self.assertEqual(expected_data[1].get(key), data.get(key)) diff --git a/erpnext/projects/utils.py b/erpnext/projects/utils.py index 3cc4da4f07d8..5046d015cb6d 100644 --- a/erpnext/projects/utils.py +++ b/erpnext/projects/utils.py @@ -19,13 +19,14 @@ def query_task(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql( """select name, subject from `tabTask` - where (`%s` like %s or `subject` like %s) %s + where (`{}` like {} or `subject` like {}) {} order by - case when `subject` like %s then 0 else 1 end, - case when `%s` like %s then 0 else 1 end, - `%s`, + case when `subject` like {} then 0 else 1 end, + case when `{}` like {} then 0 else 1 end, + `{}`, subject - limit %s offset %s""" - % (searchfield, "%s", "%s", match_conditions, "%s", searchfield, "%s", searchfield, "%s", "%s"), + limit {} offset {}""".format( + searchfield, "%s", "%s", match_conditions, "%s", searchfield, "%s", searchfield, "%s", "%s" + ), (search_string, search_string, order_by_string, order_by_string, page_len, start), ) diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py index 6834abc9d41f..5497e8db7ae7 100644 --- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py +++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py @@ -54,7 +54,9 @@ def set_parent(self): for process in self.processes: if process.procedure: - if not frappe.db.get_value("Quality Procedure", process.procedure, "parent_quality_procedure"): + if not frappe.db.get_value( + "Quality Procedure", process.procedure, "parent_quality_procedure" + ): frappe.db.set_value( "Quality Procedure", process.procedure, "parent_quality_procedure", self.name ) @@ -66,9 +68,13 @@ def remove_parent_from_old_child(self): if old_child_procedures := set([d.procedure for d in old_doc.processes if d.procedure]): current_child_procedures = set([d.procedure for d in self.processes if d.procedure]) - if removed_child_procedures := list(old_child_procedures.difference(current_child_procedures)): + if removed_child_procedures := list( + old_child_procedures.difference(current_child_procedures) + ): for child_procedure in removed_child_procedures: - frappe.db.set_value("Quality Procedure", child_procedure, "parent_quality_procedure", None) + frappe.db.set_value( + "Quality Procedure", child_procedure, "parent_quality_procedure", None + ) def add_child_to_parent(self): """Add `Child Procedure` to `Parent Procedure`""" @@ -102,7 +108,8 @@ def get_children(doctype, parent=None, parent_quality_procedure=None, is_root=Fa # return the list in order return [ dict( - value=d.procedure, expandable=frappe.db.get_value("Quality Procedure", d.procedure, "is_group") + value=d.procedure, + expandable=frappe.db.get_value("Quality Procedure", d.procedure, "is_group"), ) for d in parent_procedure.processes if d.procedure diff --git a/erpnext/quality_management/doctype/quality_review/quality_review.py b/erpnext/quality_management/doctype/quality_review/quality_review.py index f691005566d6..19aa62735001 100644 --- a/erpnext/quality_management/doctype/quality_review/quality_review.py +++ b/erpnext/quality_management/doctype/quality_review/quality_review.py @@ -47,9 +47,7 @@ def review(): def create_review(goal): goal = frappe.get_doc("Quality Goal", goal) - review = frappe.get_doc( - {"doctype": "Quality Review", "goal": goal.name, "date": frappe.utils.getdate()} - ) + review = frappe.get_doc({"doctype": "Quality Review", "goal": goal.name, "date": frappe.utils.getdate()}) review.insert(ignore_permissions=True) diff --git a/erpnext/regional/address_template/setup.py b/erpnext/regional/address_template/setup.py index fd1dfa726b67..684c76620a49 100644 --- a/erpnext/regional/address_template/setup.py +++ b/erpnext/regional/address_template/setup.py @@ -1,5 +1,6 @@ """Import Address Templates from ./templates directory.""" import os + import frappe @@ -26,7 +27,7 @@ def country(file_name): def get_file_content(file_name): """Convert 'united_states.html' to '/path/to/united_states.html'.""" full_path = os.path.join(template_dir, file_name) - with open(full_path, "r") as f: + with open(full_path) as f: content = f.read() return content @@ -41,7 +42,7 @@ def get_file_content(file_name): def update_address_template(country, html, is_default=0): """Update existing Address Template or create a new one.""" if not frappe.db.exists("Country", country): - frappe.log_error("Country {} for regional Address Template does not exist.".format(country)) + frappe.log_error(f"Country {country} for regional Address Template does not exist.") return if frappe.db.exists("Address Template", country): diff --git a/erpnext/regional/address_template/test_regional_address_template.py b/erpnext/regional/address_template/test_regional_address_template.py index 523653b58462..952748b33387 100644 --- a/erpnext/regional/address_template/test_regional_address_template.py +++ b/erpnext/regional/address_template/test_regional_address_template.py @@ -32,7 +32,7 @@ def test_update_address_template(self): """Update an existing Address Template.""" country = ensure_country("Germany") if not frappe.db.exists("Address Template", country.name): - template = frappe.get_doc( + frappe.get_doc( {"doctype": "Address Template", "country": country.name, "template": "EXISTING"} ).insert() 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 c52685e330ad..204e6f483dab 100644 --- a/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py +++ b/erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py @@ -77,13 +77,13 @@ def prepare_data_for_import(self, file_content, file_name, encoded_content): invoices_args["terms"] = get_payment_terms_from_file(file_content) supplier_name = create_supplier(self.supplier_group, supp_dict) - address = create_address(supplier_name, supp_dict) + create_address(supplier_name, supp_dict) pi_name = create_purchase_invoice(supplier_name, file_name, invoices_args, self.name) self.file_count += 1 if pi_name: self.purchase_invoices_count += 1 - file_save = save_file( + save_file( file_name, encoded_content, "Purchase Invoice", @@ -161,7 +161,7 @@ def get_file_content(file_name, zip_file_object): except UnicodeDecodeError: try: content = encoded_content.decode("utf-16") - except UnicodeDecodeError as e: + except UnicodeDecodeError: frappe.log_error("UTF-16 encoding error for File Name: " + file_name) return content @@ -279,7 +279,6 @@ def create_supplier(supplier_group, args): return existing_supplier_name else: - new_supplier = frappe.new_doc("Supplier") new_supplier.supplier_name = re.sub("&", "&", args.supplier) new_supplier.supplier_group = supplier_group @@ -390,7 +389,7 @@ def create_purchase_invoice(supplier_name, file_name, args, name): pi.imported_grand_total = calc_total pi.save() return pi.name - except Exception as e: + except Exception: frappe.db.set_value("Import Supplier Invoice", name, "status", "Error") pi.log_error("Unable to create Puchase Invoice") return None diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py index 1f66b3612215..23406ea85a66 100644 --- a/erpnext/regional/italy/setup.py +++ b/erpnext/regional/italy/setup.py @@ -7,10 +7,11 @@ from frappe import _ from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.permissions import add_permission, update_permission_property + from erpnext.regional.italy import ( fiscal_regimes, - tax_exemption_reasons, mode_of_payment_codes, + tax_exemption_reasons, vat_collectability_options, ) diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index f5b2e2d96b88..1e0a88050757 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -39,7 +39,7 @@ def export_invoices(filters=None): attachments = get_e_invoice_attachments(invoices) - zip_filename = "{0}-einvoices.zip".format(frappe.utils.get_datetime().strftime("%Y%m%d_%H%M%S")) + zip_filename = "{}-einvoices.zip".format(frappe.utils.get_datetime().strftime("%Y%m%d_%H%M%S")) download_zip(attachments, zip_filename) @@ -307,7 +307,9 @@ def sales_invoice_validate(doc): for row in doc.taxes: if row.rate == 0 and row.tax_amount == 0 and not row.tax_exemption_reason: frappe.throw( - _("Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges").format(row.idx), + _("Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges").format( + row.idx + ), title=_("E-Invoicing Information Missing"), ) @@ -338,9 +340,7 @@ def sales_invoice_on_submit(doc, method): _("Row {0}: Please set the Mode of Payment in Payment Schedule").format(schedule.idx), title=_("E-Invoicing Information Missing"), ) - elif not frappe.db.get_value( - "Mode of Payment", schedule.mode_of_payment, "mode_of_payment_code" - ): + elif not frappe.db.get_value("Mode of Payment", schedule.mode_of_payment, "mode_of_payment_code"): frappe.throw( _("Row {0}: Please set the correct code on Mode of Payment {1}").format( schedule.idx, schedule.mode_of_payment @@ -473,9 +473,7 @@ def get_progressive_name_and_number(doc, replace=False): filename = attachment.file_name.split(".xml")[0] return filename, filename.split("_")[1] - company_tax_id = ( - doc.company_tax_id if doc.company_tax_id.startswith("IT") else "IT" + doc.company_tax_id - ) + company_tax_id = doc.company_tax_id if doc.company_tax_id.startswith("IT") else "IT" + doc.company_tax_id progressive_name = frappe.model.naming.make_autoname(company_tax_id + "_.#####") progressive_number = progressive_name.split("_")[1] diff --git a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py index 671798900882..1b2bc771f7b0 100644 --- a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py +++ b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py @@ -149,12 +149,8 @@ def get_gl_entries(company, fiscal_year): debit = frappe.query_builder.functions.Sum(gle.debit).as_("debit") credit = frappe.query_builder.functions.Sum(gle.credit).as_("credit") - debit_currency = frappe.query_builder.functions.Sum(gle.debit_in_account_currency).as_( - "debitCurr" - ) - credit_currency = frappe.query_builder.functions.Sum(gle.credit_in_account_currency).as_( - "creditCurr" - ) + debit_currency = frappe.query_builder.functions.Sum(gle.debit_in_account_currency).as_("debitCurr") + credit_currency = frappe.query_builder.functions.Sum(gle.credit_in_account_currency).as_("creditCurr") query = ( frappe.qb.from_(gle) @@ -222,25 +218,21 @@ def get_result(company, fiscal_year): result = [] company_currency = frappe.get_cached_value("Company", company, "default_currency") - accounts = frappe.get_all( - "Account", filters={"Company": company}, fields=["name", "account_number"] - ) + accounts = frappe.get_all("Account", filters={"Company": company}, fields=["name", "account_number"]) for d in data: JournalCode = re.split("-|/|[0-9]", d.get("voucher_no"))[0] - if d.get("voucher_no").startswith("{0}-".format(JournalCode)) or d.get("voucher_no").startswith( - "{0}/".format(JournalCode) + if d.get("voucher_no").startswith(f"{JournalCode}-") or d.get("voucher_no").startswith( + f"{JournalCode}/" ): EcritureNum = re.split("-|/", d.get("voucher_no"))[1] else: - EcritureNum = re.search(r"{0}(\d+)".format(JournalCode), d.get("voucher_no"), re.IGNORECASE)[1] + EcritureNum = re.search(rf"{JournalCode}(\d+)", d.get("voucher_no"), re.IGNORECASE)[1] EcritureDate = format_datetime(d.get("GlPostDate"), "yyyyMMdd") - account_number = [ - account.account_number for account in accounts if account.name == d.get("account") - ] + account_number = [account.account_number for account in accounts if account.name == d.get("account")] if account_number[0] is not None: CompteNum = account_number[0] else: diff --git a/erpnext/regional/report/irs_1099/irs_1099.py b/erpnext/regional/report/irs_1099/irs_1099.py index 66ade1f89fb8..304a07c7e784 100644 --- a/erpnext/regional/report/irs_1099/irs_1099.py +++ b/erpnext/regional/report/irs_1099/irs_1099.py @@ -34,7 +34,7 @@ def execute(filters=None): conditions += "AND s.supplier_group = %s" % frappe.db.escape(filters.get("supplier_group")) data = frappe.db.sql( - """ + f""" SELECT s.supplier_group as "supplier_group", gl.party AS "supplier", @@ -55,9 +55,7 @@ def execute(filters=None): gl.party ORDER BY - gl.party DESC""".format( - conditions=conditions - ), + gl.party DESC""", {"fiscal_year": filters.fiscal_year, "company": filters.company}, as_dict=True, ) @@ -117,7 +115,7 @@ def irs_1099_print(filters): "Supplier", row.supplier ) row["payments"] = fmt_money(row["payments"], precision=0, currency="USD") - pdf = get_pdf(render_template(template, row), output=output if output else None) + get_pdf(render_template(template, row), output=output if output else None) frappe.local.response.filename = ( f"{filters.fiscal_year} {filters.company} IRS 1099 Forms{IRS_1099_FORMS_FILE_EXTENSION}" 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 6ef21e52ca1e..1b77b3c0dd10 100644 --- a/erpnext/regional/report/uae_vat_201/uae_vat_201.py +++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py @@ -62,13 +62,9 @@ def append_vat_on_sales(data, filters): frappe.format(get_reverse_charge_tax(filters), "Currency"), ) - append_data( - data, "4", _("Zero Rated"), frappe.format(get_zero_rated_total(filters), "Currency"), "-" - ) + append_data(data, "4", _("Zero Rated"), frappe.format(get_zero_rated_total(filters), "Currency"), "-") - append_data( - data, "5", _("Exempt Supplies"), frappe.format(get_exempt_total(filters), "Currency"), "-" - ) + append_data(data, "5", _("Exempt Supplies"), frappe.format(get_exempt_total(filters), "Currency"), "-") append_data(data, "", "", "", "") @@ -139,7 +135,7 @@ def get_total_emiratewise(filters): conditions = get_conditions(filters) try: return frappe.db.sql( - """ + f""" select s.vat_emirate as emirate, sum(i.base_net_amount) as total, sum(i.tax_amount) from @@ -148,12 +144,10 @@ def get_total_emiratewise(filters): i.parent = s.name where s.docstatus = 1 and i.is_exempt != 1 and i.is_zero_rated != 1 - {where_conditions} + {conditions} group by s.vat_emirate; - """.format( - where_conditions=conditions - ), + """, filters, ) except (IndexError, TypeError): @@ -198,7 +192,7 @@ def get_reverse_charge_tax(filters): conditions = get_conditions_join(filters) return ( frappe.db.sql( - """ + f""" select sum(debit) from `tabPurchase Invoice` p inner join `tabGL Entry` gl on @@ -208,10 +202,8 @@ def get_reverse_charge_tax(filters): and p.docstatus = 1 and gl.docstatus = 1 and account in (select account from `tabUAE VAT Account` where parent=%(company)s) - {where_conditions} ; - """.format( - where_conditions=conditions - ), + {conditions} ; + """, filters, )[0][0] or 0 @@ -240,7 +232,7 @@ def get_reverse_charge_recoverable_tax(filters): conditions = get_conditions_join(filters) return ( frappe.db.sql( - """ + f""" select sum(debit * p.recoverable_reverse_charge / 100) from @@ -253,10 +245,8 @@ def get_reverse_charge_recoverable_tax(filters): and p.recoverable_reverse_charge > 0 and gl.docstatus = 1 and account in (select account from `tabUAE VAT Account` where parent=%(company)s) - {where_conditions} ; - """.format( - where_conditions=conditions - ), + {conditions} ; + """, filters, )[0][0] or 0 @@ -354,7 +344,7 @@ def get_zero_rated_total(filters): try: return ( frappe.db.sql( - """ + f""" select sum(i.base_net_amount) as total from @@ -363,10 +353,8 @@ def get_zero_rated_total(filters): i.parent = s.name where s.docstatus = 1 and i.is_zero_rated = 1 - {where_conditions} ; - """.format( - where_conditions=conditions - ), + {conditions} ; + """, filters, )[0][0] or 0 @@ -381,7 +369,7 @@ def get_exempt_total(filters): try: return ( frappe.db.sql( - """ + f""" select sum(i.base_net_amount) as total from @@ -390,10 +378,8 @@ def get_exempt_total(filters): i.parent = s.name where s.docstatus = 1 and i.is_exempt = 1 - {where_conditions} ; - """.format( - where_conditions=conditions - ), + {conditions} ; + """, filters, )[0][0] or 0 diff --git a/erpnext/regional/report/vat_audit_report/vat_audit_report.py b/erpnext/regional/report/vat_audit_report/vat_audit_report.py index 3d486ce6506c..718b6c0df310 100644 --- a/erpnext/regional/report/vat_audit_report/vat_audit_report.py +++ b/erpnext/regional/report/vat_audit_report/vat_audit_report.py @@ -13,7 +13,7 @@ def execute(filters=None): return VATAuditReport(filters).run() -class VATAuditReport(object): +class VATAuditReport: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) self.columns = [] @@ -58,19 +58,17 @@ def get_invoice_data(self, doctype): self.invoices = frappe._dict() invoice_data = frappe.db.sql( - """ + f""" SELECT - {select_columns} + {self.select_columns} FROM `tab{doctype}` WHERE - docstatus = 1 {where_conditions} + docstatus = 1 {conditions} and is_opening = 'No' ORDER BY posting_date DESC - """.format( - select_columns=self.select_columns, doctype=doctype, where_conditions=conditions - ), + """, self.filters, as_dict=1, ) @@ -86,11 +84,10 @@ def get_invoice_items(self, doctype): SELECT item_code, parent, base_net_amount, is_zero_rated FROM - `tab%s Item` + `tab{} Item` WHERE - parent in (%s) - """ - % (doctype, ", ".join(["%s"] * len(self.invoices))), + parent in ({}) + """.format(doctype, ", ".join(["%s"] * len(self.invoices))), tuple(self.invoices), as_dict=1, ) @@ -111,15 +108,14 @@ def get_items_based_on_tax_rate(self, doctype): SELECT parent, account_head, item_wise_tax_detail FROM - `tab%s` + `tab{}` WHERE - parenttype = %s and docstatus = 1 - and parent in (%s) + parenttype = {} and docstatus = 1 + and parent in ({}) ORDER BY account_head - """ - % (self.tax_doctype, "%s", ", ".join(["%s"] * len(self.invoices.keys()))), - tuple([doctype] + list(self.invoices.keys())), + """.format(self.tax_doctype, "%s", ", ".join(["%s"] * len(self.invoices.keys()))), + tuple([doctype, *list(self.invoices.keys())]), ) for parent, account, item_wise_tax_detail in self.tax_details: diff --git a/erpnext/regional/saudi_arabia/setup.py b/erpnext/regional/saudi_arabia/setup.py index 7f41c462ccee..c6ba28c59932 100644 --- a/erpnext/regional/saudi_arabia/setup.py +++ b/erpnext/regional/saudi_arabia/setup.py @@ -2,11 +2,12 @@ # License: GNU General Public License v3. See license.txt import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.permissions import add_permission, update_permission_property + from erpnext.regional.saudi_arabia.wizard.operations.setup_ksa_vat_setting import ( create_ksa_vat_setting, ) -from frappe.custom.doctype.custom_field.custom_field import create_custom_fields def setup(company=None, patch=True): diff --git a/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py b/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py index 66d9df224e70..cf4f6e81b7b1 100644 --- a/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py +++ b/erpnext/regional/saudi_arabia/wizard/operations/setup_ksa_vat_setting.py @@ -10,7 +10,7 @@ def create_ksa_vat_setting(company): company = frappe.get_doc("Company", company) file_path = os.path.join(os.path.dirname(__file__), "..", "data", "ksa_vat_settings.json") - with open(file_path, "r") as json_file: + with open(file_path) as json_file: account_data = json.load(json_file) # Creating KSA VAT Setting diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 634a152147d5..d71b87bd903c 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -55,14 +55,12 @@ def generator(): def get_tax_accounts(company): """Get the list of tax accounts for a specific company.""" tax_accounts_dict = frappe._dict() - tax_accounts_list = frappe.get_all( - "UAE VAT Account", filters={"parent": company}, fields=["Account"] - ) + tax_accounts_list = frappe.get_all("UAE VAT Account", filters={"parent": company}, fields=["Account"]) if not tax_accounts_list and not frappe.flags.in_test: frappe.throw(_('Please set Vat Accounts for Company: "{0}" in UAE VAT Settings').format(company)) for tax_account in tax_accounts_list: - for account, name in tax_account.items(): + for _account, name in tax_account.items(): tax_accounts_dict[name] = name return tax_accounts_dict @@ -106,7 +104,6 @@ def update_totals(vat_tax, base_vat_tax, doc): doc.grand_total -= vat_tax if doc.meta.get_field("rounded_total"): - if doc.is_rounded_total_disabled(): doc.outstanding_amount = doc.grand_total @@ -120,9 +117,7 @@ def update_totals(vat_tax, base_vat_tax, doc): doc.outstanding_amount = doc.rounded_total or doc.grand_total doc.in_words = money_in_words(doc.grand_total, doc.currency) - doc.base_in_words = money_in_words( - doc.base_grand_total, erpnext.get_company_currency(doc.company) - ) + doc.base_in_words = money_in_words(doc.base_grand_total, erpnext.get_company_currency(doc.company)) doc.set_payment_schedule() diff --git a/erpnext/regional/united_states/setup.py b/erpnext/regional/united_states/setup.py index 47f24ef4e72c..cb139e6ee86d 100644 --- a/erpnext/regional/united_states/setup.py +++ b/erpnext/regional/united_states/setup.py @@ -1,10 +1,8 @@ # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt + import frappe -import os -import json -from frappe.permissions import add_permission, update_permission_property from frappe.custom.doctype.custom_field.custom_field import create_custom_fields diff --git a/erpnext/regional/united_states/test_united_states.py b/erpnext/regional/united_states/test_united_states.py index 83ba6ed3ad16..e54552b03329 100644 --- a/erpnext/regional/united_states/test_united_states.py +++ b/erpnext/regional/united_states/test_united_states.py @@ -10,7 +10,6 @@ class TestUnitedStates(unittest.TestCase): def test_irs_1099_custom_field(self): - if not frappe.db.exists("Supplier", "_US 1099 Test Supplier"): doc = frappe.new_doc("Supplier") doc.supplier_name = "_US 1099 Test Supplier" @@ -38,7 +37,6 @@ def test_irs_1099_report(self): def make_payment_entry_to_irs_1099_supplier(): - frappe.db.sql("delete from `tabGL Entry` where party='_US 1099 Test Supplier'") frappe.db.sql("delete from `tabGL Entry` where against='_US 1099 Test Supplier'") frappe.db.sql("delete from `tabPayment Entry` where party='_US 1099 Test Supplier'") diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 74f68ea69227..182e10a4765d 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -18,9 +18,8 @@ from frappe.utils import cint, cstr, flt, get_formatted_email, today from frappe.utils.user import get_users_with_role -from erpnext.accounts.party import ( # noqa +from erpnext.accounts.party import ( get_dashboard_info, - get_timeline_data, validate_party_accounts, ) from erpnext.utilities.transaction_base import TransactionBase @@ -49,17 +48,16 @@ def autoname(self): self.name = set_name_from_naming_options(frappe.get_meta(self.doctype).autoname, self) def get_customer_name(self): - if frappe.db.get_value("Customer", self.customer_name) and not frappe.flags.in_import: count = frappe.db.sql( """select ifnull(MAX(CAST(SUBSTRING_INDEX(name, ' ', -1) AS UNSIGNED)), 0) from tabCustomer where name like %s""", - "%{0} - %".format(self.customer_name), + f"%{self.customer_name} - %", as_list=1, )[0][0] count = cint(count) + 1 - new_customer_name = "{0} - {1}".format(self.customer_name, cstr(count)) + new_customer_name = f"{self.customer_name} - {cstr(count)}" msgprint( _("Changed customer name to '{}' as '{}' already exists.").format( @@ -259,9 +257,7 @@ def validate_credit_limit_on_change(self): ) ] - current_credit_limits = [ - d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company) - ] + current_credit_limits = [d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)] if past_credit_limits == current_credit_limits: return @@ -442,9 +438,7 @@ def get_loyalty_programs(doc): ) and ( not loyalty_program.customer_territory or doc.territory - in get_nested_links( - "Territory", loyalty_program.customer_territory, doc.flags.ignore_permissions - ) + in get_nested_links("Territory", loyalty_program.customer_territory, doc.flags.ignore_permissions) ): lp_details.append(loyalty_program.name) @@ -480,14 +474,14 @@ def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None): fields = get_fields("Customer", fields) match_conditions = build_match_conditions("Customer") - match_conditions = "and {}".format(match_conditions) if match_conditions else "" + match_conditions = f"and {match_conditions}" if match_conditions else "" if filters: filter_conditions = get_filters_cond(doctype, filters, []) - match_conditions += "{}".format(filter_conditions) + match_conditions += f"{filter_conditions}" return frappe.db.sql( - """ + f""" select %s from `tabCustomer` where docstatus < 2 @@ -497,9 +491,7 @@ def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None): case when name like %s then 0 else 1 end, case when customer_name like %s then 0 else 1 end, name, customer_name limit %s, %s - """.format( - match_conditions=match_conditions - ) + """ % (", ".join(fields), searchfield, "%s", "%s", "%s", "%s", "%s", "%s"), ("%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, start, page_len), ) @@ -534,12 +526,12 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False, ] if not credit_controller_users_formatted: frappe.throw( - _("Please contact your administrator to extend the credit limits for {0}.").format(customer) + _("Please contact your administrator to extend the credit limits for {0}.").format( + customer + ) ) - user_list = "

    • {0}
    ".format( - "
  • ".join(credit_controller_users_formatted) - ) + user_list = "

    • {}
    ".format("
  • ".join(credit_controller_users_formatted)) message = _( "Please contact any of the following users to extend the credit limits for {0}: {1}" @@ -572,33 +564,25 @@ def send_emails(args): message = _("Credit limit has been crossed for customer {0} ({1}/{2})").format( args.get("customer"), args.get("customer_outstanding"), args.get("credit_limit") ) - frappe.sendmail( - recipients=args.get("credit_controller_users_list"), subject=subject, message=message - ) + frappe.sendmail(recipients=args.get("credit_controller_users_list"), subject=subject, message=message) -def get_customer_outstanding( - customer, company, ignore_outstanding_sales_order=False, cost_center=None -): +def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=False, cost_center=None): # Outstanding based on GL Entries cond = "" if cost_center: lft, rgt = frappe.get_cached_value("Cost Center", cost_center, ["lft", "rgt"]) - cond = """ and cost_center in (select name from `tabCost Center` where - lft >= {0} and rgt <= {1})""".format( - lft, rgt - ) + cond = f""" and cost_center in (select name from `tabCost Center` where + lft >= {lft} and rgt <= {rgt})""" outstanding_based_on_gle = frappe.db.sql( - """ + f""" select sum(debit) - sum(credit) from `tabGL Entry` where party_type = 'Customer' and is_cancelled = 0 and party = %s - and company=%s {0}""".format( - cond - ), + and company=%s {cond}""", (customer, company), ) @@ -749,7 +733,7 @@ def make_address(args, is_primary_address=1, is_shipping_address=1): if reqd_fields: msg = _("Following fields are mandatory to create address:") frappe.throw( - "{0}

      {1}
    ".format(msg, "\n".join(reqd_fields)), + "{}

      {}
    ".format(msg, "\n".join(reqd_fields)), title=_("Missing Values Required"), ) diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index 7e91e6e6599c..61e5d5e457cd 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -268,7 +268,6 @@ def get_customer_outstanding_amount(self): def test_customer_credit_limit(self): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice - from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note @@ -443,17 +442,13 @@ def set_credit_limit(customer, company, credit_limit): customer.credit_limits[-1].db_insert() -def create_internal_customer( - customer_name=None, represents_company=None, allowed_to_interact_with=None -): +def create_internal_customer(customer_name=None, represents_company=None, allowed_to_interact_with=None): if not customer_name: customer_name = represents_company if not allowed_to_interact_with: allowed_to_interact_with = represents_company - exisiting_representative = frappe.db.get_value( - "Customer", {"represents_company": represents_company} - ) + exisiting_representative = frappe.db.get_value("Customer", {"represents_company": represents_company}) if exisiting_representative: return exisiting_representative diff --git a/erpnext/selling/doctype/installation_note/installation_note.py b/erpnext/selling/doctype/installation_note/installation_note.py index 0ef4754bc68e..c2464cbcb614 100644 --- a/erpnext/selling/doctype/installation_note/installation_note.py +++ b/erpnext/selling/doctype/installation_note/installation_note.py @@ -12,7 +12,7 @@ class InstallationNote(TransactionBase): def __init__(self, *args, **kwargs): - super(InstallationNote, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "source_dt": "Installation Note Item", diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py index 3d4ffebbfb43..fe4933ccdd95 100644 --- a/erpnext/selling/doctype/product_bundle/product_bundle.py +++ b/erpnext/selling/doctype/product_bundle/product_bundle.py @@ -49,7 +49,7 @@ def on_trash(self): if len(invoice_links): frappe.throw( - "This Product Bundle is linked with {0}. You will have to cancel these documents in order to delete this Product Bundle".format( + "This Product Bundle is linked with {}. You will have to cancel these documents in order to delete this Product Bundle".format( ", ".join(invoice_links) ), title=_("Not Allowed"), @@ -81,9 +81,7 @@ def get_new_item_code(doctype, txt, searchfield, start, page_len, filters): query = ( frappe.qb.from_(item) .select(item.item_code, item.item_name) - .where( - (item.is_stock_item == 0) & (item.is_fixed_asset == 0) & (item[searchfield].like(f"%{txt}%")) - ) + .where((item.is_stock_item == 0) & (item.is_fixed_asset == 0) & (item[searchfield].like(f"%{txt}%"))) .limit(page_len) .offset(start) ) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index de2cef909299..70d0c1a25fe6 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -22,7 +22,7 @@ def set_indicator(self): self.indicator_title = "Expired" def validate(self): - super(Quotation, self).validate() + super().validate() self.set_status() self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("uom", "qty") @@ -106,7 +106,8 @@ def get_valid_items(self): def is_in_sales_order(row): in_sales_order = bool( frappe.db.exists( - "Sales Order Item", {"quotation_item": row.name, "item_code": row.item_code, "docstatus": 1} + "Sales Order Item", + {"quotation_item": row.name, "item_code": row.item_code, "docstatus": 1}, ) ) return in_sales_order @@ -196,7 +197,7 @@ def on_submit(self): def on_cancel(self): if self.lost_reasons: self.lost_reasons = [] - super(Quotation, self).on_cancel() + super().on_cancel() # update enquiry status self.set_status(update=True) @@ -371,12 +372,8 @@ def set_expired_status(): # if not exists any SO, set status as Expired frappe.db.multisql( { - "mariadb": """UPDATE `tabQuotation` SET `tabQuotation`.status = 'Expired' WHERE {cond} and not exists({so_against_quo})""".format( - cond=cond, so_against_quo=so_against_quo - ), - "postgres": """UPDATE `tabQuotation` SET status = 'Expired' FROM `tabSales Order`, `tabSales Order Item` WHERE {cond} and not exists({so_against_quo})""".format( - cond=cond, so_against_quo=so_against_quo - ), + "mariadb": f"""UPDATE `tabQuotation` SET `tabQuotation`.status = 'Expired' WHERE {cond} and not exists({so_against_quo})""", + "postgres": f"""UPDATE `tabQuotation` SET status = 'Expired' FROM `tabSales Order`, `tabSales Order Item` WHERE {cond} and not exists({so_against_quo})""", }, (nowdate()), ) @@ -464,7 +461,8 @@ def _make_customer(source_name, ignore_permissions=False): frappe.local.message_log = [] lead_link = frappe.utils.get_link_to_form("Lead", lead_name) message = ( - _("Could not auto create Customer due to the following missing mandatory field(s):") + "
    " + _("Could not auto create Customer due to the following missing mandatory field(s):") + + "
    " ) message += "
    • " + "
    • ".join(mandatory_fields) + "
    " message += _("Please create Customer from Lead {0}.").format(lead_link) diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 28f9a7d4f837..e840ac202682 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -140,9 +140,7 @@ def test_make_sales_order_with_terms(self): self.assertEqual(quotation.payment_schedule[0].payment_amount, 8906.00) self.assertEqual(quotation.payment_schedule[0].due_date, quotation.transaction_date) self.assertEqual(quotation.payment_schedule[1].payment_amount, 8906.00) - self.assertEqual( - quotation.payment_schedule[1].due_date, add_days(quotation.transaction_date, 30) - ) + self.assertEqual(quotation.payment_schedule[1].due_date, add_days(quotation.transaction_date, 30)) sales_order = make_sales_order(quotation.name) @@ -175,9 +173,7 @@ def test_valid_till_before_transaction_date(self): def test_so_from_expired_quotation(self): from erpnext.selling.doctype.quotation.quotation import make_sales_order - frappe.db.set_single_value( - "Selling Settings", "allow_sales_order_creation_for_expired_quotation", 0 - ) + frappe.db.set_single_value("Selling Settings", "allow_sales_order_creation_for_expired_quotation", 0) quotation = frappe.copy_doc(test_records[0]) quotation.valid_till = add_days(nowdate(), -1) @@ -186,9 +182,7 @@ def test_so_from_expired_quotation(self): self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name) - frappe.db.set_single_value( - "Selling Settings", "allow_sales_order_creation_for_expired_quotation", 1 - ) + frappe.db.set_single_value("Selling Settings", "allow_sales_order_creation_for_expired_quotation", 1) make_sales_order(quotation.name) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 81f9cedbc626..68fa67e92f1a 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -42,10 +42,10 @@ class WarehouseRequired(frappe.ValidationError): class SalesOrder(SellingController): def __init__(self, *args, **kwargs): - super(SalesOrder, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def validate(self): - super(SalesOrder, self).validate() + super().validate() self.validate_delivery_date() self.validate_proj_cust() self.validate_po() @@ -85,7 +85,9 @@ def validate_po(self): for d in self.get("items"): if d.delivery_date and getdate(self.po_date) > getdate(d.delivery_date): frappe.throw( - _("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date").format(d.idx) + _("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date").format( + d.idx + ) ) if self.po_no and self.customer and not self.skip_delivery_note: @@ -100,9 +102,9 @@ def validate_po(self): frappe.db.get_single_value("Selling Settings", "allow_against_multiple_purchase_orders") ): frappe.msgprint( - _("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format( - frappe.bold(so[0][0]), frappe.bold(self.po_no) - ), + _( + "Warning: Sales Order {0} already exists against Customer's Purchase Order {1}" + ).format(frappe.bold(so[0][0]), frappe.bold(self.po_no)), alert=True, ) else: @@ -112,14 +114,15 @@ def validate_po(self): ).format( frappe.bold(so[0][0]), frappe.bold(self.po_no), - frappe.bold(_("'Allow Multiple Sales Orders Against a Customer's Purchase Order'")), + frappe.bold( + _("'Allow Multiple Sales Orders Against a Customer's Purchase Order'") + ), get_link_to_form("Selling Settings", "Selling Settings"), ) ) def validate_for_items(self): for d in self.get("items"): - # used for production plan d.transaction_date = self.transaction_date @@ -149,7 +152,9 @@ def validate_sales_mntc_quotation(self): (d.prevdoc_docname, self.order_type), ) if not res: - frappe.msgprint(_("Quotation {0} not of type {1}").format(d.prevdoc_docname, self.order_type)) + frappe.msgprint( + _("Quotation {0} not of type {1}").format(d.prevdoc_docname, self.order_type) + ) def validate_delivery_date(self): if self.order_type == "Sales" and not self.skip_delivery_note: @@ -188,13 +193,16 @@ def validate_proj_cust(self): ) def validate_warehouse(self): - super(SalesOrder, self).validate_warehouse() + super().validate_warehouse() for d in self.get("items"): if ( ( frappe.get_cached_value("Item", d.item_code, "is_stock_item") == 1 - or (self.has_product_bundle(d.item_code) and self.product_bundle_has_stock_item(d.item_code)) + or ( + self.has_product_bundle(d.item_code) + and self.product_bundle_has_stock_item(d.item_code) + ) ) and not d.warehouse and not cint(d.delivered_by_supplier) @@ -204,7 +212,7 @@ def validate_warehouse(self): ) def validate_with_previous_doc(self): - super(SalesOrder, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Quotation": {"ref_dn_field": "prevdoc_docname", "compare_fields": [["company", "="]]}, "Quotation Item": { @@ -262,7 +270,7 @@ def on_submit(self): def on_cancel(self): self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry") - super(SalesOrder, self).on_cancel() + super().on_cancel() # Cannot cancel closed SO if self.status == "Closed": @@ -284,9 +292,7 @@ def on_cancel(self): update_coupon_code_count(self.coupon_code, "cancelled") def update_project(self): - if ( - frappe.db.get_single_value("Selling Settings", "sales_update_frequency") != "Each Transaction" - ): + if frappe.db.get_single_value("Selling Settings", "sales_update_frequency") != "Each Transaction": return if self.project: @@ -324,7 +330,7 @@ def check_nextdoc_docstatus(self): def check_modified_date(self): mod_db = frappe.db.get_value("Sales Order", self.name, "modified") - date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % (mod_db, cstr(self.modified))) + date_diff = frappe.db.sql(f"select TIMEDIFF('{mod_db}', '{cstr(self.modified)}')") if date_diff and date_diff[0][0]: frappe.throw(_("{0} {1} has been modified. Please refresh.").format(self.doctype, self.name)) @@ -499,9 +505,9 @@ def validate_serial_no_based_delivery(self): ) if not frappe.db.exists("BOM", {"item": item.item_code, "is_active": 1}): frappe.throw( - _("No active BOM found for item {0}. Delivery by Serial No cannot be ensured").format( - item.item_code - ) + _( + "No active BOM found for item {0}. Delivery by Serial No cannot be ensured" + ).format(item.item_code) ) reserved_items.append(item.item_code) else: @@ -877,7 +883,7 @@ def get_events(start, end, filters=None): conditions = get_event_conditions("Sales Order", filters) data = frappe.db.sql( - """ + f""" select distinct `tabSales Order`.name, `tabSales Order`.customer_name, `tabSales Order`.status, `tabSales Order`.delivery_status, `tabSales Order`.billing_status, @@ -890,9 +896,7 @@ def get_events(start, end, filters=None): and (`tabSales Order Item`.delivery_date between %(start)s and %(end)s) and `tabSales Order`.docstatus < 2 {conditions} - """.format( - conditions=conditions - ), + """, {"start": start, "end": end}, as_dict=True, update={"allDay": 0}, @@ -966,9 +970,7 @@ def update_item(source, target, source_parent): items_to_map = list(set(items_to_map)) if not suppliers: - frappe.throw( - _("Please set a Supplier against the Items to be considered in the Purchase Order.") - ) + frappe.throw(_("Please set a Supplier against the Items to be considered in the Purchase Order.")) purchase_orders = [] for supplier in suppliers: @@ -1034,9 +1036,7 @@ def make_purchase_order(source_name, selected_items=None, target_doc=None): selected_items = json.loads(selected_items) items_to_map = [ - item.get("item_code") - for item in selected_items - if item.get("item_code") and item.get("item_code") + item.get("item_code") for item in selected_items if item.get("item_code") and item.get("item_code") ] items_to_map = list(set(items_to_map)) @@ -1219,17 +1219,13 @@ def make_raw_material_request(items, company, sales_order, project=None): for item in items.get("items"): item["include_exploded_items"] = items.get("include_exploded_items") item["ignore_existing_ordered_qty"] = items.get("ignore_existing_ordered_qty") - item["include_raw_materials_from_sales_order"] = items.get( - "include_raw_materials_from_sales_order" - ) + item["include_raw_materials_from_sales_order"] = items.get("include_raw_materials_from_sales_order") items.update({"company": company, "sales_order": sales_order}) raw_materials = get_items_for_material_requests(items) if not raw_materials: - frappe.msgprint( - _("Material Request not created, as quantity for Raw Materials already available.") - ) + frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available.")) return material_request = frappe.new_doc("Material Request") diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index ee7cb3232857..4ebd2a0c2d09 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -309,9 +309,7 @@ def test_reserved_qty_for_over_delivery_via_sales_invoice(self): def test_reserved_qty_for_partial_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - make_stock_entry( - item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100 - ) + make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) existing_reserved_qty_item1 = get_reserved_qty("_Test Item") existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") @@ -319,16 +317,12 @@ def test_reserved_qty_for_partial_delivery_with_packing_list(self): so = make_sales_order(item_code="_Test Product Bundle Item") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) - self.assertEqual( - get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20 - ) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) dn = create_dn_against_so(so.name) self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) - self.assertEqual( - get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10 - ) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10) # close so so.load_from_db() @@ -342,15 +336,11 @@ def test_reserved_qty_for_partial_delivery_with_packing_list(self): so.update_status("Draft") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) - self.assertEqual( - get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10 - ) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10) dn.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) - self.assertEqual( - get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20 - ) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) so.load_from_db() so.cancel() @@ -366,9 +356,7 @@ def test_sales_order_on_hold(self): def test_reserved_qty_for_over_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - make_stock_entry( - item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100 - ) + make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) # set over-delivery allowance frappe.db.set_value("Item", "_Test Product Bundle Item", "over_delivery_receipt_allowance", 50) @@ -379,9 +367,7 @@ def test_reserved_qty_for_over_delivery_with_packing_list(self): so = make_sales_order(item_code="_Test Product Bundle Item") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) - self.assertEqual( - get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20 - ) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) dn = create_dn_against_so(so.name, 15) @@ -390,9 +376,7 @@ def test_reserved_qty_for_over_delivery_with_packing_list(self): dn.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) - self.assertEqual( - get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20 - ) + self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) def test_update_child_adding_new_item(self): so = make_sales_order(item_code="_Test Item", qty=4) @@ -462,9 +446,7 @@ def test_update_child_removing_item(self): trans_item = json.dumps( [{"item_code": "_Test Item 2", "qty": 2, "rate": 500, "docname": so.get("items")[1].name}] ) - self.assertRaises( - frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name - ) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name) # remove last added item trans_item = json.dumps( @@ -503,9 +485,7 @@ def test_update_child(self): trans_item = json.dumps( [{"item_code": "_Test Item", "rate": 200, "qty": 2, "docname": so.items[0].name}] ) - self.assertRaises( - frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name - ) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name) def test_update_child_with_precision(self): from frappe.custom.doctype.property_setter.property_setter import make_property_setter @@ -535,15 +515,11 @@ def test_update_child_perm(self): trans_item = json.dumps( [{"item_code": "_Test Item", "rate": 200, "qty": 7, "docname": so.items[0].name}] ) - self.assertRaises( - frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name - ) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name) # add new item trans_item = json.dumps([{"item_code": "_Test Item", "rate": 100, "qty": 2}]) - self.assertRaises( - frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name - ) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name) def test_update_child_qty_rate_with_workflow(self): from frappe.model.workflow import apply_workflow @@ -561,9 +537,7 @@ def test_update_child_qty_rate_with_workflow(self): trans_item = json.dumps( [{"item_code": "_Test Item", "rate": 150, "qty": 2, "docname": so.items[0].name}] ) - self.assertRaises( - frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name - ) + self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name) frappe.set_user("Administrator") user2 = "test2@example.com" @@ -821,9 +795,7 @@ def test_warehouse_user(self): frappe.set_user("Administrator") frappe.permissions.remove_user_permission("Warehouse", "_Test Warehouse 1 - _TC", test_user.name) - frappe.permissions.remove_user_permission( - "Warehouse", "_Test Warehouse 2 - _TC1", test_user_2.name - ) + frappe.permissions.remove_user_permission("Warehouse", "_Test Warehouse 2 - _TC1", test_user_2.name) frappe.permissions.remove_user_permission("Company", "_Test Company 1", test_user_2.name) def test_block_delivery_note_against_cancelled_sales_order(self): @@ -942,9 +914,7 @@ def test_drop_shipping(self): from erpnext.selling.doctype.sales_order.sales_order import update_status as so_update_status # make items - po_item = make_item( - "_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1} - ) + po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1}) dn_item = make_item("_Test Regular Item", {"is_stock_item": 1}) so_items = [ @@ -1227,17 +1197,13 @@ def test_create_so_with_margin(self): new_so = frappe.copy_doc(so) new_so.save(ignore_permissions=True) - self.assertEqual( - new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate) - ) + self.assertEqual(new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate)) new_so.items[0].margin_rate_or_amount = 25 new_so.payment_schedule = [] new_so.save() new_so.submit() - self.assertEqual( - new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate) - ) + self.assertEqual(new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate)) def test_terms_auto_added(self): so = make_sales_order(do_not_save=1) @@ -1601,7 +1567,7 @@ def test_so_optional_blanket_order(self): Second Sales Order should not add on to Blanket Orders Ordered Quantity. """ - bo = make_blanket_order(blanket_order_type="Selling", quantity=10, rate=10) + make_blanket_order(blanket_order_type="Selling", quantity=10, rate=10) so = make_sales_order(item_code="_Test Item", qty=5, against_blanket_order=1) so_doc = frappe.get_doc("Sales Order", so.get("name")) @@ -1822,7 +1788,10 @@ def test_so_back_updated_from_wo_via_mr(self): wo.submit() make_stock_entry( - item_code="_Test Item", target="Work In Progress - _TC", qty=4, basic_rate=100 # Stock RM + item_code="_Test Item", + target="Work In Progress - _TC", + qty=4, + basic_rate=100, # Stock RM ) make_stock_entry( item_code="_Test Item Home Desktop 100", # Stock RM @@ -1930,10 +1899,6 @@ def test_sales_order_partial_advance_payment(self): def test_delivered_item_material_request(self): "SO -> MR (Manufacture) -> WO. Test if WO Qty is updated in SO." - from erpnext.manufacturing.doctype.work_order.work_order import ( - make_stock_entry as make_se_from_wo, - ) - from erpnext.stock.doctype.material_request.material_request import raise_work_orders so = make_sales_order( item_list=[ @@ -1941,9 +1906,7 @@ def test_delivered_item_material_request(self): ] ) - make_stock_entry( - item_code="_Test FG Item", target="Work In Progress - _TC", qty=4, basic_rate=100 - ) + make_stock_entry(item_code="_Test FG Item", target="Work In Progress - _TC", qty=4, basic_rate=100) dn = make_delivery_note(so.name) dn.items[0].qty = 4 @@ -1968,7 +1931,8 @@ def test_packed_items_for_partial_sales_order(self): if not frappe.db.exists("Item", product_bundle): bundle_item = make_item(product_bundle, {"is_stock_item": 0}) bundle_item.append( - "item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"} + "item_defaults", + {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}, ) bundle_item.save(ignore_permissions=True) @@ -2038,7 +2002,8 @@ def test_expired_rate_for_packed_item(self): if not frappe.db.exists("Item", product_bundle): bundle_item = make_item(product_bundle, {"is_stock_item": 0}) bundle_item.append( - "item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"} + "item_defaults", + {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}, ) bundle_item.save(ignore_permissions=True) @@ -2271,9 +2236,7 @@ def create_dn_against_so(so, delivered_qty=0, do_not_submit=False): def get_reserved_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"): - return flt( - frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "reserved_qty") - ) + return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "reserved_qty")) test_dependencies = ["Currency Exchange"] @@ -2286,9 +2249,7 @@ def make_sales_order_workflow(): doc.save() return doc - frappe.get_doc(dict(doctype="Role", role_name="Test Junior Approver")).insert( - ignore_if_duplicate=True - ) + frappe.get_doc(dict(doctype="Role", role_name="Test Junior Approver")).insert(ignore_if_duplicate=True) frappe.get_doc(dict(doctype="Role", role_name="Test Approver")).insert(ignore_if_duplicate=True) frappe.cache().hdel("roles", frappe.session.user) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 6744a5d49e72..bc94d3b706e1 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -3,7 +3,6 @@ import json -from typing import Dict, Optional import frappe from frappe.utils import cint @@ -178,16 +177,14 @@ def get_items(start, page_length, price_list, item_group, pos_profile, search_te @frappe.whitelist() -def search_for_serial_or_batch_or_barcode_number(search_value: str) -> Dict[str, Optional[str]]: +def search_for_serial_or_batch_or_barcode_number(search_value: str) -> dict[str, str | None]: return scan_barcode(search_value) def get_conditions(search_term): condition = "(" condition += """item.name like {search_term} - or item.item_name like {search_term}""".format( - search_term=frappe.db.escape("%" + search_term + "%") - ) + or item.item_name like {search_term}""".format(search_term=frappe.db.escape("%" + search_term + "%")) condition += add_search_fields_condition(search_term) condition += ")" @@ -199,7 +196,7 @@ def add_search_fields_condition(search_term): search_fields = frappe.get_all("POS Search Fields", fields=["fieldname"]) if search_fields: for field in search_fields: - condition += " or item.`{0}` like {1}".format( + condition += " or item.`{}` like {}".format( field["fieldname"], frappe.db.escape("%" + search_term + "%") ) return condition @@ -229,10 +226,8 @@ def item_group_query(doctype, txt, searchfield, start, page_len, filters): cond = cond % tuple(item_groups) return frappe.db.sql( - """ select distinct name from `tabItem Group` - where {condition} and (name like %(txt)s) limit {page_len} offset {start}""".format( - condition=cond, start=start, page_len=page_len - ), + f""" select distinct name from `tabItem Group` + where {cond} and (name like %(txt)s) limit {page_len} offset {start}""", {"txt": "%%%s%%" % txt}, ) @@ -277,12 +272,12 @@ def get_past_order_list(search_term, status, limit=20): if search_term and status: invoices_by_customer = frappe.db.get_all( "POS Invoice", - filters={"customer": ["like", "%{}%".format(search_term)], "status": status}, + filters={"customer": ["like", f"%{search_term}%"], "status": status}, fields=fields, ) invoices_by_name = frappe.db.get_all( "POS Invoice", - filters={"name": ["like", "%{}%".format(search_term)], "status": status}, + filters={"name": ["like", f"%{search_term}%"], "status": status}, fields=fields, ) diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.py b/erpnext/selling/page/sales_funnel/sales_funnel.py index 6b33a7175311..155d21ed5d19 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.py +++ b/erpnext/selling/page/sales_funnel/sales_funnel.py @@ -85,7 +85,7 @@ def get_opp_by_lead_source(from_date, to_date, company): * x["probability"] / 100 ) - } + }, ) for x in opportunities ] @@ -137,7 +137,7 @@ def get_pipeline_data(from_date, to_date, company): * x["probability"] / 100 ) - } + }, ) for x in opportunities ] diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.py b/erpnext/selling/report/address_and_contacts/address_and_contacts.py index 9a1cfda8474e..5ae00f373114 100644 --- a/erpnext/selling/report/address_and_contacts/address_and_contacts.py +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.py @@ -27,8 +27,8 @@ def get_columns(filters): party_type = filters.get("party_type") party_type_value = get_party_group(party_type) return [ - "{party_type}:Link/{party_type}".format(party_type=party_type), - "{party_value_type}::150".format(party_value_type=frappe.unscrub(str(party_type_value))), + f"{party_type}:Link/{party_type}", + f"{frappe.unscrub(str(party_type_value))}::150", "Address Line 1", "Address Line 2", "City", @@ -109,7 +109,7 @@ def get_party_details(party_type, party_list, doctype, party_details): ["Dynamic Link", "link_doctype", "=", party_type], ["Dynamic Link", "link_name", "in", party_list], ] - fields = ["`tabDynamic Link`.link_name"] + field_map.get(doctype, []) + fields = ["`tabDynamic Link`.link_name", *field_map.get(doctype, [])] records = frappe.get_list(doctype, filters=filters, fields=fields, as_list=True) for d in records: diff --git a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py index 3e4bfb2ef711..dcdd2525d8e2 100644 --- a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py +++ b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py @@ -77,10 +77,8 @@ def get_data_by_time(filters, common_columns): out = [] for year in range(from_year, to_year + 1): - for month in range( - from_month if year == from_year else 1, (to_month + 1) if year == to_year else 13 - ): - key = "{year}-{month:02d}".format(year=year, month=month) + for month in range(from_month if year == from_year else 1, (to_month + 1) if year == to_year else 13): + key = f"{year}-{month:02d}" data = customers_in.get(key) new = data["new"] if data else [0, 0.0] repeat = data["repeat"] if data else [0, 0.0] @@ -147,7 +145,7 @@ def get_data_by_territory(filters, common_columns): for ld in loop_data: if ld["parent_territory"]: - parent_data = [x for x in data if x["territory"] == ld["parent_territory"]][0] + parent_data = next(x for x in data if x["territory"] == ld["parent_territory"]) for key in parent_data.keys(): if key not in ["indent", "territory", "parent_territory", "bold"]: parent_data[key] += ld[key] @@ -165,15 +163,12 @@ def get_customer_stats(filters, tree_view=False): customers_in = {} for si in frappe.db.sql( - """select territory, posting_date, customer, base_grand_total from `tabSales Invoice` + f"""select territory, posting_date, customer, base_grand_total from `tabSales Invoice` where docstatus=1 and posting_date <= %(to_date)s - {company_condition} order by posting_date""".format( - company_condition=company_condition - ), + {company_condition} order by posting_date""", filters, as_dict=1, ): - key = si.territory if tree_view else si.posting_date.strftime("%Y-%m") new_or_repeat = "new" if si.customer not in customers else "repeat" customers_in.setdefault(key, {"new": [0, 0.0], "repeat": [0, 0.0]}) diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py index 98633cb7198c..3fd37f73d849 100644 --- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py +++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py @@ -77,7 +77,6 @@ def get_columns(customer_naming_type): def get_details(filters): - sql_query = """SELECT c.name, c.customer_name, ccl.bypass_credit_limit_check, diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py index 40aa9acc3c6a..6acc060031a3 100644 --- a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py @@ -51,7 +51,10 @@ def get_columns(filters=None): def fetch_item_prices( - customer: str = None, price_list: str = None, selling_price_list: str = None, items: list = None + customer: str | None = None, + price_list: str | None = None, + selling_price_list: str | None = None, + items: list | None = None, ): price_list_map = frappe._dict() ip = qb.DocType("Item Price") @@ -59,10 +62,10 @@ def fetch_item_prices( or_conditions = [] if items: and_conditions.append(ip.item_code.isin([x.item_code for x in items])) - and_conditions.append(ip.selling == True) + and_conditions.append(ip.selling is True) - or_conditions.append(ip.customer == None) - or_conditions.append(ip.price_list == None) + or_conditions.append(ip.customer is None) + or_conditions.append(ip.price_list is None) if customer: or_conditions.append(ip.customer == customer) diff --git a/erpnext/selling/report/inactive_customers/inactive_customers.py b/erpnext/selling/report/inactive_customers/inactive_customers.py index a16608532729..7e4ddc128ac5 100644 --- a/erpnext/selling/report/inactive_customers/inactive_customers.py +++ b/erpnext/selling/report/inactive_customers/inactive_customers.py @@ -40,19 +40,17 @@ def get_sales_details(doctype): DATEDIFF(CURRENT_DATE, max(so.transaction_date)) as 'days_since_last_order'""" return frappe.db.sql( - """select + f"""select cust.name, cust.customer_name, cust.territory, cust.customer_group, count(distinct(so.name)) as 'num_of_order', - sum(base_net_total) as 'total_order_value', {0} - from `tabCustomer` cust, `tab{1}` so + sum(base_net_total) as 'total_order_value', {cond} + from `tabCustomer` cust, `tab{doctype}` so where cust.name = so.customer and so.docstatus = 1 group by cust.name - order by 'days_since_last_order' desc """.format( - cond, doctype - ), + order by 'days_since_last_order' desc """, as_list=1, ) @@ -62,11 +60,9 @@ def get_last_sales_amt(customer, doctype): if doctype == "Sales Order": cond = "transaction_date" res = frappe.db.sql( - """select base_net_total from `tab{0}` - where customer = %s and docstatus = 1 order by {1} desc - limit 1""".format( - doctype, cond - ), + f"""select base_net_total from `tab{doctype}` + where customer = %s and docstatus = 1 order by {cond} desc + limit 1""", customer, ) diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py index 2624db3191df..9cdb14caf464 100644 --- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py +++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py @@ -128,7 +128,6 @@ def get_columns(filters): def get_data(filters): - data = [] company_list = get_descendants_of("Company", filters.get("company")) @@ -181,9 +180,7 @@ def get_item_details(): details = frappe.db.get_all("Item", fields=["name", "item_name", "item_group"]) item_details = {} for d in details: - item_details.setdefault( - d.name, frappe._dict({"item_name": d.item_name, "item_group": d.item_group}) - ) + item_details.setdefault(d.name, frappe._dict({"item_name": d.item_name, "item_group": d.item_group})) return item_details @@ -240,14 +237,13 @@ def get_chart_data(data): for row in data: item_key = row.get("item_code") - if not item_key in item_wise_sales_map: + if item_key not in item_wise_sales_map: item_wise_sales_map[item_key] = 0 item_wise_sales_map[item_key] = flt(item_wise_sales_map[item_key]) + flt(row.get("amount")) item_wise_sales_map = { - item: value - for item, value in (sorted(item_wise_sales_map.items(), key=lambda i: i[1], reverse=True)) + item: value for item, value in (sorted(item_wise_sales_map.items(), key=lambda i: i[1], reverse=True)) } for key in item_wise_sales_map: diff --git a/erpnext/selling/report/lost_quotations/lost_quotations.py b/erpnext/selling/report/lost_quotations/lost_quotations.py index 7c0bfbdd525c..a48e945172cb 100644 --- a/erpnext/selling/report/lost_quotations/lost_quotations.py +++ b/erpnext/selling/report/lost_quotations/lost_quotations.py @@ -53,9 +53,7 @@ def get_columns(group_by: Literal["Lost Reason", "Competitor"]): ] -def get_data( - company: str, from_date: str, to_date: str, group_by: Literal["Lost Reason", "Competitor"] -): +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" diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py index c6e464753877..cf61a0e35f3b 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py @@ -82,9 +82,7 @@ def get_descendants_of(doctype, group_name): ).run()[0] # get all children of group node - query = ( - qb.from_(group_doc).select(group_doc.name).where((group_doc.lft >= lft) & (group_doc.rgt <= rgt)) - ) + query = qb.from_(group_doc).select(group_doc.name).where((group_doc.lft >= lft) & (group_doc.rgt <= rgt)) child_nodes = [] for x in query.run(): @@ -108,7 +106,9 @@ def get_customers_or_items(doctype, txt, searchfield, start, page_len, filters): ) elif item[0] == "Item Group": if item[3] != "": - filter_list.append([doctype, "item_group", "in", get_descendants_of("Item Group", item[3])]) + filter_list.append( + [doctype, "item_group", "in", get_descendants_of("Item Group", item[3])] + ) if searchfield and txt: filter_list.append([doctype, searchfield, "like", "%%%s%%" % txt]) @@ -132,9 +132,7 @@ def get_conditions(filters): conditions.company = filters.company or frappe.defaults.get_user_default("company") conditions.end_date = filters.period_end_date or frappe.utils.today() - conditions.start_date = filters.period_start_date or frappe.utils.add_months( - conditions.end_date, -1 - ) + conditions.start_date = filters.period_start_date or frappe.utils.add_months(conditions.end_date, -1) return conditions diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py index 928ed80d5c9f..7f9f3fb999e7 100644 --- a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py +++ b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py @@ -81,9 +81,7 @@ def get_data(): bundled_item_map = get_packed_items(sales_orders) - item_with_product_bundle = get_items_with_product_bundle( - [row.item_code for row in sales_order_entry] - ) + item_with_product_bundle = get_items_with_product_bundle([row.item_code for row in sales_order_entry]) materials_request_dict = {} @@ -129,7 +127,9 @@ def get_data(): "description": item.description, "sales_order_no": so.name, "date": so.transaction_date, - "material_request": ",".join(material_requests_against_so.get("material_requests", [])), + "material_request": ",".join( + material_requests_against_so.get("material_requests", []) + ), "customer": so.customer, "territory": so.territory, "so_qty": item.qty, diff --git a/erpnext/selling/report/quotation_trends/quotation_trends.py b/erpnext/selling/report/quotation_trends/quotation_trends.py index 4d71ce77c4f1..bcb8fe9297e4 100644 --- a/erpnext/selling/report/quotation_trends/quotation_trends.py +++ b/erpnext/selling/report/quotation_trends/quotation_trends.py @@ -48,9 +48,7 @@ def get_chart_data(data, conditions, filters): return { "data": { "labels": labels, - "datasets": [ - {"name": _(filters.get("period")) + " " + _("Quoted Amount"), "values": datapoints} - ], + "datasets": [{"name": _(filters.get("period")) + " " + _("Quoted Amount"), "values": datapoints}], }, "type": "line", "lineOptions": {"regionFill": 1}, diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.py b/erpnext/selling/report/sales_analytics/sales_analytics.py index 605d2fac44f0..27d2e6e555ec 100644 --- a/erpnext/selling/report/sales_analytics/sales_analytics.py +++ b/erpnext/selling/report/sales_analytics/sales_analytics.py @@ -13,7 +13,7 @@ def execute(filters=None): return Analytics(filters).run() -class Analytics(object): +class Analytics: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) self.date_field = ( @@ -87,9 +87,7 @@ def get_columns(self): {"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120} ) - self.columns.append( - {"label": _("Total"), "fieldname": "total", "fieldtype": "Float", "width": 120} - ) + self.columns.append({"label": _("Total"), "fieldname": "total", "fieldtype": "Float", "width": 120}) def get_data(self): if self.filters.tree_type in ["Customer", "Supplier"]: @@ -129,9 +127,7 @@ def get_sales_transactions_based_on_order_type(self): """ select s.order_type as entity, s.{value_field} as value_field, s.{date_field} from `tab{doctype}` s where s.docstatus = 1 and s.company = %s and s.{date_field} between %s and %s and ifnull(s.order_type, '') != '' order by s.order_type - """.format( - date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type - ), + """.format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type), (self.filters.company, self.filters.from_date, self.filters.to_date), as_dict=1, ) @@ -166,7 +162,6 @@ def get_sales_transactions_based_on_customers_or_suppliers(self): self.entity_names.setdefault(d.entity, d.entity_name) def get_sales_transactions_based_on_items(self): - if self.filters["value_quantity"] == "Value": value_field = "base_net_amount" else: @@ -178,9 +173,7 @@ def get_sales_transactions_based_on_items(self): from `tab{doctype} Item` i , `tab{doctype}` s where s.name = i.parent and i.docstatus = 1 and s.company = %s and s.{date_field} between %s and %s - """.format( - date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type - ), + """.format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type), (self.filters.company, self.filters.from_date, self.filters.to_date), as_dict=1, ) @@ -221,14 +214,12 @@ def get_sales_transactions_based_on_item_group(self): value_field = "qty" self.entries = frappe.db.sql( - """ - select i.item_group as entity, i.{value_field} as value_field, s.{date_field} - from `tab{doctype} Item` i , `tab{doctype}` s + f""" + select i.item_group as entity, i.{value_field} as value_field, s.{self.date_field} + from `tab{self.filters.doc_type} Item` i , `tab{self.filters.doc_type}` s where s.name = i.parent and i.docstatus = 1 and s.company = %s - and s.{date_field} between %s and %s - """.format( - date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type - ), + and s.{self.date_field} between %s and %s + """, (self.filters.company, self.filters.from_date, self.filters.to_date), as_dict=1, ) @@ -294,7 +285,7 @@ def get_rows_by_group(self): total += amount row["total"] = total - out = [row] + out + out = [row, *out] self.data = out @@ -330,9 +321,7 @@ def get_period_date_ranges(self): from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date) - increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get( - self.filters.range, 1 - ) + increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(self.filters.range, 1) if self.filters.range in ["Monthly", "Quarterly"]: from_date = from_date.replace(day=1) @@ -342,7 +331,7 @@ def get_period_date_ranges(self): from_date = from_date + relativedelta(from_date, weekday=MO(-1)) self.periodic_daterange = [] - for dummy in range(1, 53): + for _dummy in range(1, 53): if self.filters.range == "Weekly": period_end_date = add_days(from_date, 6) else: @@ -370,10 +359,8 @@ def get_groups(self): self.depth_map = frappe._dict() self.group_entries = frappe.db.sql( - """select name, lft, rgt , {parent} as parent - from `tab{tree}` order by lft""".format( - tree=self.filters.tree_type, parent=parent - ), + f"""select name, lft, rgt , {parent} as parent + from `tab{self.filters.tree_type}` order by lft""", as_dict=1, ) @@ -387,12 +374,10 @@ def get_teams(self): self.depth_map = frappe._dict() self.group_entries = frappe.db.sql( - """ select * from (select "Order Types" as name, 0 as lft, + f""" select * from (select "Order Types" as name, 0 as lft, 2 as rgt, '' as parent union select distinct order_type as name, 1 as lft, 1 as rgt, "Order Types" as parent - from `tab{doctype}` where ifnull(order_type, '') != '') as b order by lft, name - """.format( - doctype=self.filters.doc_type - ), + from `tab{self.filters.doc_type}` where ifnull(order_type, '') != '') as b order by lft, name + """, as_dict=1, ) diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py index 720aa41982ab..812c21ed750f 100644 --- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py +++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py @@ -58,7 +58,7 @@ def get_conditions(filters): def get_data(conditions, filters): data = frappe.db.sql( - """ + f""" SELECT so.transaction_date as date, soi.delivery_date as delivery_date, @@ -88,9 +88,7 @@ def get_data(conditions, filters): {conditions} GROUP BY soi.name ORDER BY so.transaction_date ASC, soi.item_code ASC - """.format( - conditions=conditions - ), + """, filters, as_dict=1, ) @@ -164,7 +162,7 @@ def prepare_data(data, so_elapsed_time, filters): if filters.get("group_by_so"): so_name = row["sales_order"] - if not so_name in sales_order_map: + if so_name not in sales_order_map: # create an entry row_copy = copy.deepcopy(row) sales_order_map[so_name] = row_copy diff --git a/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py b/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py index cf9ea219c1b9..844aa86b52e2 100644 --- a/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py +++ b/erpnext/selling/report/sales_partner_commission_summary/sales_partner_commission_summary.py @@ -75,16 +75,14 @@ def get_entries(filters): entries = frappe.db.sql( """ SELECT - name, customer, territory, {0} as posting_date, base_net_total as amount, + name, customer, territory, {} as posting_date, base_net_total as amount, sales_partner, commission_rate, total_commission FROM - `tab{1}` + `tab{}` WHERE - {2} and docstatus = 1 and sales_partner is not null + {} and docstatus = 1 and sales_partner is not null and sales_partner != '' order by name desc, sales_partner - """.format( - date_field, filters.get("doctype"), conditions - ), + """.format(date_field, filters.get("doctype"), conditions), filters, as_dict=1, ) @@ -97,15 +95,15 @@ def get_conditions(filters, date_field): for field in ["company", "customer", "territory"]: if filters.get(field): - conditions += " and {0} = %({1})s".format(field, field) + conditions += f" and {field} = %({field})s" if filters.get("sales_partner"): conditions += " and sales_partner = %(sales_partner)s" if filters.get("from_date"): - conditions += " and {0} >= %(from_date)s".format(date_field) + conditions += f" and {date_field} >= %(from_date)s" if filters.get("to_date"): - conditions += " and {0} <= %(to_date)s".format(date_field) + conditions += f" and {date_field} <= %(to_date)s" return conditions diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py index 42bdf571738f..5046ec52c951 100644 --- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py @@ -94,8 +94,8 @@ def get_columns(filters, period_list, partner_doctype): ] for period in period_list: - target_key = "target_{}".format(period.key) - variance_key = "variance_{}".format(period.key) + target_key = f"target_{period.key}" + variance_key = f"variance_{period.key}" columns.extend( [ @@ -169,9 +169,7 @@ def prepare_data( for d in sales_users_data: key = (d.parent, d.item_group) - dist_data = get_periodwise_distribution_data( - d.distribution_id, period_list, filters.get("period") - ) + dist_data = get_periodwise_distribution_data(d.distribution_id, period_list, filters.get("period")) if key not in rows: rows.setdefault(key, {"total_target": 0, "total_achieved": 0, "total_variance": 0}) @@ -182,8 +180,8 @@ def prepare_data( if p_key not in details: details[p_key] = 0 - target_key = "target_{}".format(p_key) - variance_key = "variance_{}".format(p_key) + target_key = f"target_{p_key}" + variance_key = f"variance_{p_key}" details[target_key] = (d.get(target_qty_amt_field) * dist_data.get(p_key)) / 100 details[variance_key] = 0 details["total_target"] += details[target_key] diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py index f2b6a54a8a6a..bad6c94e9dde 100644 --- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/sales_partner_target_variance_based_on_item_group.py @@ -8,6 +8,4 @@ def execute(filters=None): - data = [] - return get_data_column(filters, "Sales Partner") diff --git a/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py index 2049520eadcd..216adde18fd4 100644 --- a/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py +++ b/erpnext/selling/report/sales_partner_transaction_summary/sales_partner_transaction_summary.py @@ -110,9 +110,7 @@ def get_entries(filters): {cond} and dt.name = dt_item.parent and dt.docstatus = 1 and dt.sales_partner is not null and dt.sales_partner != '' order by dt.name desc, dt.sales_partner - """.format( - date_field=date_field, doctype=filters.get("doctype"), cond=conditions - ), + """.format(date_field=date_field, doctype=filters.get("doctype"), cond=conditions), filters, as_dict=1, ) @@ -125,13 +123,13 @@ def get_conditions(filters, date_field): for field in ["company", "customer", "territory", "sales_partner"]: if filters.get(field): - conditions += " and dt.{0} = %({1})s".format(field, field) + conditions += f" and dt.{field} = %({field})s" if filters.get("from_date"): - conditions += " and dt.{0} >= %(from_date)s".format(date_field) + conditions += f" and dt.{date_field} >= %(from_date)s" if filters.get("to_date"): - conditions += " and dt.{0} <= %(to_date)s".format(date_field) + conditions += f" and dt.{date_field} <= %(to_date)s" if not filters.get("show_return_entries"): conditions += " and dt_item.qty > 0.0" @@ -142,10 +140,7 @@ def get_conditions(filters, date_field): if filters.get("item_group"): lft, rgt = frappe.get_cached_value("Item Group", filters.get("item_group"), ["lft", "rgt"]) - conditions += """ and dt_item.item_group in (select name from - `tabItem Group` where lft >= %s and rgt <= %s)""" % ( - lft, - rgt, - ) + conditions += f""" and dt_item.item_group in (select name from + `tabItem Group` where lft >= {lft} and rgt <= {rgt})""" return conditions diff --git a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py index a8df53080365..16b2d499af29 100644 --- a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py +++ b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py @@ -103,16 +103,15 @@ def get_entries(filters): entries = frappe.db.sql( """ select - dt.name, dt.customer, dt.territory, dt.%s as posting_date,dt.base_net_total as base_net_amount, + dt.name, dt.customer, dt.territory, dt.{} as posting_date,dt.base_net_total as base_net_amount, st.commission_rate,st.sales_person, st.allocated_percentage, st.allocated_amount, st.incentives from - `tab%s` dt, `tabSales Team` st + `tab{}` dt, `tabSales Team` st where - st.parent = dt.name and st.parenttype = %s - and dt.docstatus = 1 %s order by dt.name desc,st.sales_person - """ - % (date_field, filters["doc_type"], "%s", conditions), - tuple([filters["doc_type"]] + values), + st.parent = dt.name and st.parenttype = {} + and dt.docstatus = 1 {} order by dt.name desc,st.sales_person + """.format(date_field, filters["doc_type"], "%s", conditions), + tuple([filters["doc_type"], *values]), as_dict=1, ) @@ -125,18 +124,18 @@ def get_conditions(filters, date_field): for field in ["company", "customer", "territory"]: if filters.get(field): - conditions.append("dt.{0}=%s".format(field)) + conditions.append(f"dt.{field}=%s") values.append(filters[field]) if filters.get("sales_person"): - conditions.append("st.sales_person = '{0}'".format(filters.get("sales_person"))) + conditions.append("st.sales_person = '{}'".format(filters.get("sales_person"))) if filters.get("from_date"): - conditions.append("dt.{0}>=%s".format(date_field)) + conditions.append(f"dt.{date_field}>=%s") values.append(filters["from_date"]) if filters.get("to_date"): - conditions.append("dt.{0}<=%s".format(date_field)) + conditions.append(f"dt.{date_field}<=%s") values.append(filters["to_date"]) return " and ".join(conditions), values 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 847488f6fbf2..f8cde141fe43 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 @@ -156,27 +156,26 @@ def get_entries(filters): entries = frappe.db.sql( """ SELECT - dt.name, dt.customer, dt.territory, dt.%s as posting_date, dt_item.item_code, + dt.name, dt.customer, dt.territory, dt.{} as posting_date, dt_item.item_code, st.sales_person, st.allocated_percentage, dt_item.warehouse, CASE - WHEN dt.status = "Closed" THEN dt_item.%s * dt_item.conversion_factor + WHEN dt.status = "Closed" THEN dt_item.{} * dt_item.conversion_factor ELSE dt_item.stock_qty END as stock_qty, CASE - WHEN dt.status = "Closed" THEN (dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor) + WHEN dt.status = "Closed" THEN (dt_item.base_net_rate * dt_item.{} * dt_item.conversion_factor) ELSE dt_item.base_net_amount END as base_net_amount, CASE - WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor) * st.allocated_percentage/100) + WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.{} * dt_item.conversion_factor) * st.allocated_percentage/100) ELSE dt_item.base_net_amount * st.allocated_percentage/100 END as contribution_amt FROM - `tab%s` dt, `tab%s Item` dt_item, `tabSales Team` st + `tab{}` dt, `tab{} Item` dt_item, `tabSales Team` st WHERE - st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = %s - and dt.docstatus = 1 %s order by st.sales_person, dt.name desc - """ - % ( + st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = {} + and dt.docstatus = 1 {} order by st.sales_person, dt.name desc + """.format( date_field, qty_field, qty_field, @@ -186,7 +185,7 @@ def get_entries(filters): "%s", conditions, ), - tuple([filters["doc_type"]] + values), + tuple([filters["doc_type"], *values]), as_dict=1, ) @@ -199,23 +198,21 @@ def get_conditions(filters, date_field): for field in ["company", "customer", "territory"]: if filters.get(field): - conditions.append("dt.{0}=%s".format(field)) + conditions.append(f"dt.{field}=%s") values.append(filters[field]) if filters.get("sales_person"): lft, rgt = frappe.get_value("Sales Person", filters.get("sales_person"), ["lft", "rgt"]) conditions.append( - "exists(select name from `tabSales Person` where lft >= {0} and rgt <= {1} and name=st.sales_person)".format( - lft, rgt - ) + f"exists(select name from `tabSales Person` where lft >= {lft} and rgt <= {rgt} and name=st.sales_person)" ) if filters.get("from_date"): - conditions.append("dt.{0}>=%s".format(date_field)) + conditions.append(f"dt.{date_field}>=%s") values.append(filters["from_date"]) if filters.get("to_date"): - conditions.append("dt.{0}<=%s".format(date_field)) + conditions.append(f"dt.{date_field}<=%s") values.append(filters["to_date"]) items = get_items(filters) diff --git a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py index eee2d42a7866..527e60e6de38 100644 --- a/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py +++ b/erpnext/selling/report/territory_target_variance_based_on_item_group/territory_target_variance_based_on_item_group.py @@ -8,6 +8,4 @@ def execute(filters=None): - data = [] - return get_data_column(filters, "Territory") diff --git a/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py b/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py index ecb63d890a75..e31b259d7319 100644 --- a/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py +++ b/erpnext/selling/report/territory_wise_sales/territory_wise_sales.py @@ -107,7 +107,7 @@ def get_opportunities(filters): conditions = "" if filters.get("transaction_date"): - conditions = " WHERE transaction_date between {0} and {1}".format( + conditions = " WHERE transaction_date between {} and {}".format( frappe.db.escape(filters["transaction_date"][0]), frappe.db.escape(filters["transaction_date"][1]), ) @@ -120,12 +120,10 @@ def get_opportunities(filters): conditions += " company = %(company)s" return frappe.db.sql( - """ + f""" SELECT name, territory, opportunity_amount - FROM `tabOpportunity` {0} - """.format( - conditions - ), + FROM `tabOpportunity` {conditions} + """, filters, as_dict=1, ) # nosec @@ -141,10 +139,8 @@ def get_quotations(opportunities): """ SELECT `name`,`base_grand_total`, `opportunity` FROM `tabQuotation` - WHERE docstatus=1 AND opportunity in ({0}) - """.format( - ", ".join(["%s"] * len(opportunity_names)) - ), + WHERE docstatus=1 AND opportunity in ({}) + """.format(", ".join(["%s"] * len(opportunity_names))), tuple(opportunity_names), as_dict=1, ) # nosec @@ -160,10 +156,8 @@ def get_sales_orders(quotations): """ SELECT so.`name`, so.`base_grand_total`, soi.prevdoc_docname as quotation FROM `tabSales Order` so, `tabSales Order Item` soi - WHERE so.docstatus=1 AND so.name = soi.parent AND soi.prevdoc_docname in ({0}) - """.format( - ", ".join(["%s"] * len(quotation_names)) - ), + WHERE so.docstatus=1 AND so.name = soi.parent AND soi.prevdoc_docname in ({}) + """.format(", ".join(["%s"] * len(quotation_names))), tuple(quotation_names), as_dict=1, ) # nosec @@ -179,10 +173,8 @@ def get_sales_invoice(sales_orders): """ SELECT si.name, si.base_grand_total, sii.sales_order FROM `tabSales Invoice` si, `tabSales Invoice Item` sii - WHERE si.docstatus=1 AND si.name = sii.parent AND sii.sales_order in ({0}) - """.format( - ", ".join(["%s"] * len(so_names)) - ), + WHERE si.docstatus=1 AND si.name = sii.parent AND sii.sales_order in ({}) + """.format(", ".join(["%s"] * len(so_names))), tuple(so_names), as_dict=1, ) # nosec diff --git a/erpnext/setup/demo.py b/erpnext/setup/demo.py index f48402e175b4..f0253529c781 100644 --- a/erpnext/setup/demo.py +++ b/erpnext/setup/demo.py @@ -150,7 +150,6 @@ def convert_order_to_invoices(): document, filters={"docstatus": 1}, fields=["name", "transaction_date"], limit=6 ) ): - if document == "Purchase Order": invoice = make_purchase_invoice(order.name) elif document == "Sales Order": @@ -217,7 +216,7 @@ def delete_company(company): def read_data_file_using_hooks(doctype): path = os.path.join(os.path.dirname(__file__), "demo_data") - with open(os.path.join(path, doctype + ".json"), "r") as f: + with open(os.path.join(path, doctype + ".json")) as f: data = f.read() return data diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index 5e77c6fa816e..f01c2e2feb86 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -12,7 +12,7 @@ class AuthorizationControl(TransactionBase): def get_appr_user_role(self, det, doctype_name, total, based_on, condition, item, company): amt_list, appr_users, appr_roles = [], [], [] - users, roles = "", "" + _users, _roles = "", "" if det: for x in det: amt_list.append(flt(x[0])) @@ -20,18 +20,20 @@ def get_appr_user_role(self, det, doctype_name, total, based_on, condition, item app_dtl = frappe.db.sql( """select approving_user, approving_role from `tabAuthorization Rule` - where transaction = %s and (value = %s or value > %s) - and docstatus != 2 and based_on = %s and company = %s %s""" - % ("%s", "%s", "%s", "%s", "%s", condition), + where transaction = {} and (value = {} or value > {}) + and docstatus != 2 and based_on = {} and company = {} {}""".format( + "%s", "%s", "%s", "%s", "%s", condition + ), (doctype_name, flt(max_amount), total, based_on, company), ) if not app_dtl: app_dtl = frappe.db.sql( """select approving_user, approving_role from `tabAuthorization Rule` - where transaction = %s and (value = %s or value > %s) and docstatus != 2 - and based_on = %s and ifnull(company,'') = '' %s""" - % ("%s", "%s", "%s", "%s", condition), + where transaction = {} and (value = {} or value > {}) and docstatus != 2 + and based_on = {} and ifnull(company,'') = '' {}""".format( + "%s", "%s", "%s", "%s", condition + ), (doctype_name, flt(max_amount), total, based_on), ) @@ -54,18 +56,20 @@ def validate_auth_rule(self, doctype_name, total, based_on, cond, company, item= add_cond1 += " and master_name = " + frappe.db.escape(cstr(item)) itemwise_exists = frappe.db.sql( """select value from `tabAuthorization Rule` - where transaction = %s and value <= %s - and based_on = %s and company = %s and docstatus != 2 %s %s""" - % ("%s", "%s", "%s", "%s", cond, add_cond1), + where transaction = {} and value <= {} + and based_on = {} and company = {} and docstatus != 2 {} {}""".format( + "%s", "%s", "%s", "%s", cond, add_cond1 + ), (doctype_name, total, based_on, company), ) if not itemwise_exists: itemwise_exists = frappe.db.sql( """select value from `tabAuthorization Rule` - where transaction = %s and value <= %s and based_on = %s - and ifnull(company,'') = '' and docstatus != 2 %s %s""" - % ("%s", "%s", "%s", cond, add_cond1), + where transaction = {} and value <= {} and based_on = {} + and ifnull(company,'') = '' and docstatus != 2 {} {}""".format( + "%s", "%s", "%s", cond, add_cond1 + ), (doctype_name, total, based_on), ) @@ -80,18 +84,18 @@ def validate_auth_rule(self, doctype_name, total, based_on, cond, company, item= appr = frappe.db.sql( """select value from `tabAuthorization Rule` - where transaction = %s and value <= %s and based_on = %s - and company = %s and docstatus != 2 %s %s""" - % ("%s", "%s", "%s", "%s", cond, add_cond2), + where transaction = {} and value <= {} and based_on = {} + and company = {} and docstatus != 2 {} {}""".format("%s", "%s", "%s", "%s", cond, add_cond2), (doctype_name, total, based_on, company), ) if not appr: appr = frappe.db.sql( """select value from `tabAuthorization Rule` - where transaction = %s and value <= %s and based_on = %s - and ifnull(company,'') = '' and docstatus != 2 %s %s""" - % ("%s", "%s", "%s", cond, add_cond2), + where transaction = {} and value <= {} and based_on = {} + and ifnull(company,'') = '' and docstatus != 2 {} {}""".format( + "%s", "%s", "%s", cond, add_cond2 + ), (doctype_name, total, based_on), ) @@ -116,7 +120,7 @@ def bifurcate_based_on_type(self, doctype_name, total, av_dis, based_on, doc_obj customer = doc_obj.customer else: customer = doc_obj.customer_name - add_cond = " and master_name = {}".format(frappe.db.escape(customer)) + add_cond = f" and master_name = {frappe.db.escape(customer)}" if based_on == "Itemwise Discount": if doc_obj: for t in doc_obj.get("items"): @@ -175,11 +179,10 @@ def validate_approving_authority(self, doctype_name, company, total, doc_obj="") for x in frappe.db.sql( """select based_on from `tabAuthorization Rule` - where transaction = %s and system_role IN (%s) and based_on IN (%s) - and (company = %s or ifnull(company,'')='') + where transaction = {} and system_role IN ({}) and based_on IN ({}) + and (company = {} or ifnull(company,'')='') and docstatus != 2 - """ - % ( + """.format( "%s", "'" + "','".join(frappe.get_roles()) + "'", "'" + "','".join(final_based_on) + "'", diff --git a/erpnext/setup/doctype/authorization_rule/authorization_rule.py b/erpnext/setup/doctype/authorization_rule/authorization_rule.py index 44bd826fc6e4..1bf9aa61c332 100644 --- a/erpnext/setup/doctype/authorization_rule/authorization_rule.py +++ b/erpnext/setup/doctype/authorization_rule/authorization_rule.py @@ -48,9 +48,7 @@ def validate_rule(self): "Customerwise Discount", "Itemwise Discount", ]: - frappe.throw( - _("Cannot set authorization on basis of Discount for {0}").format(self.transaction) - ) + frappe.throw(_("Cannot set authorization on basis of Discount for {0}").format(self.transaction)) elif self.based_on == "Average Discount" and flt(self.value) > 100.00: frappe.throw(_("Discount must be less than 100")) elif self.based_on == "Customerwise Discount" and not self.master_name: diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 5ee7dbb4b47e..2477444dab65 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -38,9 +38,8 @@ def check_if_transactions_exist(self): "Supplier Quotation", ]: if frappe.db.sql( - """select name from `tab%s` where company=%s and docstatus=1 - limit 1""" - % (doctype, "%s"), + """select name from `tab{}` where company={} and docstatus=1 + limit 1""".format(doctype, "%s"), self.name, ): exists = True @@ -73,9 +72,7 @@ def validate_abbr(self): if not self.abbr.strip(): frappe.throw(_("Abbreviation is mandatory")) - if frappe.db.sql( - "select abbr from tabCompany where name!=%s and abbr=%s", (self.name, self.abbr) - ): + if frappe.db.sql("select abbr from tabCompany where name!=%s and abbr=%s", (self.name, self.abbr)): frappe.throw(_("Abbreviation already used for another company")) @frappe.whitelist() @@ -99,7 +96,9 @@ def validate_default_accounts(self): for_company = frappe.db.get_value("Account", self.get(account[1]), "company") if for_company != self.name: frappe.throw( - _("Account {0} does not belong to company: {1}").format(self.get(account[1]), self.name) + _("Account {0} does not belong to company: {1}").format( + self.get(account[1]), self.name + ) ) if get_account_currency(self.get(account[1])) != self.default_currency: @@ -111,9 +110,7 @@ def validate_default_accounts(self): def validate_currency(self): if self.is_new(): return - self.previous_default_currency = frappe.get_cached_value( - "Company", self.name, "default_currency" - ) + self.previous_default_currency = frappe.get_cached_value("Company", self.name, "default_currency") if ( self.default_currency and self.previous_default_currency @@ -177,20 +174,19 @@ def create_default_warehouses(self): {"warehouse_name": _("Finished Goods"), "is_group": 0}, {"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"}, ]: - - if not frappe.db.exists( - "Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr) - ): + if not frappe.db.exists("Warehouse", "{} - {}".format(wh_detail["warehouse_name"], self.abbr)): warehouse = frappe.get_doc( { "doctype": "Warehouse", "warehouse_name": wh_detail["warehouse_name"], "is_group": wh_detail["is_group"], "company": self.name, - "parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) + "parent_warehouse": "{} - {}".format(_("All Warehouses"), self.abbr) if not wh_detail["is_group"] else "", - "warehouse_type": wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None, + "warehouse_type": wh_detail["warehouse_type"] + if "warehouse_type" in wh_detail + else None, } ) warehouse.flags.ignore_permissions = True @@ -212,9 +208,7 @@ def create_default_accounts(self): self.db_set( "default_payable_account", - frappe.db.get_value( - "Account", {"company": self.name, "account_type": "Payable", "is_group": 0} - ), + frappe.db.get_value("Account", {"company": self.name, "account_type": "Payable", "is_group": 0}), ) def create_default_departments(self): @@ -341,7 +335,9 @@ def validate_provisional_account_for_non_stock_items(self): and not self.default_provisional_account ): frappe.throw( - _("Set default {0} account for non stock items").format(frappe.bold("Provisional Account")) + _("Set default {0} account for non stock items").format( + frappe.bold("Provisional Account") + ) ) make_property_setter( @@ -356,9 +352,7 @@ def validate_provisional_account_for_non_stock_items(self): def check_country_change(self): frappe.flags.country_change = False - if not self.is_new() and self.country != frappe.get_cached_value( - "Company", self.name, "country" - ): + if not self.is_new() and self.country != frappe.get_cached_value("Company", self.name, "country"): frappe.flags.country_change = True def set_chart_of_accounts(self): @@ -519,14 +513,14 @@ def on_trash(self): ) for doctype in ["Account", "Cost Center", "Budget", "Party Account"]: - frappe.db.sql("delete from `tab{0}` where company = %s".format(doctype), self.name) + frappe.db.sql(f"delete from `tab{doctype}` where company = %s", self.name) if not frappe.db.get_value("Stock Ledger Entry", {"company": self.name}): frappe.db.sql("""delete from `tabWarehouse` where company=%s""", self.name) frappe.defaults.clear_default("company", value=self.name) for doctype in ["Mode of Payment Account", "Item Default"]: - frappe.db.sql("delete from `tab{0}` where company = %s".format(doctype), self.name) + frappe.db.sql(f"delete from `tab{doctype}` where company = %s", self.name) # clear default accounts, warehouses from item warehouses = frappe.db.sql_list("select name from tabWarehouse where company=%s", self.name) @@ -559,7 +553,7 @@ def on_trash(self): frappe.db.sql("delete from tabBOM where company=%s", self.name) for dt in ("BOM Operation", "BOM Item", "BOM Scrap Item", "BOM Explosion Item"): frappe.db.sql( - "delete from `tab%s` where parent in (%s)" "" % (dt, ", ".join(["%s"] * len(boms))), + "delete from `tab{}` where parent in ({})" "".format(dt, ", ".join(["%s"] * len(boms))), tuple(boms), ) @@ -615,7 +609,7 @@ def update_company_current_month_sales(company): current_month_year = formatdate(today(), "MM-yyyy") results = frappe.db.sql( - """ + f""" SELECT SUM(base_grand_total) AS total, DATE_FORMAT(`posting_date`, '%m-%Y') AS month_year @@ -624,12 +618,10 @@ def update_company_current_month_sales(company): WHERE DATE_FORMAT(`posting_date`, '%m-%Y') = '{current_month_year}' AND docstatus = 1 - AND company = {company} + AND company = {frappe.db.escape(company)} GROUP BY month_year - """.format( - current_month_year=current_month_year, company=frappe.db.escape(company) - ), + """, as_dict=True, ) @@ -644,9 +636,7 @@ def update_company_monthly_sales(company): from frappe.utils.goal import get_monthly_results - filter_str = "company = {0} and status != 'Draft' and docstatus=1".format( - frappe.db.escape(company) - ) + filter_str = f"company = {frappe.db.escape(company)} and status != 'Draft' and docstatus=1" month_to_value_dict = get_monthly_results( "Sales Invoice", "base_grand_total", "posting_date", filter_str, "sum" ) @@ -656,9 +646,7 @@ def update_company_monthly_sales(company): def update_transactions_annual_history(company, commit=False): transactions_history = get_all_transactions_annual_history(company) - frappe.db.set_value( - "Company", company, "transactions_annual_history", json.dumps(transactions_history) - ) + frappe.db.set_value("Company", company, "transactions_annual_history", json.dumps(transactions_history)) if commit: frappe.db.commit() @@ -674,21 +662,19 @@ def cache_companies_monthly_sales_history(): @frappe.whitelist() def get_children(doctype, parent=None, company=None, is_root=False): - if parent == None or parent == "All Companies": + if parent is None or parent == "All Companies": parent = "" return frappe.db.sql( - """ + f""" select name as value, is_group as expandable from `tabCompany` comp where - ifnull(parent_company, "")={parent} - """.format( - parent=frappe.db.escape(parent) - ), + ifnull(parent_company, "")={frappe.db.escape(parent)} + """, as_dict=1, ) @@ -764,7 +750,6 @@ def get_all_transactions_annual_history(company): def get_timeline_data(doctype, name): """returns timeline data based on linked records in dashboard""" - out = {} date_to_value_dict = {} history = frappe.get_cached_value("Company", name, "transactions_annual_history") @@ -789,14 +774,13 @@ def get_default_company_address(name, sort_key="is_primary_address", existing_ad out = frappe.db.sql( """ SELECT - addr.name, addr.%s + addr.name, addr.{} FROM `tabAddress` addr, `tabDynamic Link` dl WHERE dl.parent = addr.name and dl.link_doctype = 'Company' and - dl.link_name = %s and ifnull(addr.disabled, 0) = 0 - """ - % (sort_key, "%s"), + dl.link_name = {} and ifnull(addr.disabled, 0) = 0 + """.format(sort_key, "%s"), (name), ) # nosec diff --git a/erpnext/setup/doctype/currency_exchange/currency_exchange.py b/erpnext/setup/doctype/currency_exchange/currency_exchange.py index f9f3b3a7dcb2..8cb34e111530 100644 --- a/erpnext/setup/doctype/currency_exchange/currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/currency_exchange.py @@ -22,7 +22,7 @@ def autoname(self): if cint(self.for_buying) == 1 and cint(self.for_selling) == 0: purpose = "Buying" - self.name = "{0}-{1}-{2}{3}".format( + self.name = "{}-{}-{}{}".format( formatdate(get_datetime_str(self.date), "yyyy-MM-dd"), self.from_currency, self.to_currency, diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py index d4defdf88de6..d8e223fe12bc 100644 --- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py @@ -49,6 +49,7 @@ def save_new_records(test_records): test_exchange_values = {"2015-12-15": "66.999", "2016-01-15": "65.1"} + # Removing API call from get_exchange_rate def patched_requests_get(*args, **kwargs): class PatchResponse: @@ -83,7 +84,7 @@ class TestCurrencyExchange(unittest.TestCase): def clear_cache(self): cache = frappe.cache() for date in test_exchange_values.keys(): - key = "currency_exchange_rate_{0}:{1}:{2}".format(date, "USD", "INR") + key = "currency_exchange_rate_{}:{}:{}".format(date, "USD", "INR") cache.delete(key) def tearDown(self): diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index 246cc195e129..45726621d3ab 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -16,7 +16,7 @@ def validate(self): def on_update(self): self.validate_name_with_customer() - super(CustomerGroup, self).on_update() + super().on_update() self.validate_one_root() def validate_name_with_customer(self): diff --git a/erpnext/setup/doctype/department/department.py b/erpnext/setup/doctype/department/department.py index 1745178574b1..a5d5313715f7 100644 --- a/erpnext/setup/doctype/department/department.py +++ b/erpnext/setup/doctype/department/department.py @@ -26,17 +26,17 @@ def validate(self): def before_rename(self, old, new, merge=False): # renaming consistency with abbreviation - if not frappe.get_cached_value("Company", self.company, "abbr") in new: + if frappe.get_cached_value("Company", self.company, "abbr") not in new: new = get_abbreviated_name(new, self.company) return new def on_update(self): if not (frappe.local.flags.ignore_update_nsm or frappe.flags.in_setup_wizard): - super(Department, self).on_update() + super().on_update() def on_trash(self): - super(Department, self).on_trash() + super().on_trash() delete_events(self.doctype, self.name) @@ -46,7 +46,7 @@ def on_doctype_update(): def get_abbreviated_name(name, company): abbr = frappe.get_cached_value("Company", company, "abbr") - new_name = "{0} - {1}".format(name, abbr) + new_name = f"{name} - {abbr}" return new_name diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 6ed44fff686c..d1f8340a4d6f 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -31,7 +31,7 @@ class EmailDigest(Document): def __init__(self, *args, **kwargs): - super(EmailDigest, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.from_date, self.to_date = self.get_from_to_date() self.set_dates() @@ -46,9 +46,7 @@ def get_users(self): select name, enabled from tabUser where name not in ({}) and user_type != "Website User" - order by enabled desc, name asc""".format( - ", ".join(["%s"] * len(STANDARD_USERS)) - ), + order by enabled desc, name asc""".format(", ".join(["%s"] * len(STANDARD_USERS))), STANDARD_USERS, as_dict=1, ) @@ -151,15 +149,11 @@ def set_style(self, context): context.text_color = "#36414C" context.h1 = "margin-bottom: 30px; margin-top: 40px; font-weight: 400; font-size: 30px;" context.h2 = "margin-bottom: 30px; margin-top: -20px; font-weight: 400; font-size: 20px;" - context.label_css = """display: inline-block; color: {text_muted}; - padding: 3px 7px; margin-right: 7px;""".format( - text_muted=context.text_muted - ) + context.label_css = f"""display: inline-block; color: {context.text_muted}; + padding: 3px 7px; margin-right: 7px;""" context.section_head = "margin-top: 60px; font-size: 16px;" context.line_item = "padding: 5px 0px; margin: 0; border-bottom: 1px solid #d1d8dd;" - context.link_css = "color: {text_color}; text-decoration: none;".format( - text_color=context.text_color - ) + context.link_css = f"color: {context.text_color}; text-decoration: none;" def get_notifications(self): """Get notifications for user""" @@ -182,7 +176,7 @@ def get_calendar_events(self): events = get_events(from_date, to_date) event_count = 0 - for i, e in enumerate(events): + for _i, e in enumerate(events): e.starts_on_label = format_time(e.starts_on) e.ends_on_label = format_time(e.ends_on) if e.ends_on else None e.date = formatdate(e.starts) @@ -298,11 +292,8 @@ def set_accounting_cards(self, context): "new_quotations", "pending_quotations", ): - if self.get(key): - cache_key = "email_digest:card:{0}:{1}:{2}:{3}".format( - self.company, self.frequency, key, self.from_date - ) + cache_key = f"email_digest:card:{self.company}:{self.frequency}:{key}:{self.from_date}" card = cache.get(cache_key) if card: @@ -421,9 +412,7 @@ def get_invoiced_amount(self): return self.get_type_balance("invoiced_amount", "Receivable") def get_expenses_booked(self): - expenses, past_expenses, count = self.get_period_amounts( - self.get_roots("expense"), "expenses_booked" - ) + expenses, past_expenses, count = self.get_period_amounts(self.get_roots("expense"), "expenses_booked") expense_account = frappe.db.get_all( "Account", @@ -559,7 +548,6 @@ def get_purchase_orders_to_bill(self): return {"label": label, "value": value, "count": count} def get_type_balance(self, fieldname, account_type, root_type=None): - if root_type: accounts = [ d.name @@ -645,57 +633,47 @@ def get_roots(self, root_type): ] def get_root_type_accounts(self, root_type): - if not root_type in self._accounts: + if root_type not in self._accounts: self._accounts[root_type] = [ d.name for d in frappe.db.get_all( - "Account", filters={"root_type": root_type.title(), "company": self.company, "is_group": 0} + "Account", + filters={"root_type": root_type.title(), "company": self.company, "is_group": 0}, ) ] return self._accounts[root_type] def get_purchase_order(self): - return self.get_summary_of_doc("Purchase Order", "purchase_order") def get_sales_order(self): - return self.get_summary_of_doc("Sales Order", "sales_order") def get_pending_purchase_orders(self): - return self.get_summary_of_pending("Purchase Order", "pending_purchase_orders", "per_received") def get_pending_sales_orders(self): - return self.get_summary_of_pending("Sales Order", "pending_sales_orders", "per_delivered") def get_sales_invoice(self): - return self.get_summary_of_doc("Sales Invoice", "sales_invoice") def get_purchase_invoice(self): - return self.get_summary_of_doc("Purchase Invoice", "purchase_invoice") def get_new_quotations(self): - return self.get_summary_of_doc("Quotation", "new_quotations") def get_pending_quotations(self): - return self.get_summary_of_pending_quotations("pending_quotations") def get_summary_of_pending(self, doc_type, fieldname, getfield): - value, count, billed_value, delivered_value = frappe.db.sql( """select ifnull(sum(grand_total),0), count(*), - ifnull(sum(grand_total*per_billed/100),0), ifnull(sum(grand_total*{0}/100),0) from `tab{1}` + ifnull(sum(grand_total*per_billed/100),0), ifnull(sum(grand_total*{}/100),0) from `tab{}` where (transaction_date <= %(to_date)s) and status not in ('Closed','Cancelled', 'Completed') - and company = %(company)s """.format( - getfield, doc_type - ), + and company = %(company)s """.format(getfield, doc_type), {"to_date": self.future_to_date, "company": self.company}, )[0] @@ -708,7 +686,6 @@ def get_summary_of_pending(self, doc_type, fieldname, getfield): } def get_summary_of_pending_quotations(self, fieldname): - value, count = frappe.db.sql( """select ifnull(sum(grand_total),0), count(*) from `tabQuotation` where (transaction_date <= %(to_date)s) @@ -741,19 +718,14 @@ def get_summary_of_pending_quotations(self, fieldname): return {"label": label, "value": value, "last_value": last_value, "count": count} def get_summary_of_doc(self, doc_type, fieldname): - date_field = ( "posting_date" if doc_type in ["Sales Invoice", "Purchase Invoice"] else "transaction_date" ) - value = flt( - self.get_total_on(doc_type, self.future_from_date, self.future_to_date)[0].grand_total - ) + value = flt(self.get_total_on(doc_type, self.future_from_date, self.future_to_date)[0].grand_total) count = self.get_total_on(doc_type, self.future_from_date, self.future_to_date)[0].count - last_value = flt( - self.get_total_on(doc_type, self.past_from_date, self.past_to_date)[0].grand_total - ) + last_value = flt(self.get_total_on(doc_type, self.past_from_date, self.past_to_date)[0].grand_total) filters = { date_field: [[">=", self.future_from_date], ["<=", self.future_to_date]], @@ -772,7 +744,6 @@ def get_summary_of_doc(self, doc_type, fieldname): return {"label": label, "value": value, "last_value": last_value, "count": count} def get_total_on(self, doc_type, from_date, to_date): - date_field = ( "posting_date" if doc_type in ["Sales Invoice", "Purchase Invoice"] else "transaction_date" ) @@ -853,20 +824,16 @@ def get_purchase_orders_items_overdue_list(self): "received_qty, qty - received_qty as missing_qty, rate, amount" ) - sql_po = """select {fields} from `tabPurchase Order Item` + sql_po = f"""select {fields_po} from `tabPurchase Order Item` left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and CURRENT_DATE > `tabPurchase Order Item`.schedule_date and received_qty < qty order by `tabPurchase Order Item`.parent DESC, - `tabPurchase Order Item`.schedule_date DESC""".format( - fields=fields_po - ) + `tabPurchase Order Item`.schedule_date DESC""" - sql_poi = """select {fields} from `tabPurchase Order Item` + sql_poi = f"""select {fields_poi} from `tabPurchase Order Item` left join `tabPurchase Order` on `tabPurchase Order`.name = `tabPurchase Order Item`.parent where status<>'Closed' and `tabPurchase Order Item`.docstatus=1 and CURRENT_DATE > `tabPurchase Order Item`.schedule_date - and received_qty < qty order by `tabPurchase Order Item`.idx""".format( - fields=fields_poi - ) + and received_qty < qty order by `tabPurchase Order Item`.idx""" purchase_order_list = frappe.db.sql(sql_po, as_dict=True) purchase_order_items_overdue_list = frappe.db.sql(sql_poi, as_dict=True) diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index a632c90f51ee..9f8f3861cf3a 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -265,16 +265,12 @@ def validate_employee_role(doc, method=None, ignore_emp_check=False): 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) - ) + 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 - ) + _("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]) @@ -290,17 +286,13 @@ def update_user_permissions(doc, method): def get_employee_email(employee_doc): return ( - employee_doc.get("user_id") - or employee_doc.get("personal_email") - or employee_doc.get("company_email") + employee_doc.get("user_id") or employee_doc.get("personal_email") or employee_doc.get("company_email") ) def get_holiday_list_for_employee(employee, raise_exception=True): if employee: - holiday_list, company = frappe.get_cached_value( - "Employee", employee, ["holiday_list", "company"] - ) + holiday_list, company = frappe.get_cached_value("Employee", employee, ["holiday_list", "company"]) else: holiday_list = "" company = frappe.db.get_single_value("Global Defaults", "default_company") @@ -316,9 +308,7 @@ def get_holiday_list_for_employee(employee, raise_exception=True): return holiday_list -def is_holiday( - employee, date=None, raise_exception=True, only_non_weekly=False, with_description=False -): +def is_holiday(employee, date=None, raise_exception=True, only_non_weekly=False, with_description=False): """ Returns True if given Employee has an holiday on the given date :param employee: Employee `name` @@ -428,7 +418,6 @@ def get_employee_emails(employee_list): @frappe.whitelist() def get_children(doctype, parent=None, company=None, is_root=False, is_tree=False): - filters = [["status", "=", "Active"]] if company and company != "All Companies": filters.append(["company", "=", company]) diff --git a/erpnext/setup/doctype/holiday_list/holiday_list.py b/erpnext/setup/doctype/holiday_list/holiday_list.py index 4593cbda5ee7..94ec0b95675e 100644 --- a/erpnext/setup/doctype/holiday_list/holiday_list.py +++ b/erpnext/setup/doctype/holiday_list/holiday_list.py @@ -161,9 +161,7 @@ def is_holiday(holiday_list, date=None): if date is None: date = today() if holiday_list: - return bool( - frappe.db.exists("Holiday", {"parent": holiday_list, "holiday_date": date}, cache=True) - ) + return bool(frappe.db.exists("Holiday", {"parent": holiday_list, "holiday_date": date}, cache=True)) else: return False diff --git a/erpnext/setup/doctype/holiday_list/test_holiday_list.py b/erpnext/setup/doctype/holiday_list/test_holiday_list.py index c0e71f5d2547..21dacc624b66 100644 --- a/erpnext/setup/doctype/holiday_list/test_holiday_list.py +++ b/erpnext/setup/doctype/holiday_list/test_holiday_list.py @@ -112,9 +112,7 @@ def test_localized_country_names(self): frappe.local.lang = lang -def make_holiday_list( - name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None -): +def make_holiday_list(name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None): frappe.delete_doc_if_exists("Holiday List", name, force=1) doc = frappe.get_doc( { diff --git a/erpnext/setup/doctype/incoterm/incoterm.py b/erpnext/setup/doctype/incoterm/incoterm.py index 7e2e622c24bb..6b39a7b2f578 100644 --- a/erpnext/setup/doctype/incoterm/incoterm.py +++ b/erpnext/setup/doctype/incoterm/incoterm.py @@ -14,7 +14,7 @@ def create_incoterms(): import os from csv import DictReader - with open(os.path.join(os.path.dirname(__file__), "incoterms.csv"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "incoterms.csv")) as f: for incoterm in DictReader(f): if frappe.db.exists("Incoterm", incoterm["code"]): continue diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index cc67c696b437..cb43f949000d 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -25,7 +25,7 @@ class ItemGroup(NestedSet, WebsiteGenerator): ) def validate(self): - super(ItemGroup, self).validate() + super().validate() if not self.parent_item_group and not frappe.flags.in_test: if frappe.db.exists("Item Group", _("All Item Groups")): @@ -45,7 +45,7 @@ def check_item_tax(self): frappe.throw( _("{0} entered twice {1} in Item Taxes").format( frappe.bold(d.item_tax_template), - "for tax category {0}".format(frappe.bold(d.tax_category)) if d.tax_category else "", + f"for tax category {frappe.bold(d.tax_category)}" if d.tax_category else "", ) ) else: diff --git a/erpnext/setup/doctype/item_group/test_item_group.py b/erpnext/setup/doctype/item_group/test_item_group.py index 11bc9b92c12e..a579fb703da1 100644 --- a/erpnext/setup/doctype/item_group/test_item_group.py +++ b/erpnext/setup/doctype/item_group/test_item_group.py @@ -124,9 +124,7 @@ def test_move_group_into_root(self): def print_tree(self): import json - print( - json.dumps(frappe.db.sql("select name, lft, rgt from `tabItem Group` order by lft"), indent=1) - ) + print(json.dumps(frappe.db.sql("select name, lft, rgt from `tabItem Group` order by lft"), indent=1)) def test_move_leaf_into_another_group(self): # before move @@ -156,17 +154,13 @@ def test_move_leaf_into_another_group(self): def test_delete_leaf(self): # for checking later - parent_item_group = frappe.db.get_value( - "Item Group", "_Test Item Group B - 3", "parent_item_group" - ) - rgt = frappe.db.get_value("Item Group", parent_item_group, "rgt") + parent_item_group = frappe.db.get_value("Item Group", "_Test Item Group B - 3", "parent_item_group") + frappe.db.get_value("Item Group", parent_item_group, "rgt") ancestors = get_ancestors_of("Item Group", "_Test Item Group B - 3") ancestors = frappe.db.sql( """select name, rgt from `tabItem Group` - where name in ({})""".format( - ", ".join(["%s"] * len(ancestors)) - ), + where name in ({})""".format(", ".join(["%s"] * len(ancestors))), tuple(ancestors), as_dict=True, ) @@ -188,9 +182,7 @@ def test_delete_leaf(self): def test_delete_group(self): # cannot delete group with child, but can delete leaf - self.assertRaises( - NestedSetChildExistsError, frappe.delete_doc, "Item Group", "_Test Item Group B" - ) + self.assertRaises(NestedSetChildExistsError, frappe.delete_doc, "Item Group", "_Test Item Group B") def test_merge_groups(self): frappe.rename_doc("Item Group", "_Test Item Group B", "_Test Item Group C", merge=True) @@ -207,7 +199,6 @@ def test_merge_groups(self): """select name from `tabItem Group` where parent_item_group='_Test Item Group C'""" ): - doc = frappe.get_doc("Item Group", name) doc.parent_item_group = "_Test Item Group B" doc.save() diff --git a/erpnext/setup/doctype/party_type/party_type.py b/erpnext/setup/doctype/party_type/party_type.py index cf7cba845282..e14287237f83 100644 --- a/erpnext/setup/doctype/party_type/party_type.py +++ b/erpnext/setup/doctype/party_type/party_type.py @@ -19,10 +19,8 @@ def get_party_type(doctype, txt, searchfield, start, page_len, filters): cond = "and account_type = '%s'" % account_type return frappe.db.sql( - """select name from `tabParty Type` - where `{key}` LIKE %(txt)s {cond} - order by name limit %(page_len)s offset %(start)s""".format( - key=searchfield, cond=cond - ), + f"""select name from `tabParty Type` + where `{searchfield}` LIKE %(txt)s {cond} + order by name limit %(page_len)s offset %(start)s""", {"txt": "%" + txt + "%", "start": start, "page_len": page_len}, ) diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.py b/erpnext/setup/doctype/sales_partner/sales_partner.py index c3136715fe51..e72773e71326 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.py +++ b/erpnext/setup/doctype/sales_partner/sales_partner.py @@ -25,7 +25,7 @@ def autoname(self): def validate(self): if not self.route: self.route = "partners/" + self.scrub(self.partner_name) - super(SalesPartner, self).validate() + super().validate() if self.partner_website and not self.partner_website.startswith("http"): self.partner_website = "http://" + self.partner_website diff --git a/erpnext/setup/doctype/sales_person/sales_person.py b/erpnext/setup/doctype/sales_person/sales_person.py index 0082c7007587..91a7008fabd9 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.py +++ b/erpnext/setup/doctype/sales_person/sales_person.py @@ -52,7 +52,7 @@ def load_dashboard_info(self): self.set_onload("dashboard_info", info) def on_update(self): - super(SalesPerson, self).on_update() + super().on_update() self.validate_one_root() def get_email_id(self): @@ -78,7 +78,6 @@ def on_doctype_update(): def get_timeline_data(doctype, name): - out = {} out.update( 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 344f6c6a19d8..c795401d3995 100644 --- a/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py +++ b/erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.py @@ -15,12 +15,7 @@ class TermsandConditions(Document): def validate(self): if self.terms: validate_template(self.terms) - if ( - not cint(self.buying) - and not cint(self.selling) - and not cint(self.hr) - and not cint(self.disabled) - ): + if not cint(self.buying) and not cint(self.selling) and not cint(self.hr) and not cint(self.disabled): throw(_("At least one of the Applicable Modules should be selected")) diff --git a/erpnext/setup/doctype/territory/territory.py b/erpnext/setup/doctype/territory/territory.py index 9bb5569de5b6..630dfa168092 100644 --- a/erpnext/setup/doctype/territory/territory.py +++ b/erpnext/setup/doctype/territory/territory.py @@ -20,7 +20,7 @@ def validate(self): frappe.throw(_("Either target qty or target amount is mandatory")) def on_update(self): - super(Territory, self).on_update() + super().on_update() self.validate_one_root() diff --git a/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py index 24a12bac9fef..2f32fe0eee42 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py @@ -25,7 +25,7 @@ def test_doctypes_contain_company_field(self): self.assertTrue(contains_company) def test_no_of_docs_is_correct(self): - for i in range(5): + for _i in range(5): create_task("Dunder Mifflin Paper Co") tdr = create_transaction_deletion_request("Dunder Mifflin Paper Co") tdr.reload() @@ -41,9 +41,7 @@ def test_deletion_is_successful(self): def create_company(company_name): - company = frappe.get_doc( - {"doctype": "Company", "company_name": company_name, "default_currency": "INR"} - ) + company = frappe.get_doc({"doctype": "Company", "company_name": company_name, "default_currency": "INR"}) company.insert(ignore_if_duplicate=True) 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 c32df4ec9d03..3cda609f0432 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py @@ -13,7 +13,7 @@ class TransactionDeletionRecord(Document): def __init__(self, *args, **kwargs): - super(TransactionDeletionRecord, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.batch_size = 5000 # Tasks are listed by their execution order self.task_to_internal_method_map = OrderedDict( @@ -127,7 +127,7 @@ def execute_task(self, task_to_execute: str | None = None): if task := getattr(self, method, None): try: task() - except Exception as err: + except Exception: frappe.db.rollback() traceback = frappe.get_traceback(with_context=True) if traceback: @@ -147,7 +147,7 @@ def populate_doctypes_to_be_ignored_table(self): for doctype in doctypes_to_be_ignored_list: self.append("doctypes_to_be_ignored", {"doctype_name": doctype}) - def validate_running_task_for_doc(self, job_names: list = None): + def validate_running_task_for_doc(self, job_names: list | None = None): # at most only one task should be runnning running_tasks = [] for x in job_names: @@ -196,9 +196,7 @@ def delete_lead_addresses(self): if leads: addresses = frappe.db.sql_list( """select parent from `tabDynamic Link` where link_name - in ({leads})""".format( - leads=",".join(leads) - ) + in ({leads})""".format(leads=",".join(leads)) ) if addresses: @@ -208,16 +206,12 @@ def delete_lead_addresses(self): """delete from `tabAddress` where name in ({addresses}) and name not in (select distinct dl1.parent from `tabDynamic Link` dl1 inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent - and dl1.link_doctype<>dl2.link_doctype)""".format( - addresses=",".join(addresses) - ) + and dl1.link_doctype<>dl2.link_doctype)""".format(addresses=",".join(addresses)) ) frappe.db.sql( """delete from `tabDynamic Link` where link_doctype='Lead' - and parenttype='Address' and link_name in ({leads})""".format( - leads=",".join(leads) - ) + and parenttype='Address' and link_name in ({leads})""".format(leads=",".join(leads)) ) frappe.db.sql( @@ -259,9 +253,9 @@ def delete_company_transactions(self): self.validate_doc_status() if not self.delete_transactions: doctypes_to_be_ignored_list = self.get_doctypes_to_be_ignored_list() - docfields = self.get_doctypes_with_company_field(doctypes_to_be_ignored_list) + self.get_doctypes_with_company_field(doctypes_to_be_ignored_list) - tables = self.get_all_child_doctypes() + self.get_all_child_doctypes() for docfield in self.doctypes: if docfield.doctype_name != self.doctype and not docfield.done: no_of_docs = self.get_number_of_docs_linked_with_specified_company( @@ -269,7 +263,9 @@ def delete_company_transactions(self): ) if no_of_docs > 0: reference_docs = frappe.get_all( - docfield.doctype_name, filters={docfield.docfield_name: self.company}, limit=self.batch_size + docfield.doctype_name, + filters={docfield.docfield_name: self.company}, + limit=self.batch_size, ) reference_doc_names = [r.name for r in reference_docs] @@ -278,7 +274,9 @@ def delete_company_transactions(self): self.delete_comments(docfield.doctype_name, reference_doc_names) self.unlink_attachments(docfield.doctype_name, reference_doc_names) self.delete_child_tables(docfield.doctype_name, reference_doc_names) - self.delete_docs_linked_with_specified_company(docfield.doctype_name, reference_doc_names) + self.delete_docs_linked_with_specified_company( + docfield.doctype_name, reference_doc_names + ) processed = int(docfield.no_of_docs) + len(reference_doc_names) frappe.db.set_value(docfield.doctype, docfield.name, "no_of_docs", processed) else: @@ -355,10 +353,8 @@ def update_naming_series(self, naming_series, doctype_name): else: prefix, hashes = naming_series.rsplit("{", 1) last = frappe.db.sql( - """select max(name) from `tab{0}` - where name like %s""".format( - doctype_name - ), + f"""select max(name) from `tab{doctype_name}` + where name like %s""", prefix + "%", ) if last and last[0][0]: diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index d217bfa52198..2e26117ef334 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -135,7 +135,6 @@ def create_default_success_action(): def create_default_energy_point_rules(): - for rule in get_default_energy_point_rules(): # check if any rule for ref. doctype exists rule_exists = frappe.db.exists( @@ -182,7 +181,7 @@ def add_standard_navbar_items(): for item in erpnext_navbar_items: current_labels = [item.get("item_label") for item in current_navbar_items] - if not item.get("item_label") in current_labels: + if item.get("item_label") not in current_labels: navbar_settings.append("help_dropdown", item) for item in current_navbar_items: diff --git a/erpnext/setup/setup_wizard/operations/defaults_setup.py b/erpnext/setup/setup_wizard/operations/defaults_setup.py index eed8f73cb48f..daceafa94b63 100644 --- a/erpnext/setup/setup_wizard/operations/defaults_setup.py +++ b/erpnext/setup/setup_wizard/operations/defaults_setup.py @@ -30,9 +30,7 @@ def set_default_settings(args): stock_settings = frappe.get_doc("Stock Settings") stock_settings.item_naming_by = "Item Code" stock_settings.valuation_method = "FIFO" - stock_settings.default_warehouse = frappe.db.get_value( - "Warehouse", {"warehouse_name": _("Stores")} - ) + stock_settings.default_warehouse = frappe.db.get_value("Warehouse", {"warehouse_name": _("Stores")}) stock_settings.stock_uom = _("Nos") stock_settings.auto_indent = 1 stock_settings.auto_insert_price_list_rate_if_missing = 1 diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index 081a51573e02..0fe2b56a9440 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -276,9 +276,7 @@ def install(country=None): records += [{"doctype": doctype, title_field: title} for title in read_lines(filename)] base_path = frappe.get_app_path("erpnext", "stock", "doctype") - response = frappe.read_file( - os.path.join(base_path, "delivery_trip/dispatch_notification_template.html") - ) + response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html")) records += [ { @@ -478,9 +476,7 @@ def update_stock_settings(): stock_settings = frappe.get_doc("Stock Settings") stock_settings.item_naming_by = "Item Code" stock_settings.valuation_method = "FIFO" - stock_settings.default_warehouse = frappe.db.get_value( - "Warehouse", {"warehouse_name": _("Stores")} - ) + stock_settings.default_warehouse = frappe.db.get_value("Warehouse", {"warehouse_name": _("Stores")}) stock_settings.stock_uom = _("Nos") stock_settings.auto_indent = 1 stock_settings.auto_insert_price_list_rate_if_missing = 1 diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py index 49ba78c63a42..14fcb800ae75 100644 --- a/erpnext/setup/setup_wizard/operations/taxes_setup.py +++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py @@ -2,8 +2,8 @@ # License: GNU General Public License v3. See license.txt -import os import json +import os import frappe from frappe import _ @@ -14,7 +14,7 @@ def setup_taxes_and_charges(company_name: str, country: str): frappe.throw(_("Company {} does not exist yet. Taxes setup aborted.").format(company_name)) file_path = os.path.join(os.path.dirname(__file__), "..", "data", "country_wise_tax.json") - with open(file_path, "r") as json_file: + with open(file_path) as json_file: tax_data = json.load(json_file) country_wise_tax = tax_data.get(country) @@ -54,7 +54,12 @@ def simple_to_detailed(templates): { "title": title, "taxes": [ - {"tax_type": {"account_name": data.get("account_name"), "tax_rate": data.get("tax_rate")}} + { + "tax_type": { + "account_name": data.get("account_name"), + "tax_rate": data.get("tax_rate"), + } + } ], } for title, data in templates.items() @@ -110,11 +115,9 @@ def update_regional_tax_settings(country, company): path = frappe.get_app_path("erpnext", "regional", frappe.scrub(country)) if os.path.exists(path.encode("utf-8")): try: - module_name = "erpnext.regional.{0}.setup.update_regional_tax_settings".format( - frappe.scrub(country) - ) + module_name = f"erpnext.regional.{frappe.scrub(country)}.setup.update_regional_tax_settings" frappe.get_attr(module_name)(country, company) - except Exception as e: + except Exception: # Log error and ignore if failed to setup regional tax settings frappe.log_error("Unable to setup regional tax settings") pass @@ -140,7 +143,7 @@ def make_taxes_and_charges_template(company_name, doctype, template): # if account_head is a dict, search or create the account and get it's name if isinstance(account_data, dict): - tax_row_defaults["description"] = "{0} @ {1}".format( + tax_row_defaults["description"] = "{} @ {}".format( account_data.get("account_name"), account_data.get("tax_rate") ) tax_row_defaults["rate"] = account_data.get("tax_rate") diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index bab57fe267ab..705fb1f2fcfe 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -5,7 +5,7 @@ from frappe import _ from frappe.utils import add_days, flt, get_datetime_str, nowdate from frappe.utils.data import now_datetime -from frappe.utils.nestedset import get_ancestors_of, get_root_of # noqa +from frappe.utils.nestedset import get_root_of from erpnext import get_default_company @@ -81,14 +81,12 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No if entries: return flt(entries[0].exchange_rate) - if frappe.get_cached_value( - "Currency Exchange Settings", "Currency Exchange Settings", "disabled" - ): + if frappe.get_cached_value("Currency Exchange Settings", "Currency Exchange Settings", "disabled"): return 0.00 try: cache = frappe.cache() - key = "currency_exchange_rate_{0}:{1}:{2}".format(transaction_date, from_currency, to_currency) + key = f"currency_exchange_rate_{transaction_date}:{from_currency}:{to_currency}" value = cache.get(key) if not value: diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index bc4b6141bf06..6d101b7e6eca 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -15,9 +15,7 @@ def boot_session(bootinfo): update_page_info(bootinfo) bootinfo.sysdefaults.territory = frappe.db.get_single_value("Selling Settings", "territory") - bootinfo.sysdefaults.customer_group = frappe.db.get_single_value( - "Selling Settings", "customer_group" - ) + bootinfo.sysdefaults.customer_group = frappe.db.get_single_value("Selling Settings", "customer_group") bootinfo.sysdefaults.allow_stale = cint( frappe.db.get_single_value("Accounts Settings", "allow_stale") ) @@ -30,9 +28,7 @@ def boot_session(bootinfo): ) bootinfo.sysdefaults.allow_sales_order_creation_for_expired_quotation = cint( - frappe.db.get_single_value( - "Selling Settings", "allow_sales_order_creation_for_expired_quotation" - ) + frappe.db.get_single_value("Selling Settings", "allow_sales_order_creation_for_expired_quotation") ) # if no company, show a dialog box to create a new company @@ -56,9 +52,7 @@ def boot_session(bootinfo): update={"doctype": ":Company"}, ) - party_account_types = frappe.db.sql( - """ select name, ifnull(account_type, '') from `tabParty Type`""" - ) + party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""") bootinfo.party_account_types = frappe._dict(party_account_types) diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index 5a60d2ff967f..06f61fd961e6 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -93,7 +93,7 @@ def get_all_items(date_range, company, field, limit=None): select_field = "sum(actual_qty)" if field == "available_stock_qty" else "sum(stock_value)" results = frappe.db.get_all( "Bin", - fields=["item_code as name", "{0} as value".format(select_field)], + fields=["item_code as name", f"{select_field} as value"], group_by="item_code", order_by="value desc", limit=limit, @@ -224,9 +224,7 @@ def get_date_condition(date_range, field): if date_range: date_range = frappe.parse_json(date_range) from_date, to_date = date_range - date_condition = "and {0} between {1} and {2}".format( - field, frappe.db.escape(from_date), frappe.db.escape(to_date) - ) + date_condition = f"and {field} between {frappe.db.escape(from_date)} and {frappe.db.escape(to_date)}" return date_condition diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index 45bf012be85a..242bdcf8b550 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -17,9 +17,9 @@ def get_warehouse_account_map(company=None): - company_warehouse_account_map = company and frappe.flags.setdefault( - "warehouse_account_map", {} - ).get(company) + company_warehouse_account_map = company and frappe.flags.setdefault("warehouse_account_map", {}).get( + company + ) warehouse_account_map = frappe.flags.warehouse_account_map if not warehouse_account_map or not company_warehouse_account_map or frappe.flags.in_test: diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py index d488150eef3b..cbc4fc76ecfe 100644 --- a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py @@ -27,9 +27,7 @@ def get( if filters and filters.get("company"): warehouse_filters.append(["company", "=", filters.get("company")]) - warehouses = frappe.get_list( - "Warehouse", pluck="name", filters=warehouse_filters, order_by="name" - ) + warehouses = frappe.get_list("Warehouse", pluck="name", filters=warehouse_filters, order_by="name") warehouses = frappe.get_list( "Bin", diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index f377f94a8cf8..6ddc2abbc73b 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -165,9 +165,7 @@ def get_name_from_naming_series(self): @frappe.whitelist() -def get_batch_qty( - batch_no=None, warehouse=None, item_code=None, posting_date=None, posting_time=None -): +def get_batch_qty(batch_no=None, warehouse=None, item_code=None, posting_date=None, posting_time=None): """Returns batch actual qty if warehouse is passed, or returns dict of qty by warehouse if warehouse is None @@ -221,9 +219,7 @@ def get_batch_qty( def get_batches_by_oldest(item_code, warehouse): """Returns the oldest batch and qty for the given item_code and warehouse""" batches = get_batch_qty(item_code=item_code, warehouse=warehouse) - batches_dates = [ - [batch, frappe.get_value("Batch", batch.batch_no, "expiry_date")] for batch in batches - ] + batches_dates = [[batch, frappe.get_value("Batch", batch.batch_no, "expiry_date")] for batch in batches] batches_dates.sort(key=lambda tup: tup[1]) return batches_dates diff --git a/erpnext/stock/doctype/batch/test_batch.py b/erpnext/stock/doctype/batch/test_batch.py index 271e2e029847..51a5dac4d4b2 100644 --- a/erpnext/stock/doctype/batch/test_batch.py +++ b/erpnext/stock/doctype/batch/test_batch.py @@ -81,9 +81,7 @@ def test_stock_entry_incoming(self): stock_entry.submit() self.assertTrue(stock_entry.items[0].batch_no) - self.assertEqual( - get_batch_qty(stock_entry.items[0].batch_no, stock_entry.items[0].t_warehouse), 90 - ) + self.assertEqual(get_batch_qty(stock_entry.items[0].batch_no, stock_entry.items[0].t_warehouse), 90) def test_delivery_note(self): """Test automatic batch selection for outgoing items""" @@ -159,9 +157,7 @@ def test_batch_split(self): receipt = self.test_purchase_receipt() from erpnext.stock.doctype.batch.batch import split_batch - new_batch = split_batch( - receipt.items[0].batch_no, "ITEM-BATCH-1", receipt.items[0].warehouse, 22 - ) + new_batch = split_batch(receipt.items[0].batch_no, "ITEM-BATCH-1", receipt.items[0].warehouse, 22) self.assertEqual(get_batch_qty(receipt.items[0].batch_no, receipt.items[0].warehouse), 78) self.assertEqual(get_batch_qty(new_batch, receipt.items[0].warehouse), 22) @@ -359,9 +355,7 @@ def test_moving_batch_valuation_rates(self): self.make_batch_item(item_code) def assertValuation(expected): - actual = get_valuation_rate( - item_code, warehouse, "voucher_type", "voucher_no", batch_no=batch_no - ) + actual = get_valuation_rate(item_code, warehouse, "voucher_type", "voucher_no", batch_no=batch_no) self.assertAlmostEqual(actual, expected) se = make_stock_entry(item_code=item_code, qty=100, rate=10, target=warehouse) diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index bd6d7241c2b1..75753c8b0f5e 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -58,9 +58,7 @@ def update_reserved_qty_for_for_sub_assembly(self): get_reserved_qty_for_sub_assembly, ) - reserved_qty_for_production_plan = get_reserved_qty_for_sub_assembly( - self.item_code, self.warehouse - ) + reserved_qty_for_production_plan = get_reserved_qty_for_sub_assembly(self.item_code, self.warehouse) if reserved_qty_for_production_plan is None and not self.reserved_qty_for_production_plan: return @@ -81,9 +79,7 @@ def update_reserved_qty_for_production(self): in open work orders""" from erpnext.manufacturing.doctype.work_order.work_order import get_reserved_qty_for_production - self.reserved_qty_for_production = get_reserved_qty_for_production( - self.item_code, self.warehouse - ) + self.reserved_qty_for_production = get_reserved_qty_for_production(self.item_code, self.warehouse) self.db_set( "reserved_qty_for_production", flt(self.reserved_qty_for_production), update_modified=True @@ -131,9 +127,7 @@ def update_reserved_qty_for_sub_contracting(self, subcontract_doctype="Subcontra se_item = frappe.qb.DocType("Stock Entry Detail") if frappe.db.field_exists("Stock Entry", "is_return"): - qty_field = ( - Case().when(se.is_return == 1, se_item.transfer_qty * -1).else_(se_item.transfer_qty) - ) + qty_field = Case().when(se.is_return == 1, se_item.transfer_qty * -1).else_(se_item.transfer_qty) else: qty_field = se_item.transfer_qty diff --git a/erpnext/stock/doctype/bin/test_bin.py b/erpnext/stock/doctype/bin/test_bin.py index b79dee81e215..e4f5565cd751 100644 --- a/erpnext/stock/doctype/bin/test_bin.py +++ b/erpnext/stock/doctype/bin/test_bin.py @@ -31,4 +31,4 @@ def test_concurrent_inserts(self): def test_index_exists(self): indexes = frappe.db.sql("show index from tabBin where Non_unique = 0", as_dict=1) if not any(index.get("Key_name") == "unique_item_warehouse" for index in indexes): - self.fail(f"Expected unique index on item-warehouse") + self.fail("Expected unique index on item-warehouse") 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 c762ad68adc9..70aa57f4c12a 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py @@ -126,6 +126,6 @@ def prepare_closing_stock_balance(name): try: doc.create_closing_stock_balance_entries() doc.db_set("status", "Completed") - except Exception as e: + except Exception: doc.db_set("status", "Failed") doc.log_error(title="Closing Stock Balance Failed") diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 88552d8de083..9ff22d384e7c 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -20,7 +20,7 @@ class DeliveryNote(SellingController): def __init__(self, *args, **kwargs): - super(DeliveryNote, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "source_dt": "Delivery Note Item", @@ -108,7 +108,7 @@ def toggle_print_hide(meta, fieldname): for f in fieldname: toggle_print_hide(self.meta if key == "parent" else item_meta, f) - super(DeliveryNote, self).before_print(settings) + super().before_print(settings) def set_actual_qty(self): for d in self.get("items"): @@ -129,7 +129,7 @@ def so_required(self): def validate(self): self.validate_posting_time() - super(DeliveryNote, self).validate() + super().validate() self.validate_references() self.set_status() self.so_required() @@ -159,11 +159,16 @@ def validate(self): self.reset_default_field_value("set_warehouse", "items", "warehouse") def validate_with_previous_doc(self): - super(DeliveryNote, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Sales Order": { "ref_dn_field": "against_sales_order", - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]], + "compare_fields": [ + ["customer", "="], + ["company", "="], + ["project", "="], + ["currency", "="], + ], }, "Sales Order Item": { "ref_dn_field": "so_detail", @@ -173,7 +178,12 @@ def validate_with_previous_doc(self): }, "Sales Invoice": { "ref_dn_field": "against_sales_invoice", - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]], + "compare_fields": [ + ["customer", "="], + ["company", "="], + ["project", "="], + ["currency", "="], + ], }, "Sales Invoice Item": { "ref_dn_field": "si_detail", @@ -263,7 +273,7 @@ def validate_proj_cust(self): ) def validate_warehouse(self): - super(DeliveryNote, self).validate_warehouse() + super().validate_warehouse() for d in self.get_item_list(): if not d["warehouse"] and frappe.get_cached_value("Item", d["item_code"], "is_stock_item") == 1: @@ -311,7 +321,7 @@ def on_submit(self): self.repost_future_sle_and_gle() def on_cancel(self): - super(DeliveryNote, self).on_cancel() + super().on_cancel() self.check_sales_order_on_hold_or_close("against_sales_order") self.check_next_docstatus() @@ -851,7 +861,7 @@ def postprocess(source, target): "User", frappe.session.user, ["email", "full_name", "phone", "mobile_no"], as_dict=1 ) target.pickup_contact_email = user.email - pickup_contact_display = "{}".format(user.full_name) + pickup_contact_display = f"{user.full_name}" if user: if user.email: pickup_contact_display += "
    " + user.email @@ -867,7 +877,7 @@ def postprocess(source, target): contact = frappe.db.get_value( "Contact", source.contact_person, ["email_id", "phone", "mobile_no"], as_dict=1 ) - delivery_contact_display = "{}".format(source.contact_display) + delivery_contact_display = f"{source.contact_display}" if contact: if contact.email_id: delivery_contact_display += "
    " + contact.email_id @@ -1043,8 +1053,7 @@ def update_item(source, target, source_parent): "postprocess": update_details, "field_no_map": ["taxes_and_charges", "set_warehouse"], }, - doctype - + " Item": { + doctype + " Item": { "doctype": target_doctype + " Item", "field_map": { source_document_warehouse_field: target_document_warehouse_field, diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 6e735ea67b77..e9b07e76b2de 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -54,7 +54,7 @@ def test_over_billing_against_dn(self): self.assertRaises(frappe.ValidationError, frappe.get_doc(si).insert) def test_delivery_note_no_gl_entry(self): - company = frappe.db.get_value("Warehouse", "_Test Warehouse - _TC", "company") + frappe.db.get_value("Warehouse", "_Test Warehouse - _TC", "company") make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100) stock_queue = json.loads( @@ -71,16 +71,14 @@ def test_delivery_note_no_gl_entry(self): dn = create_delivery_note() - sle = frappe.get_doc( - "Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name} - ) + sle = frappe.get_doc("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name}) self.assertEqual(sle.stock_value_difference, flt(-1 * stock_queue[0][1], 2)) self.assertFalse(get_gl_entries("Delivery Note", dn.name)) def test_delivery_note_gl_entry_packing_item(self): - company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company") + frappe.db.get_value("Warehouse", "Stores - TCP1", "company") make_stock_entry(item_code="_Test Item", target="Stores - TCP1", qty=10, basic_rate=100) make_stock_entry( @@ -127,7 +125,7 @@ def test_delivery_note_gl_entry_packing_item(self): stock_in_hand_account: [0.0, stock_value_diff], "Cost of Goods Sold - TCP1": [stock_value_diff, 0.0], } - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) # check stock in hand balance @@ -159,9 +157,7 @@ def test_serialized_partial_sales_invoice(self): serial_no = get_serial_nos(se.get("items")[0].serial_no) serial_no = "\n".join(serial_no) - dn = create_delivery_note( - item_code="_Test Serialized Item With Series", qty=2, serial_no=serial_no - ) + dn = create_delivery_note(item_code="_Test Serialized Item With Series", qty=2, serial_no=serial_no) si = make_sales_invoice(dn.name) si.items[0].qty = 1 @@ -694,7 +690,7 @@ def test_delivery_of_bundled_items_to_target_warehouse(self): "Stock In Hand - TCP1": [0.0, stock_value_difference], target_warehouse: [stock_value_difference, 0.0], } - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) # tear down @@ -902,7 +898,7 @@ def test_delivery_note_with_cost_center(self): "Cost of Goods Sold - TCP1": {"cost_center": cost_center}, stock_in_hand_account: {"cost_center": cost_center}, } - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) def test_delivery_note_cost_center_with_balance_sheet_account(self): @@ -931,7 +927,7 @@ def test_delivery_note_cost_center_with_balance_sheet_account(self): "Cost of Goods Sold - TCP1": {"cost_center": cost_center}, stock_in_hand_account: {"cost_center": cost_center}, } - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) def test_make_sales_invoice_from_dn_for_returned_qty(self): @@ -997,9 +993,7 @@ def test_delivery_note_bundle_with_batched_item(self): }, ) make_product_bundle(parent=batched_bundle.name, items=[batched_item.name]) - make_stock_entry( - item_code=batched_item.name, target="_Test Warehouse - _TC", qty=10, basic_rate=42 - ) + make_stock_entry(item_code=batched_item.name, target="_Test Warehouse - _TC", qty=10, basic_rate=42) try: dn = create_delivery_note(item_code=batched_bundle.name, qty=1) @@ -1008,9 +1002,7 @@ def test_delivery_note_bundle_with_batched_item(self): self.fail("Batch numbers not getting added to bundled items in DN.") raise e - self.assertTrue( - "TESTBATCH" in dn.packed_items[0].batch_no, "Batch number not added in packed item" - ) + self.assertTrue("TESTBATCH" in dn.packed_items[0].batch_no, "Batch number not added in packed item") def test_payment_terms_are_fetched_when_creating_sales_invoice(self): from erpnext.accounts.doctype.payment_entry.test_payment_entry import ( @@ -1185,9 +1177,7 @@ def test_internal_transfer_precision_gle(self): warehouse=warehouse, target_warehouse=target, ) - self.assertFalse( - frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype}) - ) + self.assertFalse(frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype})) def test_batch_expiry_for_delivery_note(self): from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt @@ -1262,11 +1252,9 @@ def test_packed_items_for_return_delivery_note(self): ).name # Step - 2: Inward Stock - se1 = make_stock_entry(item_code=batch_item, target="_Test Warehouse - _TC", qty=3) + make_stock_entry(item_code=batch_item, target="_Test Warehouse - _TC", qty=3) serial_nos = ( - make_stock_entry(item_code=serial_item, target="_Test Warehouse - _TC", qty=3) - .items[0] - .serial_no + make_stock_entry(item_code=serial_item, target="_Test Warehouse - _TC", qty=3).items[0].serial_no ) # Step - 3: Create a Product Bundle @@ -1353,9 +1341,7 @@ def test_sales_return_valuation_for_moving_average(self): basic_rate=100.0, posting_date=add_days(nowdate(), -5), ) - dn = create_delivery_note( - item_code=item_code, qty=5, rate=500, posting_date=add_days(nowdate(), -4) - ) + dn = create_delivery_note(item_code=item_code, qty=5, rate=500, posting_date=add_days(nowdate(), -4)) self.assertEqual(dn.items[0].incoming_rate, 100.0) make_stock_entry( diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py index c531a8769c08..a81dffddfb37 100644 --- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py @@ -13,7 +13,7 @@ class DeliveryTrip(Document): def __init__(self, *args, **kwargs): - super(DeliveryTrip, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Google Maps returns distances in meters by default self.default_distance_uom = ( @@ -67,9 +67,7 @@ def update_delivery_notes(self, delete=False): delete (bool, optional): Defaults to `False`. `True` if driver details need to be emptied, else `False`. """ - delivery_notes = list( - set(stop.delivery_note for stop in self.delivery_stops if stop.delivery_note) - ) + delivery_notes = list(set(stop.delivery_note for stop in self.delivery_stops if stop.delivery_note)) update_fields = { "driver": self.driver, @@ -315,14 +313,11 @@ def get_contact_display(contact): "Contact", contact, ["first_name", "last_name", "phone", "mobile_no"], as_dict=1 ) - contact_info.html = ( - """ %(first_name)s %(last_name)s
    %(phone)s
    %(mobile_no)s""" - % { - "first_name": contact_info.first_name, - "last_name": contact_info.last_name or "", - "phone": contact_info.phone or "", - "mobile_no": contact_info.mobile_no or "", - } + contact_info.html = """ {first_name} {last_name}
    {phone}
    {mobile_no}""".format( + first_name=contact_info.first_name, + last_name=contact_info.last_name or "", + phone=contact_info.phone or "", + mobile_no=contact_info.mobile_no or "", ) return contact_info.html diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py index 9b8b46e6e0ad..09f5b2c2c89b 100644 --- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py +++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.tests.utils import FrappeTestCase diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index a7ead064c97a..5fe5042ffd65 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -360,9 +360,7 @@ def delete_dimension(dimension): @frappe.whitelist() def get_parent_fields(child_doctype, dimension_name): - parent_doctypes = frappe.get_all( - "DocField", fields=["parent"], filters={"options": child_doctype} - ) + parent_doctypes = frappe.get_all("DocField", fields=["parent"], filters={"options": child_doctype}) fields = [] diff --git a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py index 59389c7d7df6..57b37801cb56 100644 --- a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py @@ -210,9 +210,7 @@ def test_check_standard_dimensions(self): ) self.assertFalse( - frappe.db.get_value( - "Custom Field", {"fieldname": "project", "dt": "Stock Ledger Entry"}, "name" - ) + frappe.db.get_value("Custom Field", {"fieldname": "project", "dt": "Stock Ledger Entry"}, "name") ) def test_check_mandatory_dimensions(self): @@ -296,9 +294,7 @@ def test_for_purchase_sales_and_stock_transaction(self): se_doc.save() se_doc.submit() - entries = get_voucher_sl_entries( - se_doc.name, ["warehouse", "store", "incoming_rate", "actual_qty"] - ) + entries = get_voucher_sl_entries(se_doc.name, ["warehouse", "store", "incoming_rate", "actual_qty"]) for entry in entries: self.assertEqual(entry.warehouse, warehouse) @@ -488,7 +484,14 @@ def create_store_dimension(): "autoname": "field:store_name", "fields": [{"label": "Store Name", "fieldname": "store_name", "fieldtype": "Data"}], "permissions": [ - {"role": "System Manager", "permlevel": 0, "read": 1, "write": 1, "create": 1, "delete": 1} + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } ], } ).insert(ignore_permissions=True) @@ -510,7 +513,14 @@ def prepare_test_data(): "autoname": "field:shelf_name", "fields": [{"label": "Shelf Name", "fieldname": "shelf_name", "fieldtype": "Data"}], "permissions": [ - {"role": "System Manager", "permlevel": 0, "read": 1, "write": 1, "create": 1, "delete": 1} + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } ], } ).insert(ignore_permissions=True) @@ -532,7 +542,14 @@ def prepare_test_data(): "autoname": "field:rack_name", "fields": [{"label": "Rack Name", "fieldname": "rack_name", "fieldtype": "Data"}], "permissions": [ - {"role": "System Manager", "permlevel": 0, "read": 1, "write": 1, "create": 1, "delete": 1} + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } ], } ).insert(ignore_permissions=True) @@ -554,7 +571,14 @@ def prepare_test_data(): "autoname": "field:pallet_name", "fields": [{"label": "Pallet Name", "fieldname": "pallet_name", "fieldtype": "Data"}], "permissions": [ - {"role": "System Manager", "permlevel": 0, "read": 1, "write": 1, "create": 1, "delete": 1} + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } ], } ).insert(ignore_permissions=True) @@ -570,7 +594,14 @@ def prepare_test_data(): "autoname": "field:site_name", "fields": [{"label": "Site Name", "fieldname": "site_name", "fieldtype": "Data"}], "permissions": [ - {"role": "System Manager", "permlevel": 0, "read": 1, "write": 1, "create": 1, "delete": 1} + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } ], } ).insert(ignore_permissions=True) @@ -623,9 +654,7 @@ def prepare_data_for_internal_transfer(): to_warehouse = create_warehouse("_Test Internal Warehouse GIT A", company=company) - pr_doc = make_purchase_receipt( - company=company, warehouse=warehouse, qty=10, rate=100, do_not_submit=True - ) + pr_doc = make_purchase_receipt(company=company, warehouse=warehouse, qty=10, rate=100, do_not_submit=True) pr_doc.items[0].store = "Inter Transfer Store 1" pr_doc.submit() @@ -651,9 +680,7 @@ def prepare_data_for_internal_transfer(): expense_account = frappe.db.get_value( "Company", company, "stock_adjustment_account" - ) or frappe.db.get_value( - "Account", {"company": company, "account_type": "Expense Account"}, "name" - ) + ) or frappe.db.get_value("Account", {"company": company, "account_type": "Expense Account"}, "name") return frappe._dict( { diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index ac1b3f278486..b2b06e05871a 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -3,7 +3,6 @@ import copy import json -from typing import Dict, List, Optional import frappe from frappe import _ @@ -300,9 +299,9 @@ def validate_conversion_factor(self): for d in self.get("uoms"): if cstr(d.uom) in check_list: frappe.throw( - _("Unit of Measure {0} has been entered more than once in Conversion Factor Table").format( - d.uom - ) + _( + "Unit of Measure {0} has been entered more than once in Conversion Factor Table" + ).format(d.uom) ) else: check_list.append(cstr(d.uom)) @@ -354,7 +353,7 @@ def check_item_tax(self): frappe.throw( _("{0} entered twice {1} in Item Taxes").format( frappe.bold(d.item_tax_template), - "for tax category {0}".format(frappe.bold(d.tax_category)) if d.tax_category else "", + f"for tax category {frappe.bold(d.tax_category)}" if d.tax_category else "", ) ) else: @@ -373,7 +372,9 @@ def validate_barcode(self): ) if duplicate: frappe.throw( - _("Barcode {0} already used in Item {1}").format(item_barcode.barcode, duplicate[0][0]) + _("Barcode {0} already used in Item {1}").format( + item_barcode.barcode, duplicate[0][0] + ) ) item_barcode.barcode_type = ( @@ -403,9 +404,9 @@ def validate_warehouse_for_reorder(self): warehouse_material_request_type += [(d.get("warehouse"), d.get("material_request_type"))] else: frappe.throw( - _("Row #{0}: A reorder entry already exists for warehouse {1} with reorder type {2}.").format( - d.idx, d.warehouse, d.material_request_type - ), + _( + "Row #{0}: A reorder entry already exists for warehouse {1} with reorder type {2}." + ).format(d.idx, d.warehouse, d.material_request_type), DuplicateReorderRows, ) @@ -477,20 +478,21 @@ def after_rename(self, old_name, new_name, merge): for dt in ("Sales Taxes and Charges", "Purchase Taxes and Charges"): for d in frappe.db.sql( - """select name, item_wise_tax_detail from `tab{0}` - where ifnull(item_wise_tax_detail, '') != ''""".format( - dt - ), + f"""select name, item_wise_tax_detail from `tab{dt}` + where ifnull(item_wise_tax_detail, '') != ''""", as_dict=1, ): - item_wise_tax_detail = json.loads(d.item_wise_tax_detail) if isinstance(item_wise_tax_detail, dict) and old_name in item_wise_tax_detail: item_wise_tax_detail[new_name] = item_wise_tax_detail[old_name] item_wise_tax_detail.pop(old_name) frappe.db.set_value( - dt, d.name, "item_wise_tax_detail", json.dumps(item_wise_tax_detail), update_modified=False + dt, + d.name, + "item_wise_tax_detail", + json.dumps(item_wise_tax_detail), + update_modified=False, ) def delete_old_bins(self, old_name): @@ -517,9 +519,7 @@ def validate_duplicate_item_in_stock_reconciliation(self, old_name, new_name): ) msg += "
    " - msg += ( - ", ".join([get_link_to_form("Stock Reconciliation", d.parent) for d in records]) + "

    " - ) + msg += ", ".join([get_link_to_form("Stock Reconciliation", d.parent) for d in records]) + "

    " msg += _( "Note: To merge the items, create a separate Stock Reconciliation for the old item {0}" @@ -542,12 +542,8 @@ def validate_properties_before_merge(self, new_name): 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, "disabled": 0} - ) - new_bundle = frappe.get_value( - "Product Bundle", filters={"new_item_code": new_name, "disabled": 0} - ) + 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) @@ -572,7 +568,7 @@ def validate_duplicate_website_item_before_merge(self, old_name, new_name): if len(web_items) <= 1: return - old_web_item = [d.get("name") for d in web_items if d.get("item_code") == old_name][0] + old_web_item = next(d.get("name") for d in web_items if d.get("item_code") == old_name) web_item_link = get_link_to_form("Website Item", old_web_item) old_name, new_name = frappe.bold(old_name), frappe.bold(new_name) @@ -586,9 +582,7 @@ def set_last_purchase_rate(self, new_name): def recalculate_bin_qty(self, new_name): from erpnext.stock.stock_balance import repost_stock - existing_allow_negative_stock = frappe.db.get_value( - "Stock Settings", None, "allow_negative_stock" - ) + existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock") frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) repost_stock_for_warehouses = frappe.get_all( @@ -605,9 +599,7 @@ def recalculate_bin_qty(self, new_name): for warehouse in repost_stock_for_warehouses: repost_stock(new_name, warehouse) - frappe.db.set_value( - "Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock - ) + frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock) def update_bom_item_desc(self): if self.is_new(): @@ -768,16 +760,14 @@ def body(docnames): return "
    ".join(docnames) def table_row(title, body): - return """ - {0} - {1} - """.format( - title, body - ) + return f""" + {title} + {body} + """ rows = "" for docname, attr_list in not_included.items(): - link = "{0}".format(frappe.bold(_(docname))) + link = f"{frappe.bold(_(docname))}" rows += table_row(link, body(attr_list)) error_description = _( @@ -785,17 +775,15 @@ def table_row(title, body): ) message = """ -
    {0}

    +
    {}

    - - + + - {3} + {}
    {1}{2}{}{}
    - """.format( - error_description, _("Variant Items"), _("Attributes"), rows - ) + """.format(error_description, _("Variant Items"), _("Attributes"), rows) frappe.throw(message, title=_("Variant Attribute Error"), is_minimizable=True, wide=True) @@ -925,7 +913,7 @@ def cant_change(self): frappe.throw(msg, title=_("Linked with submitted documents")) - def _get_linked_submitted_documents(self, changed_fields: List[str]) -> Optional[Dict[str, str]]: + def _get_linked_submitted_documents(self, changed_fields: list[str]) -> dict[str, str] | None: linked_doctypes = [ "Delivery Note Item", "Sales Invoice Item", @@ -1088,17 +1076,13 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): last_purchase_receipt and last_purchase_receipt[0].posting_date or "1900-01-01" ) - if last_purchase_order and ( - purchase_order_date >= purchase_receipt_date or not last_purchase_receipt - ): + if last_purchase_order and (purchase_order_date >= purchase_receipt_date or not last_purchase_receipt): # use purchase order last_purchase = last_purchase_order[0] purchase_date = purchase_order_date - elif last_purchase_receipt and ( - purchase_receipt_date > purchase_order_date or not last_purchase_order - ): + elif last_purchase_receipt and (purchase_receipt_date > purchase_order_date or not last_purchase_order): # use purchase receipt last_purchase = last_purchase_receipt[0] purchase_date = purchase_receipt_date @@ -1305,7 +1289,7 @@ def set_item_tax_from_hsn_code(item): pass -def validate_item_default_company_links(item_defaults: List[ItemDefault]) -> None: +def validate_item_default_company_links(item_defaults: list[ItemDefault]) -> None: for item_default in item_defaults: for doctype, field in [ ["Warehouse", "default_warehouse"], diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 7c665b973d8c..d109cf2f01c7 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -315,7 +315,6 @@ def test_item_defaults(self): self.assertEqual(value, purchase_item_details.get(key)) def test_item_default_validations(self): - with self.assertRaises(frappe.ValidationError) as ve: make_item( "Bad Item defaults", @@ -469,9 +468,7 @@ def test_item_merging(self): self.assertFalse(frappe.db.exists("Item", old)) - self.assertTrue( - frappe.db.get_value("Bin", {"item_code": new, "warehouse": "_Test Warehouse - _TC"}) - ) + self.assertTrue(frappe.db.get_value("Bin", {"item_code": new, "warehouse": "_Test Warehouse - _TC"})) self.assertTrue( frappe.db.get_value("Bin", {"item_code": new, "warehouse": "_Test Warehouse 1 - _TC"}) ) @@ -715,9 +712,7 @@ def test_backdated_negative_stock(self): @change_settings("Stock Settings", {"sample_retention_warehouse": "_Test Warehouse - _TC"}) def test_retain_sample(self): - item = make_item( - "_TestRetainSample", {"has_batch_no": 1, "retain_sample": 1, "sample_quantity": 1} - ) + item = make_item("_TestRetainSample", {"has_batch_no": 1, "retain_sample": 1, "sample_quantity": 1}) self.assertEqual(item.has_batch_no, 1) self.assertEqual(item.retain_sample, 1) @@ -790,7 +785,7 @@ def test_item_type_field_change(self): def test_customer_codes_length(self): """Check if item code with special characters are allowed.""" item = make_item(properties={"item_code": "Test Item Code With Special Characters"}) - for row in range(3): + for _row in range(3): item.append("customer_items", {"ref_code": frappe.generate_hash("", 120)}) item.save() self.assertTrue(len(item.customer_code) > 140) @@ -831,9 +826,7 @@ def test_serach_fields_for_item(self): make_property_setter("Item", None, "search_fields", "item_name", "Data", for_doctype="Doctype") item = make_item(properties={"item_name": "Test Item", "description": "Test Description"}) - data = item_query( - "Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True - ) + data = item_query("Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True) self.assertEqual(data[0].name, item.name) self.assertEqual(data[0].item_name, item.item_name) self.assertTrue("description" not in data[0]) @@ -841,9 +834,7 @@ def test_serach_fields_for_item(self): make_property_setter( "Item", None, "search_fields", "item_name, description", "Data", for_doctype="Doctype" ) - data = item_query( - "Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True - ) + data = item_query("Item", "Test Item", "", 0, 20, filters={"item_name": "Test Item"}, as_dict=True) self.assertEqual(data[0].name, item.name) self.assertEqual(data[0].item_name, item.item_name) self.assertEqual(data[0].description, item.description) diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py index 0c24d3c780f1..3ef7553853f8 100644 --- a/erpnext/stock/doctype/item_alternative/item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/item_alternative.py @@ -30,9 +30,7 @@ def validate_alternative_item(self): "allow_alternative_item", ] item_data = frappe.db.get_value("Item", self.item_code, fields, as_dict=1) - alternative_item_data = frappe.db.get_value( - "Item", self.alternative_item_code, fields, as_dict=1 - ) + alternative_item_data = frappe.db.get_value("Item", self.alternative_item_code, fields, as_dict=1) for field in fields: if item_data.get(field) != alternative_item_data.get(field): @@ -72,14 +70,12 @@ def validate_duplicate(self): @frappe.validate_and_sanitize_search_inputs def get_alternative_items(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql( - """ (select alternative_item_code from `tabItem Alternative` + f""" (select alternative_item_code from `tabItem Alternative` where item_code = %(item_code)s and alternative_item_code like %(txt)s) union (select item_code from `tabItem Alternative` where alternative_item_code = %(item_code)s and item_code like %(txt)s - and two_way = 1) limit {1} offset {0} - """.format( - start, page_len - ), + and two_way = 1) limit {page_len} offset {start} + """, {"item_code": filters.get("item_code"), "txt": "%" + txt + "%"}, ) diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.py b/erpnext/stock/doctype/item_alternative/test_item_alternative.py index 199641803ed3..11e45ee06ca8 100644 --- a/erpnext/stock/doctype/item_alternative/test_item_alternative.py +++ b/erpnext/stock/doctype/item_alternative/test_item_alternative.py @@ -54,9 +54,7 @@ def test_alternative_item_for_subcontract_rm(self): "fg_item_qty": 5, }, ] - sco = get_subcontracting_order( - service_items=service_items, supplier_warehouse=supplier_warehouse - ) + sco = get_subcontracting_order(service_items=service_items, supplier_warehouse=supplier_warehouse) rm_items = [ { "item_code": "Test Finished Goods - A", @@ -106,9 +104,7 @@ def test_alternative_item_for_subcontract_rm(self): "reserved_qty_for_sub_contract", ) - self.assertEqual( - after_transfer_reserved_qty_for_sub_contract, flt(reserved_qty_for_sub_contract - 5) - ) + self.assertEqual(after_transfer_reserved_qty_for_sub_contract, flt(reserved_qty_for_sub_contract - 5)) scr = make_subcontracting_receipt(sco.name) scr.save() @@ -159,9 +155,7 @@ def test_alternative_item_for_production_rm(self): "reserved_qty_for_production", ) - self.assertEqual( - reserved_qty_for_production_after_transfer, flt(reserved_qty_for_production - 5) - ) + self.assertEqual(reserved_qty_for_production_after_transfer, flt(reserved_qty_for_production - 5)) ste1 = frappe.get_doc(make_stock_entry(pro_order.name, "Manufacture", 5)) status = False diff --git a/erpnext/stock/doctype/item_attribute/item_attribute.py b/erpnext/stock/doctype/item_attribute/item_attribute.py index ac4c313e28a8..e714cd275045 100644 --- a/erpnext/stock/doctype/item_attribute/item_attribute.py +++ b/erpnext/stock/doctype/item_attribute/item_attribute.py @@ -75,7 +75,9 @@ def validate_duplication(self): values, abbrs = [], [] for d in self.item_attribute_values: if d.attribute_value.lower() in map(str.lower, values): - frappe.throw(_("Attribute value: {0} must appear only once").format(d.attribute_value.title())) + frappe.throw( + _("Attribute value: {0} must appear only once").format(d.attribute_value.title()) + ) values.append(d.attribute_value) if d.abbr.lower() in map(str.lower, abbrs): diff --git a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py index b65ba98a8bfa..09f3ca0374c5 100644 --- a/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py +++ b/erpnext/stock/doctype/item_manufacturer/item_manufacturer.py @@ -41,7 +41,9 @@ def manage_default_item_manufacturer(self, delete=False): # if unchecked and default in Item master, clear it. if default_manufacturer == self.manufacturer and default_part_no == self.manufacturer_part_no: frappe.db.set_value( - "Item", item.name, {"default_item_manufacturer": None, "default_manufacturer_part_no": None} + "Item", + item.name, + {"default_item_manufacturer": None, "default_manufacturer_part_no": None}, ) elif self.is_default: diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py index 54d1ae634f53..a4df337af939 100644 --- a/erpnext/stock/doctype/item_price/item_price.py +++ b/erpnext/stock/doctype/item_price/item_price.py @@ -40,7 +40,7 @@ def update_price_list_details(self): if not price_list_details: link = frappe.utils.get_link_to_form("Price List", self.price_list) - frappe.throw("The price list {0} does not exist or is disabled".format(link)) + frappe.throw(f"The price list {link} does not exist or is disabled") self.buying, self.selling, self.currency = price_list_details @@ -57,7 +57,6 @@ def validate_item_template(self): frappe.throw(_(msg)) def check_duplicates(self): - item_price = frappe.qb.DocType("Item Price") query = ( 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 cec5e218cca2..3fcdb7b49bd9 100644 --- a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py +++ b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py @@ -24,7 +24,6 @@ def set_default_fields(self): "description", "variant_of", "valuation_rate", - "description", "barcodes", "has_variants", "attributes", @@ -50,4 +49,6 @@ def remove_invalid_fields_for_copy_fields_in_variants(self): def validate(self): for d in self.fields: if d.field_name in self.invalid_fields_for_copy_fields_in_variants: - frappe.throw(_("Cannot set the field {0} for copying in variants").format(d.field_name)) + frappe.throw( + _("Cannot set the field {0} for copying in variants").format(d.field_name) + ) 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 11a001ccc70a..f6b7e0d84353 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -76,13 +76,13 @@ def validate_receipt_documents(self): for d in self.get("purchase_receipts"): docstatus = frappe.db.get_value(d.receipt_document_type, d.receipt_document, "docstatus") if docstatus != 1: - msg = ( - f"Row {d.idx}: {d.receipt_document_type} {frappe.bold(d.receipt_document)} must be submitted" - ) + msg = f"Row {d.idx}: {d.receipt_document_type} {frappe.bold(d.receipt_document)} must be submitted" frappe.throw(_(msg), title=_("Invalid Document")) if d.receipt_document_type == "Purchase Invoice": - update_stock = frappe.db.get_value(d.receipt_document_type, d.receipt_document, "update_stock") + update_stock = frappe.db.get_value( + d.receipt_document_type, d.receipt_document, "update_stock" + ) if not update_stock: msg = _("Row {0}: Purchase Invoice {1} has no stock impact.").format( d.idx, frappe.bold(d.receipt_document) @@ -132,7 +132,8 @@ def set_applicable_charges_on_item(self): ) item.applicable_charges = flt( - flt(item.get(based_on_field)) * (flt(self.total_taxes_and_charges) / flt(total_item_cost)), + flt(item.get(based_on_field)) + * (flt(self.total_taxes_and_charges) / flt(total_item_cost)), item.precision("applicable_charges"), ) total_charges += item.applicable_charges @@ -230,7 +231,9 @@ def validate_asset_qty_and_status(self, receipt_document_type, receipt_document) for item in self.get("items"): if item.is_fixed_asset: receipt_document_type = ( - "purchase_invoice" if item.receipt_document_type == "Purchase Invoice" else "purchase_receipt" + "purchase_invoice" + if item.receipt_document_type == "Purchase Invoice" + else "purchase_receipt" ) docs = frappe.db.get_all( "Asset", @@ -249,9 +252,7 @@ def validate_asset_qty_and_status(self, receipt_document_type, receipt_document) frappe.throw( _( "{0} {1} has submitted Assets. Remove Item {2} from table to continue." - ).format( - item.receipt_document_type, item.receipt_document, item.item_code - ) + ).format(item.receipt_document_type, item.receipt_document, item.item_code) ) def update_rate_in_serial_no_for_non_asset_items(self, receipt_document): @@ -260,10 +261,10 @@ def update_rate_in_serial_no_for_non_asset_items(self, receipt_document): serial_nos = get_serial_nos(item.serial_no) if serial_nos: frappe.db.sql( - "update `tabSerial No` set purchase_rate=%s where name in ({0})".format( + "update `tabSerial No` set purchase_rate=%s where name in ({})".format( ", ".join(["%s"] * len(serial_nos)) ), - tuple([item.valuation_rate] + serial_nos), + tuple([item.valuation_rate, *serial_nos]), ) diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py index 00fa1686c0d3..51c44f60676f 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py @@ -62,9 +62,7 @@ def test_landed_cost_voucher(self): as_dict=1, ) - self.assertEqual( - last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction - ) + self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction) self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 25.0) # assert after submit @@ -87,7 +85,6 @@ def test_landed_cost_voucher(self): self.assertPurchaseReceiptLCVGLEntries(pr) def assertPurchaseReceiptLCVGLEntries(self, pr): - gl_entries = get_gl_entries("Purchase Receipt", pr.name) self.assertTrue(gl_entries) @@ -170,9 +167,7 @@ def test_landed_cost_voucher_stock_impact(self): as_dict=1, ) - self.assertEqual( - last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction - ) + self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction) self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 50.0) def test_landed_cost_voucher_for_zero_purchase_rate(self): @@ -229,7 +224,6 @@ def test_landed_cost_voucher_for_zero_purchase_rate(self): ) def test_landed_cost_voucher_against_purchase_invoice(self): - pi = make_purchase_invoice( update_stock=1, posting_date=frappe.utils.nowdate(), @@ -274,9 +268,7 @@ def test_landed_cost_voucher_against_purchase_invoice(self): as_dict=1, ) - self.assertEqual( - last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction - ) + self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction) self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 50.0) @@ -365,9 +357,7 @@ def test_serialized_lcv_delivered(self): new_purchase_rate = serial_no_rate + charges - serial_no = frappe.db.get_value( - "Serial No", serial_no, ["warehouse", "purchase_rate"], as_dict=1 - ) + serial_no = frappe.db.get_value("Serial No", serial_no, ["warehouse", "purchase_rate"], as_dict=1) self.assertEqual(serial_no.purchase_rate, new_purchase_rate) @@ -392,7 +382,7 @@ def test_landed_cost_voucher_for_odd_numbers(self): do_not_save=True, ) pr.items[0].cost_center = "Main - TCP1" - for x in range(2): + for _x in range(2): pr.append( "items", { diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 8d38fdcd8df0..9381bbb47064 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -33,10 +33,10 @@ def validate_qty_against_so(self): so_items = {} # Format --> {'SO/00001': {'Item/001': 120, 'Item/002': 24}} for d in self.get("items"): if d.sales_order: - if not d.sales_order in so_items: + if d.sales_order not in so_items: so_items[d.sales_order] = {d.item_code: flt(d.qty)} else: - if not d.item_code in so_items[d.sales_order]: + if d.item_code not in so_items[d.sales_order]: so_items[d.sales_order][d.item_code] = flt(d.qty) else: so_items[d.sales_order][d.item_code] += flt(d.qty) @@ -61,13 +61,13 @@ def validate_qty_against_so(self): if actual_so_qty and (flt(so_items[so_no][item]) + already_indented > actual_so_qty): frappe.throw( - _("Material Request of maximum {0} can be made for Item {1} against Sales Order {2}").format( - actual_so_qty - already_indented, item, so_no - ) + _( + "Material Request of maximum {0} can be made for Item {1} against Sales Order {2}" + ).format(actual_so_qty - already_indented, item, so_no) ) def validate(self): - super(MaterialRequest, self).validate() + super().validate() self.validate_schedule_date() self.check_for_on_hold_or_closed_status("Sales Order", "sales_order") @@ -141,12 +141,8 @@ def before_cancel(self): self.set_status(update=True, status="Cancelled") def check_modified_date(self): - mod_db = frappe.db.sql( - """select modified from `tabMaterial Request` where name = %s""", self.name - ) - date_diff = frappe.db.sql( - """select TIMEDIFF('%s', '%s')""" % (mod_db[0][0], cstr(self.modified)) - ) + mod_db = frappe.db.sql("""select modified from `tabMaterial Request` where name = %s""", self.name) + date_diff = frappe.db.sql(f"""select TIMEDIFF('{mod_db[0][0]}', '{cstr(self.modified)}')""") if date_diff and date_diff[0][0]: frappe.throw(_("{0} {1} has been modified. Please refresh.").format(_(self.doctype), self.name)) @@ -326,9 +322,7 @@ def update_completed_and_requested_qty(stock_entry, method): def set_missing_values(source, target_doc): - if target_doc.doctype == "Purchase Order" and getdate(target_doc.schedule_date) < getdate( - nowdate() - ): + if target_doc.doctype == "Purchase Order" and getdate(target_doc.schedule_date) < getdate(nowdate()): target_doc.schedule_date = None target_doc.run_method("set_missing_values") target_doc.run_method("calculate_taxes_and_totals") @@ -458,9 +452,7 @@ def postprocess(source, target_doc): target_doc.schedule_date = None target_doc.set( "items", - [ - d for d in target_doc.get("items") if d.get("item_code") in supplier_items and d.get("qty") > 0 - ], + [d for d in target_doc.get("items") if d.get("item_code") in supplier_items and d.get("qty") > 0], ) set_missing_values(source, target_doc) @@ -512,7 +504,7 @@ def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, pa if filters.get("transaction_date"): date = filters.get("transaction_date")[1] - conditions += "and mr.transaction_date between '{0}' and '{1}' ".format(date[0], date[1]) + conditions += f"and mr.transaction_date between '{date[0]}' and '{date[1]}' " supplier = filters.get("supplier") supplier_items = get_items_based_on_default_supplier(supplier) @@ -524,18 +516,18 @@ def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, pa """select distinct mr.name, transaction_date,company from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item where mr.name = mr_item.parent - and mr_item.item_code in ({0}) + and mr_item.item_code in ({}) and mr.material_request_type = 'Purchase' and mr.per_ordered < 99.99 and mr.docstatus = 1 and mr.status != 'Stopped' and mr.company = %s - {1} + {} order by mr_item.item_code ASC - limit {2} offset {3} """.format( + limit {} offset {} """.format( ", ".join(["%s"] * len(supplier_items)), conditions, cint(page_len), cint(start) ), - tuple(supplier_items) + (filters.get("company"),), + (*tuple(supplier_items), filters.get("company")), as_dict=1, ) @@ -663,7 +655,10 @@ def set_missing_values(source, target): "doctype": "Stock Entry", "validation": { "docstatus": ["=", 1], - "material_request_type": ["in", ["Material Transfer", "Material Issue", "Customer Provided"]], + "material_request_type": [ + "in", + ["Material Transfer", "Material Issue", "Customer Provided"], + ], }, }, "Material Request Item": { @@ -693,9 +688,7 @@ def raise_work_orders(material_request): mr = frappe.get_doc("Material Request", material_request) errors = [] work_orders = [] - default_wip_warehouse = frappe.db.get_single_value( - "Manufacturing Settings", "default_wip_warehouse" - ) + default_wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse") for d in mr.items: if (d.stock_qty - d.ordered_qty) > 0: diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index b5817c750e28..b87413e67dac 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -744,9 +744,7 @@ def test_multi_uom_for_purchase(self): self.assertEqual(mr.per_ordered, 100) def test_customer_provided_parts_mr(self): - create_item( - "CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0 - ) + create_item("CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0) existing_requested_qty = self._get_requested_qty("_Test Customer", "_Test Warehouse - _TC") mr = make_material_request(item_code="CUST-0987", material_request_type="Customer Provided") @@ -810,7 +808,7 @@ def test_auto_email_users_with_company_user_permissions(self): ) comapnywise_mr_list.setdefault(mr2.company, []).append(mr2.name) - for company, mr_list in comapnywise_mr_list.items(): + for company, _mr_list in comapnywise_mr_list.items(): emails = get_email_list(company) self.assertTrue(comapnywise_users[company] in emails) @@ -828,9 +826,7 @@ def get_in_transit_warehouse(company): } ).insert() - in_transit_warehouse = frappe.db.exists( - "Warehouse", {"warehouse_type": "Transit", "company": company} - ) + in_transit_warehouse = frappe.db.exists("Warehouse", {"warehouse_type": "Transit", "company": company}) if not in_transit_warehouse: in_transit_warehouse = ( diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index 35701c90deb8..a157606a37a0 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -23,9 +23,7 @@ def make_packing_list(doc): return parent_items_price, reset = {}, False - set_price_from_children = frappe.db.get_single_value( - "Selling Settings", "editable_bundle_item_rates" - ) + set_price_from_children = frappe.db.get_single_value("Selling Settings", "editable_bundle_item_rates") stale_packed_items_table = get_indexed_packed_items_table(doc) @@ -244,9 +242,7 @@ def get_packed_item_bin_qty(item, warehouse): def get_cancelled_doc_packed_item_details(old_packed_items): prev_doc_packed_items_map = {} for items in old_packed_items: - prev_doc_packed_items_map.setdefault((items.item_code, items.parent_item), []).append( - items.as_dict() - ) + prev_doc_packed_items_map.setdefault((items.item_code, items.parent_item), []).append(items.as_dict()) return prev_doc_packed_items_map diff --git a/erpnext/stock/doctype/packed_item/test_packed_item.py b/erpnext/stock/doctype/packed_item/test_packed_item.py index ad06732bc3ed..3f87cede7d6c 100644 --- a/erpnext/stock/doctype/packed_item/test_packed_item.py +++ b/erpnext/stock/doctype/packed_item/test_packed_item.py @@ -1,7 +1,6 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from typing import List, Optional, Tuple import frappe from frappe.tests.utils import FrappeTestCase, change_settings @@ -15,8 +14,8 @@ def create_product_bundle( - quantities: Optional[List[int]] = None, warehouse: Optional[str] = None -) -> Tuple[str, List[str]]: + quantities: list[int] | None = None, warehouse: str | None = None +) -> tuple[str, list[str]]: """Get a new product_bundle for use in tests. Create 10x required stock if warehouse is specified. @@ -169,9 +168,7 @@ def test_reposting_packed_items(self): # backdated stock entry for item in self.bundle_items: - make_stock_entry( - item_code=item, to_warehouse=warehouse, qty=10, rate=200, posting_date=yesterday - ) + make_stock_entry(item_code=item, to_warehouse=warehouse, qty=10, rate=200, posting_date=yesterday) # assert correct reposting gles = get_gl_entries(dn.doctype, dn.name) @@ -182,10 +179,11 @@ def test_reposting_packed_items(self): def assertReturns(self, original, returned): self.assertEqual(len(original), len(returned)) - sort_function = lambda p: (p.parent_item, p.item_code, p.qty) + def sort_function(p): + return p.parent_item, p.item_code, p.qty for sent, returned in zip( - sorted(original, key=sort_function), sorted(returned, key=sort_function) + sorted(original, key=sort_function), sorted(returned, key=sort_function), strict=False ): self.assertEqual(sent.item_code, returned.item_code) self.assertEqual(sent.parent_item, returned.parent_item) diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py index 6ea5938917ab..df66b98c3372 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -11,7 +11,7 @@ class PackingSlip(StatusUpdater): def __init__(self, *args, **kwargs) -> None: - super(PackingSlip, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "target_dt": "Delivery Note Item", @@ -64,9 +64,7 @@ def validate_case_nos(self): """Validate if case nos overlap. If they do, recommend next case no.""" if cint(self.from_case_no) <= 0: - frappe.throw( - _("The 'From Package No.' field must neither be empty nor it's value less than 1.") - ) + frappe.throw(_("The 'From Package No.' field must neither be empty nor it's value less than 1.")) elif not self.to_case_no: self.to_case_no = self.from_case_no elif cint(self.to_case_no) < cint(self.from_case_no): @@ -189,9 +187,8 @@ def item_details(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql( """select name, item_name, description from `tabItem` where name in ( select item_code FROM `tabDelivery Note Item` - where parent= %s) - and %s like "%s" %s - limit %s offset %s """ - % ("%s", searchfield, "%s", get_match_cond(doctype), "%s", "%s"), + where parent= {}) + and {} like "{}" {} + limit {} offset {} """.format("%s", searchfield, "%s", get_match_cond(doctype), "%s", "%s"), ((filters or {}).get("delivery_note"), "%%%s%%" % txt, page_len, start), ) diff --git a/erpnext/stock/doctype/packing_slip/test_packing_slip.py b/erpnext/stock/doctype/packing_slip/test_packing_slip.py index 96da23db4a8d..08c70bf8e95d 100644 --- a/erpnext/stock/doctype/packing_slip/test_packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/test_packing_slip.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.tests.utils import FrappeTestCase diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index fb202a31f581..ef7dc710b13c 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -4,7 +4,6 @@ import json from collections import OrderedDict, defaultdict from itertools import groupby -from typing import Dict, List import frappe from frappe import _ @@ -213,9 +212,7 @@ def set_item_locations(self, save=False): ), ) - locations = get_items_with_location_and_quantity( - item_doc, self.item_location_map, self.docstatus - ) + locations = get_items_with_location_and_quantity(item_doc, self.item_location_map, self.docstatus) item_doc.idx = None item_doc.name = None @@ -269,12 +266,10 @@ def aggregate_item_qty(self): item_map = OrderedDict() for item in locations: if not item.item_code: - frappe.throw("Row #{0}: Item Code is Mandatory".format(item.idx)) + frappe.throw(f"Row #{item.idx}: Item Code is Mandatory") 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, "disabled": 0} - ): + ) 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 @@ -395,7 +390,7 @@ def get_picked_items_details(self, items): return picked_items - def _get_product_bundles(self) -> Dict[str, str]: + def _get_product_bundles(self) -> dict[str, str]: # Dict[so_item_row: item_code] product_bundles = {} for item in self.locations: @@ -408,13 +403,11 @@ def _get_product_bundles(self) -> Dict[str, str]: ) return product_bundles - def _get_product_bundle_qty_map(self, bundles: List[str]) -> Dict[str, Dict[str, float]]: + def _get_product_bundle_qty_map(self, bundles: list[str]) -> dict[str, dict[str, float]]: # 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, "disabled": 0} - ) + 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 @@ -440,7 +433,7 @@ def update_pick_list_status(pick_list): doc.run_method("update_status") -def get_picked_items_qty(items) -> List[Dict]: +def get_picked_items_qty(items) -> list[dict]: pi_item = frappe.qb.DocType("Pick List Item") return ( frappe.qb.from_(pi_item) @@ -470,17 +463,13 @@ def get_items_with_location_and_quantity(item_doc, item_location_map, docstatus) locations = [] # if stock qty is zero on submitted entry, show positive remaining qty to recalculate in case of restock. - remaining_stock_qty = ( - item_doc.qty if (docstatus == 1 and item_doc.stock_qty == 0) else item_doc.stock_qty - ) + remaining_stock_qty = item_doc.qty if (docstatus == 1 and item_doc.stock_qty == 0) else item_doc.stock_qty while flt(remaining_stock_qty) > 0 and available_locations: item_location = available_locations.pop(0) item_location = frappe._dict(item_location) - stock_qty = ( - remaining_stock_qty if item_location.qty >= remaining_stock_qty else item_location.qty - ) + stock_qty = remaining_stock_qty if item_location.qty >= remaining_stock_qty else item_location.qty qty = stock_qty / (item_doc.conversion_factor or 1) uom_must_be_whole_number = frappe.get_cached_value("UOM", item_doc.uom, "must_be_whole_number") @@ -515,7 +504,7 @@ def get_items_with_location_and_quantity(item_doc, item_location_map, docstatus) if item_location.serial_no: # set remaining serial numbers item_location.serial_no = item_location.serial_no[-int(qty_diff) :] - available_locations = [item_location] + available_locations + available_locations = [item_location, *available_locations] # update available locations for the item item_location_map[item_doc.item_code] = available_locations @@ -830,8 +819,7 @@ def create_dn_with_so(sales_dict, pick_list): "name": "so_detail", "parent": "against_sales_order", }, - "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) - and doc.delivered_by_supplier != 1, + "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier != 1, } for customer in sales_dict: @@ -852,7 +840,6 @@ def create_dn_with_so(sales_dict, pick_list): def map_pl_locations(pick_list, item_mapper, delivery_note, sales_order=None): - for location in pick_list.locations: if location.sales_order != sales_order or location.product_bundle_item: continue @@ -883,9 +870,7 @@ def map_pl_locations(pick_list, item_mapper, delivery_note, sales_order=None): delivery_note.customer = frappe.get_value("Sales Order", sales_order, "customer") -def add_product_bundles_to_delivery_note( - pick_list: "PickList", delivery_note, item_mapper -) -> None: +def add_product_bundles_to_delivery_note(pick_list: "PickList", delivery_note, item_mapper) -> None: """Add product bundles found in pick list to delivery note. When mapping pick list items, the bundle item itself isn't part of the @@ -963,7 +948,7 @@ def get_pending_work_orders(doctype, txt, searchfield, start, page_length, filte & (wo.qty > wo.material_transferred_for_manufacturing) & (wo.docstatus == 1) & (wo.company == filters.get("company")) - & (wo.name.like("%{0}%".format(txt))) + & (wo.name.like(f"%{txt}%")) ) .orderby(Case().when(Locate(txt, wo.name) > 0, Locate(txt, wo.name)).else_(99999)) .orderby(wo.name) @@ -1030,9 +1015,7 @@ def update_stock_entry_based_on_work_order(pick_list, stock_entry): stock_entry.use_multi_level_bom = work_order.use_multi_level_bom stock_entry.fg_completed_qty = pick_list.for_qty if work_order.bom_no: - stock_entry.inspection_required = frappe.db.get_value( - "BOM", work_order.bom_no, "inspection_required" - ) + stock_entry.inspection_required = frappe.db.get_value("BOM", work_order.bom_no, "inspection_required") is_wip_warehouse_group = frappe.db.get_value("Warehouse", work_order.wip_warehouse, "is_group") if not (is_wip_warehouse_group and work_order.skip_transfer): diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py index 1254fe3927fa..4a9a1a50ac60 100644 --- a/erpnext/stock/doctype/pick_list/test_pick_list.py +++ b/erpnext/stock/doctype/pick_list/test_pick_list.py @@ -139,7 +139,6 @@ def test_pick_list_splits_row_according_to_warehouse_availability(self): self.assertEqual(pick_list.locations[1].qty, 10) def test_pick_list_shows_serial_no_for_serialized_item(self): - stock_reconciliation = frappe.get_doc( { "doctype": "Stock Reconciliation", @@ -274,7 +273,6 @@ def test_pick_list_for_batched_and_serialised_item(self): pr2.cancel() def test_pick_list_for_items_from_multiple_sales_orders(self): - item_code = make_item().name try: frappe.get_doc( @@ -418,9 +416,7 @@ def test_pick_list_for_items_with_multiple_UOM(self): self.assertEqual(pick_list.locations[0].qty, delivery_note.items[0].qty) self.assertEqual(pick_list.locations[1].qty, delivery_note.items[1].qty) - self.assertEqual( - sales_order.items[0].conversion_factor, delivery_note.items[0].conversion_factor - ) + self.assertEqual(sales_order.items[0].conversion_factor, delivery_note.items[0].conversion_factor) pick_list.cancel() sales_order.cancel() @@ -469,7 +465,7 @@ def _compare_dicts(a, b): _dict(item_code="A", warehouse="X", qty=8, picked_qty=3), _dict(item_code="B", warehouse="Y", qty=6, picked_qty=4), ] - for expected_item, created_item in zip(expected_items, pl.locations): + for expected_item, created_item in zip(expected_items, pl.locations, strict=False): _compare_dicts(expected_item, created_item) def test_multiple_dn_creation(self): @@ -579,9 +575,7 @@ def test_multiple_dn_creation(self): pick_list_1.set_item_locations() pick_list_1.submit() create_delivery_note(pick_list_1.name) - for dn in frappe.get_all( - "Delivery Note", filters={"pick_list": pick_list_1.name}, fields={"name"} - ): + for dn in frappe.get_all("Delivery Note", filters={"pick_list": pick_list_1.name}, fields={"name"}): for dn_item in frappe.get_doc("Delivery Note", dn.name).get("items"): if dn_item.item_code == "_Test Item": self.assertEqual(dn_item.qty, 1) @@ -609,7 +603,7 @@ def test_picklist_with_bundles(self): quantities = [5, 2] bundle, components = create_product_bundle(quantities, warehouse=warehouse) - bundle_items = dict(zip(components, quantities)) + bundle_items = dict(zip(components, quantities, strict=False)) so = make_sales_order(item_code=bundle, qty=3, rate=42) @@ -715,7 +709,7 @@ def create_stock_entries(items): for item in items: for warehouse in warehouses: - se = make_stock_entry( + make_stock_entry( item=item.get("item_code"), to_warehouse=warehouse, qty=5, diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 064c717c3205..0beb98563cfe 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -23,7 +23,7 @@ class PurchaseReceipt(BuyingController): def __init__(self, *args, **kwargs): - super(PurchaseReceipt, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "target_dt": "Purchase Order Item", @@ -116,7 +116,7 @@ def before_validate(self): def validate(self): self.validate_posting_time() - super(PurchaseReceipt, self).validate() + super().validate() if self._action == "submit": self.make_batches("warehouse") @@ -148,15 +148,15 @@ def validate_cwip_accounts(self): # Improves UX by not giving messages of "Assets Created" before throwing error of not finding arbnb account self.get_company_default("asset_received_but_not_billed") get_asset_account( - "capital_work_in_progress_account", asset_category=item.asset_category, company=self.company + "capital_work_in_progress_account", + asset_category=item.asset_category, + company=self.company, ) break def validate_provisional_expense_account(self): provisional_accounting_for_non_stock_items = cint( - frappe.db.get_value( - "Company", self.company, "enable_provisional_accounting_for_non_stock_items" - ) + frappe.db.get_value("Company", self.company, "enable_provisional_accounting_for_non_stock_items") ) if not provisional_accounting_for_non_stock_items: @@ -168,7 +168,7 @@ def validate_provisional_expense_account(self): item.provisional_expense_account = default_provisional_account def validate_with_previous_doc(self): - super(PurchaseReceipt, self).validate_with_previous_doc( + super().validate_with_previous_doc( { "Purchase Order": { "ref_dn_field": "purchase_order", @@ -229,24 +229,20 @@ def get_already_received_qty(self, po, po_detail): return qty and flt(qty[0][0]) or 0.0 def get_po_qty_and_warehouse(self, po_detail): - po_qty, po_warehouse = frappe.db.get_value( - "Purchase Order Item", po_detail, ["qty", "warehouse"] - ) + po_qty, po_warehouse = frappe.db.get_value("Purchase Order Item", po_detail, ["qty", "warehouse"]) return po_qty, po_warehouse # Check for Closed status def check_on_hold_or_closed_status(self): check_list = [] for d in self.get("items"): - if ( - d.meta.get_field("purchase_order") and d.purchase_order and d.purchase_order not in check_list - ): + if d.meta.get_field("purchase_order") and d.purchase_order and d.purchase_order not in check_list: check_list.append(d.purchase_order) check_on_hold_or_closed_status("Purchase Order", d.purchase_order) # on submit def on_submit(self): - super(PurchaseReceipt, self).on_submit() + super().on_submit() # Check for Approving Authority frappe.get_doc("Authorization Control").validate_approving_authority( @@ -283,7 +279,7 @@ def check_next_docstatus(self): frappe.throw(_("Purchase Invoice {0} is already submitted").format(self.submit_rv[0][0])) def on_cancel(self): - super(PurchaseReceipt, self).on_cancel() + super().on_cancel() self.check_on_hold_or_closed_status() # Check if Purchase Invoice has been submitted against current Purchase Order @@ -325,9 +321,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): ) provisional_accounting_for_non_stock_items = cint( - frappe.db.get_value( - "Company", self.company, "enable_provisional_accounting_for_non_stock_items" - ) + frappe.db.get_value("Company", self.company, "enable_provisional_accounting_for_non_stock_items") ) exchange_rate_map, net_rate_map = get_purchase_document_details(self) @@ -396,7 +390,6 @@ def make_stock_received_but_not_billed_entry(item): and self.conversion_rate != exchange_rate_map[item.purchase_invoice] and item.net_rate == net_rate_map[item.purchase_invoice_item] ): - discrepancy_caused_by_exchange_rate_difference = (item.qty * item.net_rate) * ( exchange_rate_map[item.purchase_invoice] - self.conversion_rate ) @@ -578,10 +571,12 @@ def make_divisional_loss_gl_entry(item, outgoing_amount): elif warehouse_account.get(d.warehouse): stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) stock_asset_account_name = warehouse_account[d.warehouse]["account"] - supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") - supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( - "account_currency" + supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get( + "account" ) + supplier_warehouse_account_currency = warehouse_account.get( + self.supplier_warehouse, {} + ).get("account_currency") # If PR is sub-contracted and fg item rate is zero # in that case if account for source and target warehouse are same, @@ -988,9 +983,7 @@ def set_missing_values(source, target): frappe.throw(_("All items have already been Invoiced/Returned")) doc = frappe.get_doc(target) - doc.payment_terms_template = get_payment_terms_template( - source.supplier, "Supplier", source.company - ) + doc.payment_terms_template = get_payment_terms_template(source.supplier, "Supplier", source.company) doc.run_method("onload") doc.run_method("set_missing_values") @@ -1002,9 +995,7 @@ def set_missing_values(source, target): def update_item(source_doc, target_doc, source_parent): target_doc.qty, returned_qty = get_pending_qty(source_doc) - if frappe.db.get_single_value( - "Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice" - ): + if frappe.db.get_single_value("Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice"): target_doc.rejected_qty = 0 target_doc.stock_qty = flt(target_doc.qty) * flt( target_doc.conversion_factor, target_doc.precision("conversion_factor") @@ -1013,9 +1004,7 @@ def update_item(source_doc, target_doc, source_parent): def get_pending_qty(item_row): qty = item_row.qty - if frappe.db.get_single_value( - "Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice" - ): + if frappe.db.get_single_value("Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice"): qty = item_row.received_qty pending_qty = qty - invoiced_qty_map.get(item_row.name, 0) returned_qty = flt(returned_qty_map.get(item_row.name, 0)) @@ -1193,15 +1182,11 @@ def get_item_account_wise_additional_cost(purchase_document): if total_item_cost > 0: item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ account.expense_account - ]["amount"] += ( - account.amount * item.get(based_on_field) / total_item_cost - ) + ]["amount"] += account.amount * item.get(based_on_field) / total_item_cost item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ account.expense_account - ]["base_amount"] += ( - account.base_amount * item.get(based_on_field) / total_item_cost - ) + ]["base_amount"] += account.base_amount * item.get(based_on_field) / total_item_cost else: item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ account.expense_account diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index d4f85b1aa7ef..b185fd471f92 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -11,7 +11,7 @@ from erpnext.controllers.buying_controller import QtyMismatchError from erpnext.stock.doctype.item.test_item import create_item, make_item from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice -from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError, get_serial_nos +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse @@ -37,7 +37,6 @@ def test_purchase_receipt_received_qty(self): pr.delete() def test_reverse_purchase_receipt_sle(self): - pr = make_purchase_receipt(qty=0.5, item_code="_Test Item Home Desktop 200") sl_entry = frappe.db.get_all( @@ -124,9 +123,7 @@ def test_make_purchase_invoice(self): pi.delete() # draft PI pr.cancel() frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", old_template_in_supplier) - frappe.get_doc( - "Payment Terms Template", "_Test Payment Terms Template For Purchase Invoice" - ).delete() + frappe.get_doc("Payment Terms Template", "_Test Payment Terms Template For Purchase Invoice").delete() def test_purchase_receipt_no_gl_entry(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry @@ -273,7 +270,8 @@ def test_rejected_serial_no(self): self.assertEqual(len(rejected_serial_nos), 2) for serial_no in rejected_serial_nos: self.assertEqual( - frappe.db.get_value("Serial No", serial_no, "warehouse"), pr.get("items")[0].rejected_warehouse + frappe.db.get_value("Serial No", serial_no, "warehouse"), + pr.get("items")[0].rejected_warehouse, ) pr.cancel() @@ -613,7 +611,7 @@ def test_serial_no_against_purchase_receipt(self): item_code = "Test Manual Created Serial No" if not frappe.db.exists("Item", item_code): - item = make_item(item_code, dict(has_serial_no=1)) + make_item(item_code, dict(has_serial_no=1)) serial_no = "12903812901" pr_doc = make_purchase_receipt(item_code=item_code, qty=1, serial_no=serial_no) @@ -759,7 +757,7 @@ def test_purchase_receipt_cost_center(self): "Stock Received But Not Billed - TCP1": {"cost_center": cost_center}, stock_in_hand_account: {"cost_center": cost_center}, } - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) pr.cancel() @@ -784,7 +782,7 @@ def test_purchase_receipt_cost_center_with_balance_sheet_account(self): "Stock Received But Not Billed - TCP1": {"cost_center": cost_center}, stock_in_hand_account: {"cost_center": cost_center}, } - for i, gle in enumerate(gl_entries): + for _i, gle in enumerate(gl_entries): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) pr.cancel() @@ -1045,9 +1043,7 @@ def test_purchase_receipt_with_exchange_rate_difference(self): pr.submit() # Get exchnage gain and loss account - exchange_gain_loss_account = frappe.db.get_value( - "Company", pr.company, "exchange_gain_loss_account" - ) + exchange_gain_loss_account = frappe.db.get_value("Company", pr.company, "exchange_gain_loss_account") # fetching the latest GL Entry with exchange gain and loss account account amount = frappe.db.get_value( @@ -1104,9 +1100,7 @@ def test_neg_to_positive(self): account = "Stock Received But Not Billed - TCP1" make_item(item_code) - se = make_stock_entry( - item_code=item_code, from_warehouse=warehouse, qty=50, do_not_save=True, rate=0 - ) + se = make_stock_entry(item_code=item_code, from_warehouse=warehouse, qty=50, do_not_save=True, rate=0) se.items[0].allow_zero_valuation_rate = 1 se.save() se.submit() @@ -1221,9 +1215,7 @@ def test_rejected_qty_for_internal_transfer(self): from_warehouse = create_warehouse("_Test Internal From Warehouse New", company=company) to_warehouse = create_warehouse("_Test Internal To Warehouse New", company=company) - rejected_warehouse = create_warehouse( - "_Test Rejected Internal To Warehouse New", company=company - ) + rejected_warehouse = create_warehouse("_Test Rejected Internal To Warehouse New", company=company) item_doc = make_item( "Test Internal Transfer Item DS", { @@ -1616,7 +1608,6 @@ def test_validate_received_qty_for_internal_pr(self): ) # Step 4: Create Internal Purchase Receipt - from erpnext.controllers.status_updater import OverAllowanceError from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt pr = make_inter_company_purchase_receipt(dn.name) @@ -1766,7 +1757,6 @@ def test_internal_pr_reference(self): ) # Step 4: Create Internal Purchase Receipt - from erpnext.controllers.status_updater import OverAllowanceError from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt pr = make_inter_company_purchase_receipt(dn.name) @@ -2072,9 +2062,7 @@ def test_valuation_rate_in_return_purchase_receipt_for_moving_average(self): ) # Step - 4: Create a Material Issue Stock Entry (Qty = 100, Basic Rate = 18.18 [Auto Fetched]) - make_stock_entry( - purpose="Material Issue", item_code=item_code, from_warehouse=warehouse, qty=100 - ) + make_stock_entry(purpose="Material Issue", item_code=item_code, from_warehouse=warehouse, qty=100) # Step - 5: Create a Return Purchase Return (Qty = -8, Rate = 100 [Auto fetched]) return_pr = make_purchase_receipt( @@ -2146,9 +2134,9 @@ def test_purchase_return_with_zero_rate(self): gl_entries = get_gl_entries(pr_return.doctype, pr_return.name) # Test - 1: SLE Stock Value Difference should be equal to Qty * Average Rate - average_rate = ( - (se.items[0].qty * se.items[0].basic_rate) + (pr.items[0].qty * pr.items[0].rate) - ) / (se.items[0].qty + pr.items[0].qty) + average_rate = ((se.items[0].qty * se.items[0].basic_rate) + (pr.items[0].qty * pr.items[0].rate)) / ( + se.items[0].qty + pr.items[0].qty + ) expected_stock_value_difference = pr_return.items[0].qty * average_rate self.assertEqual( flt(sl_entries[0].stock_value_difference, 2), flt(expected_stock_value_difference, 2) @@ -2243,7 +2231,7 @@ def test_sle_qty_after_transaction(self): do_not_save=1, ) - for i in range(9): + for _i in range(9): pr.append( "items", { @@ -2283,7 +2271,7 @@ def test_sle_qty_after_transaction(self): do_not_save=1, ) - for i in range(9): + for _i in range(9): pr.append( "items", { @@ -2370,7 +2358,6 @@ def get_gl_entries(voucher_type, voucher_no): def get_taxes(**args): - args = frappe._dict(args) return [ @@ -2490,15 +2477,14 @@ def make_purchase_receipt(**args): "rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "", - "rate": args.rate if args.rate != None else 50, + "rate": args.rate if args.rate is not None else 50, "conversion_factor": args.conversion_factor or 1.0, "stock_qty": flt(qty) * (flt(args.conversion_factor) or 1.0), "serial_no": args.serial_no, "batch_no": args.batch_no, "stock_uom": args.stock_uom or "_Test UOM", "uom": uom, - "cost_center": args.cost_center - or frappe.get_cached_value("Company", pr.company, "cost_center"), + "cost_center": args.cost_center or frappe.get_cached_value("Company", pr.company, "cost_center"), "asset_location": args.location or "Test Location", }, ) diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py index 623fbde2b0bb..2795c576c914 100644 --- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py @@ -109,9 +109,7 @@ def apply_putaway_rule(doctype, items, company, sync=None, purpose=None): updated_table = add_row(item, pending_qty, source_warehouse or item.warehouse, updated_table) continue - at_capacity, rules = get_ordered_putaway_rules( - item_code, company, source_warehouse=source_warehouse - ) + at_capacity, rules = get_ordered_putaway_rules(item_code, company, source_warehouse=source_warehouse) if not rules: warehouse = source_warehouse or item.get("warehouse") @@ -204,7 +202,7 @@ def _items_changed(old, new, doctype: str) -> bool: new_sorted = sorted(new, key=sort_key) # Once sorted by all relevant keys both tables should align if they are same. - for old_item, new_item in zip(old_sorted, new_sorted): + for old_item, new_item in zip(old_sorted, new_sorted, strict=False): for key in compare_keys: if old_item.get(key) != new_item.get(key): return True @@ -253,9 +251,7 @@ def add_row(item, to_allocate, warehouse, updated_table, rule=None, serial_nos=N if item.doctype == "Stock Entry Detail": new_updated_table_row.t_warehouse = warehouse - new_updated_table_row.transfer_qty = flt(to_allocate) * flt( - new_updated_table_row.conversion_factor - ) + new_updated_table_row.transfer_qty = flt(to_allocate) * flt(new_updated_table_row.conversion_factor) else: new_updated_table_row.stock_qty = flt(to_allocate) * flt(new_updated_table_row.conversion_factor) new_updated_table_row.warehouse = warehouse @@ -277,24 +273,20 @@ def show_unassigned_items_message(items_not_accomodated): for entry in items_not_accomodated: item_link = frappe.utils.get_link_to_form("Item", entry[0]) - formatted_item_rows += """ - {0} - {1} - """.format( - item_link, frappe.bold(entry[1]) - ) + formatted_item_rows += f""" + {item_link} + {frappe.bold(entry[1])} + """ msg += """ - - + + - {2} + {}
    {0}{1}{}{}
    - """.format( - _("Item"), _("Unassigned Qty"), formatted_item_rows - ) + """.format(_("Item"), _("Unassigned Qty"), formatted_item_rows) frappe.msgprint(msg, title=_("Insufficient Capacity"), is_minimizable=True, wide=True) diff --git a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py index ab0ca106a8b3..7253f767e928 100644 --- a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py @@ -46,9 +46,7 @@ def assertUnchangedItemsOnResave(self, doc): def test_putaway_rules_priority(self): """Test if rule is applied by priority, irrespective of free space.""" - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg") rule_2 = create_putaway_rule( item_code="_Rice", warehouse=self.warehouse_2, capacity=300, uom="Kg", priority=2 ) @@ -69,17 +67,11 @@ def test_putaway_rules_priority(self): def test_putaway_rules_with_same_priority(self): """Test if rule with more free space is applied, among two rules with same priority and capacity.""" - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=500, uom="Kg" - ) - rule_2 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_2, capacity=500, uom="Kg" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=500, uom="Kg") + rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=500, uom="Kg") # out of 500 kg capacity, occupy 100 kg in warehouse_1 - stock_receipt = make_stock_entry( - item_code="_Rice", target=self.warehouse_1, qty=100, basic_rate=50 - ) + stock_receipt = make_stock_entry(item_code="_Rice", target=self.warehouse_1, qty=100, basic_rate=50) pr = make_purchase_receipt(item_code="_Rice", qty=700, apply_putaway_rule=1, do_not_submit=1) self.assertEqual(len(pr.items), 2) @@ -97,12 +89,8 @@ def test_putaway_rules_with_same_priority(self): def test_putaway_rules_with_insufficient_capacity(self): """Test if qty exceeding capacity, is handled.""" - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=100, uom="Kg" - ) - rule_2 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_2, capacity=200, uom="Kg" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=100, uom="Kg") + rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=200, uom="Kg") pr = make_purchase_receipt(item_code="_Rice", qty=350, apply_putaway_rule=1, do_not_submit=1) self.assertEqual(len(pr.items), 2) @@ -123,19 +111,13 @@ def test_putaway_rules_multi_uom(self): item.append("uoms", {"uom": "Bag", "conversion_factor": 1000}) item.save() - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=3, uom="Bag" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=3, uom="Bag") self.assertEqual(rule_1.stock_capacity, 3000) - rule_2 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_2, capacity=4, uom="Bag" - ) + rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=4, uom="Bag") self.assertEqual(rule_2.stock_capacity, 4000) # populate 'Rack 1' with 1 Bag, making the free space 2 Bags - stock_receipt = make_stock_entry( - item_code="_Rice", target=self.warehouse_1, qty=1000, basic_rate=50 - ) + stock_receipt = make_stock_entry(item_code="_Rice", target=self.warehouse_1, qty=1000, basic_rate=50) pr = make_purchase_receipt( item_code="_Rice", @@ -167,9 +149,7 @@ def test_putaway_rules_multi_uom_whole_uom(self): frappe.db.set_value("UOM", "Bag", "must_be_whole_number", 1) # Putaway Rule in different UOM - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=1, uom="Bag" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=1, uom="Bag") self.assertEqual(rule_1.stock_capacity, 1000) # Putaway Rule in Stock UOM rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=500) @@ -199,9 +179,7 @@ def test_putaway_rules_multi_uom_whole_uom(self): def test_putaway_rules_with_reoccurring_item(self): """Test rules on same item entered multiple times with different rate.""" - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg") # total capacity is 200 Kg pr = make_purchase_receipt(item_code="_Rice", qty=100, apply_putaway_rule=1, do_not_submit=1) @@ -237,9 +215,7 @@ def test_putaway_rules_with_reoccurring_item(self): def test_validate_over_receipt_in_warehouse(self): """Test if overreceipt is blocked in the presence of putaway rules.""" - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg") pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1, do_not_submit=1) self.assertEqual(len(pr.items), 1) @@ -291,9 +267,7 @@ def test_putaway_rule_on_stock_entry_material_transfer(self): def test_putaway_rule_on_stock_entry_material_transfer_reoccuring_item(self): """Test if reoccuring item is correctly considered.""" - rule_1 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_1, capacity=300, uom="Kg" - ) + rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=300, uom="Kg") rule_2 = create_putaway_rule( item_code="_Rice", warehouse=self.warehouse_2, capacity=600, uom="Kg", priority=2 ) @@ -428,9 +402,7 @@ def test_putaway_rule_on_stock_entry_material_receipt(self): rule_1 = create_putaway_rule( item_code="_Rice", warehouse=self.warehouse_1, capacity=200, uom="Kg" ) # more capacity - rule_2 = create_putaway_rule( - item_code="_Rice", warehouse=self.warehouse_2, capacity=100, uom="Kg" - ) + rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=100, uom="Kg") stock_entry = make_stock_entry( item_code="_Rice", @@ -480,9 +452,7 @@ def create_putaway_rule(**args): putaway.capacity = args.capacity or 1 putaway.stock_uom = frappe.db.get_value("Item", putaway.item_code, "stock_uom") putaway.uom = args.uom or putaway.stock_uom - putaway.conversion_factor = get_conversion_factor(putaway.item_code, putaway.uom)[ - "conversion_factor" - ] + putaway.conversion_factor = get_conversion_factor(putaway.item_code, putaway.uom)["conversion_factor"] if not args.do_not_save: putaway.save() diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 002f7bf8a8c9..feb2844aec0f 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -82,13 +82,11 @@ def update_qc_reference(self): if self.reference_type == "Job Card": if self.reference_name: frappe.db.sql( - """ - UPDATE `tab{doctype}` + f""" + UPDATE `tab{self.reference_type}` SET quality_inspection = %s, modified = %s WHERE name = %s and production_item = %s - """.format( - doctype=self.reference_type - ), + """, (quality_inspection, self.modified, self.reference_name, self.item_code), ) @@ -110,9 +108,9 @@ def update_qc_reference(self): args.append(self.name) frappe.db.sql( - """ + f""" UPDATE - `tab{child_doc}` t1, `tab{parent_doc}` t2 + `tab{doctype}` t1, `tab{self.reference_type}` t2 SET t1.quality_inspection = %s, t2.modified = %s WHERE @@ -120,9 +118,7 @@ def update_qc_reference(self): and t1.item_code = %s and t1.parent = t2.name {conditions} - """.format( - parent_doc=self.reference_type, child_doc=doctype, conditions=conditions - ), + """, args, ) @@ -180,9 +176,9 @@ def set_status_based_on_acceptance_formula(self, reading): except NameError as e: field = frappe.bold(e.args[0].split()[1]) frappe.throw( - _("Row #{0}: {1} is not a valid reading field. Please refer to the field description.").format( - reading.idx, field - ), + _( + "Row #{0}: {1} is not a valid reading field. Please refer to the field description." + ).format(reading.idx, field), title=_("Invalid Formula"), ) except Exception: @@ -251,40 +247,26 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): qi_condition = "" return frappe.db.sql( - """ + f""" SELECT item_code - FROM `tab{doc}` + FROM `tab{from_doctype}` WHERE parent=%(parent)s and docstatus < 2 and item_code like %(txt)s {qi_condition} {cond} {mcond} - ORDER BY item_code limit {page_len} offset {start} - """.format( - doc=from_doctype, - cond=cond, - mcond=mcond, - start=cint(start), - page_len=cint(page_len), - qi_condition=qi_condition, - ), + ORDER BY item_code limit {cint(page_len)} offset {cint(start)} + """, {"parent": filters.get("parent"), "txt": "%%%s%%" % txt}, ) elif filters.get("reference_name"): return frappe.db.sql( - """ + f""" SELECT production_item - FROM `tab{doc}` + FROM `tab{from_doctype}` WHERE name = %(reference_name)s and docstatus < 2 and production_item like %(txt)s {qi_condition} {cond} {mcond} ORDER BY production_item - limit {page_len} offset {start} - """.format( - doc=from_doctype, - cond=cond, - mcond=mcond, - start=cint(start), - page_len=cint(page_len), - qi_condition=qi_condition, - ), + limit {cint(page_len)} offset {cint(start)} + """, {"reference_name": filters.get("reference_name"), "txt": "%%%s%%" % txt}, ) diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py index 9eeb4602ab60..40feaccf08c0 100644 --- a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py @@ -159,9 +159,7 @@ def test_rejected_qi_validation(self): do_not_submit=True, ) - readings = [ - {"specification": "Iron Content", "min_value": 0.1, "max_value": 0.9, "reading_1": "1.0"} - ] + readings = [{"specification": "Iron Content", "min_value": 0.1, "max_value": 0.9, "reading_1": "1.0"}] qa = create_quality_inspection( reference_type="Stock Entry", reference_name=se.name, readings=readings, status="Rejected" 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 846be0b9bdcd..15c692f3a072 100644 --- a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py +++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py @@ -17,17 +17,13 @@ class QuickStockBalance(Document): def get_stock_item_details(warehouse, date, item=None, barcode=None): out = {} if barcode: - out["item"] = frappe.db.get_value( - "Item Barcode", filters={"barcode": barcode}, fieldname=["parent"] - ) + out["item"] = frappe.db.get_value("Item Barcode", filters={"barcode": barcode}, fieldname=["parent"]) if not out["item"]: frappe.throw(_("Invalid Barcode. There is no Item attached to this barcode.")) else: out["item"] = item - barcodes = frappe.db.get_values( - "Item Barcode", filters={"parent": out["item"]}, fieldname=["barcode"] - ) + barcodes = frappe.db.get_values("Item Barcode", filters={"parent": out["item"]}, fieldname=["barcode"]) out["barcodes"] = [x[0] for x in barcodes] out["qty"] = get_stock_balance(out["item"], warehouse, date) 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 4d3e9f0aaf65..e47c1f8aba7e 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -117,15 +117,12 @@ def validate_accounts_freeze(self): if not acc_settings.acc_frozen_upto: return if getdate(self.posting_date) <= getdate(acc_settings.acc_frozen_upto): - if ( + if acc_settings.frozen_accounts_modifier and frappe.session.user in get_users_with_role( acc_settings.frozen_accounts_modifier - and frappe.session.user in get_users_with_role(acc_settings.frozen_accounts_modifier) ): frappe.msgprint(_("Caution: This might alter frozen accounts.")) return - frappe.throw( - _("You cannot repost item valuation before {}").format(acc_settings.acc_frozen_upto) - ) + frappe.throw(_("You cannot repost item valuation before {}").format(acc_settings.acc_frozen_upto)) def reset_field_values(self): if self.based_on == "Transaction": diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py index aa90ff03a828..56b960fb59b6 100644 --- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py @@ -179,7 +179,6 @@ def _assert_status(doc, status): riv3.set_status("Skipped") def test_stock_freeze_validation(self): - today = nowdate() riv = frappe.get_doc( diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 71b2faa41dee..50f476878282 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -3,7 +3,6 @@ import json -from typing import List, Optional, Union import frappe from frappe import ValidationError, _ @@ -66,7 +65,7 @@ class SerialNoDuplicateError(ValidationError): class SerialNo(StockController): def __init__(self, *args, **kwargs): - super(SerialNo, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.via_stock_ledger = False def validate(self): @@ -123,9 +122,7 @@ def validate_item(self): """ item = frappe.get_cached_doc("Item", self.item_code) if item.has_serial_no != 1: - frappe.throw( - _("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code) - ) + frappe.throw(_("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code)) self.item_group = item.item_group self.description = item.description @@ -301,7 +298,8 @@ def validate_serial_no(sle, item_det): if len(serial_nos) != len(set(serial_nos)): frappe.throw( - _("Duplicate Serial No entered for Item {0}").format(sle.item_code), SerialNoDuplicateError + _("Duplicate Serial No entered for Item {0}").format(sle.item_code), + SerialNoDuplicateError, ) allow_existing_serial_no = cint( @@ -337,7 +335,9 @@ def validate_serial_no(sle, item_det): if sr.item_code != sle.item_code: if not allow_serial_nos_with_different_item(serial_no, sle): frappe.throw( - _("Serial No {0} does not belong to Item {1}").format(serial_no, sle.item_code), + _("Serial No {0} does not belong to Item {1}").format( + serial_no, sle.item_code + ), SerialNoItemError, ) @@ -362,7 +362,9 @@ def validate_serial_no(sle, item_det): frappe.throw(_(msg), SerialNoDuplicateError) if cint(sle.actual_qty) > 0 and has_serial_no_exists(sr, sle): - doc_name = frappe.bold(get_link_to_form(sr.purchase_document_type, sr.purchase_document_no)) + doc_name = frappe.bold( + get_link_to_form(sr.purchase_document_type, sr.purchase_document_no) + ) frappe.throw( _("Serial No {0} has already been received in the {1} #{2}").format( frappe.bold(serial_no), sr.purchase_document_type, doc_name @@ -375,25 +377,32 @@ def validate_serial_no(sle, item_det): and sle.voucher_type not in ["Stock Entry", "Stock Reconciliation"] and sle.voucher_type == sr.delivery_document_type ): - return_against = frappe.db.get_value(sle.voucher_type, sle.voucher_no, "return_against") + return_against = frappe.db.get_value( + sle.voucher_type, sle.voucher_no, "return_against" + ) if return_against and return_against != sr.delivery_document_no: frappe.throw(_("Serial no {0} has been already returned").format(sr.name)) if cint(sle.actual_qty) < 0: if sr.warehouse != sle.warehouse: frappe.throw( - _("Serial No {0} does not belong to Warehouse {1}").format(serial_no, sle.warehouse), + _("Serial No {0} does not belong to Warehouse {1}").format( + serial_no, sle.warehouse + ), SerialNoWarehouseError, ) if not sr.purchase_document_no: - frappe.throw(_("Serial No {0} not in stock").format(serial_no), SerialNoNotExistsError) + frappe.throw( + _("Serial No {0} not in stock").format(serial_no), SerialNoNotExistsError + ) if sle.voucher_type in ("Delivery Note", "Sales Invoice"): - if sr.batch_no and sr.batch_no != sle.batch_no: frappe.throw( - _("Serial No {0} does not belong to Batch {1}").format(serial_no, sle.batch_no), + _("Serial No {0} does not belong to Batch {1}").format( + serial_no, sle.batch_no + ), SerialNoBatchError, ) @@ -408,7 +417,11 @@ def validate_serial_no(sle, item_det): if sle.voucher_type == "Sales Invoice": if not frappe.db.exists( "Sales Invoice Item", - {"parent": sle.voucher_no, "item_code": sle.item_code, "sales_order": sr.sales_order}, + { + "parent": sle.voucher_no, + "item_code": sle.item_code, + "sales_order": sr.sales_order, + }, ): frappe.throw( _( @@ -431,7 +444,11 @@ def validate_serial_no(sle, item_det): ) if not invoice or frappe.db.exists( "Sales Invoice Item", - {"parent": invoice, "item_code": sle.item_code, "sales_order": sr.sales_order}, + { + "parent": invoice, + "item_code": sle.item_code, + "sales_order": sr.sales_order, + }, ): frappe.throw( _( @@ -467,7 +484,9 @@ def validate_serial_no(sle, item_det): {"parent": sales_invoice, "item_code": sle.item_code}, "sales_order", ) - if sales_order and get_reserved_qty_for_so(sales_order, sle.item_code): + if sales_order and get_reserved_qty_for_so( + sales_order, sle.item_code + ): validate_so_serial_no(sr, sales_order) elif cint(sle.actual_qty) < 0: # transfer out @@ -483,9 +502,7 @@ def validate_serial_no(sle, item_det): def check_serial_no_validity_on_cancel(serial_no, sle): - sr = frappe.db.get_value( - "Serial No", serial_no, ["name", "warehouse", "company", "status"], as_dict=1 - ) + sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse", "company", "status"], as_dict=1) sr_link = frappe.utils.get_link_to_form("Serial No", serial_no) doc_link = frappe.utils.get_link_to_form(sle.voucher_type, sle.voucher_no) actual_qty = cint(sle.actual_qty) @@ -538,9 +555,7 @@ def validate_so_serial_no(sr, sales_order): def has_serial_no_exists(sn, sle): - if ( - sn.warehouse and not sle.skip_serial_no_validaiton and sle.voucher_type != "Stock Reconciliation" - ): + if sn.warehouse and not sle.skip_serial_no_validaiton and sle.voucher_type != "Stock Reconciliation": return True if sn.company != sle.company: @@ -584,7 +599,7 @@ def update_serial_nos(sle, item_det): def get_auto_serial_nos(serial_no_series, qty): serial_nos = [] - for i in range(cint(qty)): + for _i in range(cint(qty)): serial_nos.append(get_new_serial_number(serial_no_series)) return "\n".join(serial_nos) @@ -634,13 +649,11 @@ def auto_make_serial_nos(args): def get_items_html(serial_nos, item_code): body = ", ".join(serial_nos) - return """
    - {0}: {1} Serial Numbers + return f"""
    + {item_code}: {len(serial_nos)} Serial Numbers -
    {2}
    - """.format( - item_code, len(serial_nos), body - ) +
    {body}
    + """ def get_item_details(item_code): @@ -657,9 +670,7 @@ def get_serial_nos(serial_no): if isinstance(serial_no, list): return serial_no - return [ - s.strip() for s in cstr(serial_no).strip().upper().replace(",", "\n").split("\n") if s.strip() - ] + return [s.strip() for s in cstr(serial_no).strip().upper().replace(",", "\n").split("\n") if s.strip()] def clean_serial_no_string(serial_no: str) -> str: @@ -779,11 +790,9 @@ def update_maintenance_status(): def get_delivery_note_serial_no(item_code, qty, delivery_note): serial_nos = "" dn_serial_nos = frappe.db.sql_list( - """ select name from `tabSerial No` + f""" select name from `tabSerial No` where item_code = %(item_code)s and delivery_document_no = %(delivery_note)s - and sales_invoice is null limit {0}""".format( - cint(qty) - ), + and sales_invoice is null limit {cint(qty)}""", {"item_code": item_code, "delivery_note": delivery_note}, ) @@ -798,12 +807,11 @@ def auto_fetch_serial_number( qty: int, item_code: str, warehouse: str, - posting_date: Optional[str] = None, - batch_nos: Optional[Union[str, List[str]]] = None, - for_doctype: Optional[str] = None, + posting_date: str | None = None, + batch_nos: str | list[str] | None = None, + for_doctype: str | None = None, exclude_sr_nos=None, -) -> List[str]: - +) -> list[str]: filters = frappe._dict({"item_code": item_code, "warehouse": warehouse}) if exclude_sr_nos is None: diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.py b/erpnext/stock/doctype/serial_no/test_serial_no.py index 68623fba11ee..612905e40745 100644 --- a/erpnext/stock/doctype/serial_no/test_serial_no.py +++ b/erpnext/stock/doctype/serial_no/test_serial_no.py @@ -248,16 +248,12 @@ def test_correct_serial_no_incoming_rate(self): warehouse = "_Test Warehouse - _TC" serial_nos = ["LOWVALUATION", "HIGHVALUATION"] - in1 = make_stock_entry( - item_code=item_code, to_warehouse=warehouse, qty=1, rate=42, serial_no=serial_nos[0] - ) - in2 = make_stock_entry( + make_stock_entry(item_code=item_code, to_warehouse=warehouse, qty=1, rate=42, serial_no=serial_nos[0]) + make_stock_entry( item_code=item_code, to_warehouse=warehouse, qty=1, rate=113, serial_no=serial_nos[1] ) - out = create_delivery_note( - item_code=item_code, qty=1, serial_no=serial_nos[0], do_not_submit=True - ) + out = create_delivery_note(item_code=item_code, qty=1, serial_no=serial_nos[0], do_not_submit=True) # change serial no out.items[0].serial_no = serial_nos[1] diff --git a/erpnext/stock/doctype/shipment/test_shipment.py b/erpnext/stock/doctype/shipment/test_shipment.py index 726dff4f313d..4d4eadc339b1 100644 --- a/erpnext/stock/doctype/shipment/test_shipment.py +++ b/erpnext/stock/doctype/shipment/test_shipment.py @@ -76,9 +76,7 @@ def create_test_shipment(delivery_notes=None): shipment.description_of_content = "unit test entry" for delivery_note in delivery_notes: shipment.append("shipment_delivery_note", {"delivery_note": delivery_note.name}) - shipment.append( - "shipment_parcel", {"length": 5, "width": 5, "height": 5, "weight": 5, "count": 5} - ) + shipment.append("shipment_parcel", {"length": 5, "width": 5, "height": 5, "weight": 5, "count": 5}) shipment.insert() return shipment @@ -96,9 +94,7 @@ def get_shipment_customer_contact(customer_name): def get_shipment_customer_address(customer_name): address_title = customer_name + " address 123" - customer_address = frappe.get_all( - "Address", fields=["name"], filters={"address_title": address_title} - ) + customer_address = frappe.get_all("Address", fields=["name"], filters={"address_title": address_title}) if len(customer_address): return customer_address[0] else: @@ -160,9 +156,7 @@ def create_customer_contact(fname, lname): customer.is_primary_contact = 1 customer.is_billing_contact = 1 customer.append("email_ids", {"email_id": "randomme@email.com", "is_primary": 1}) - customer.append( - "phone_nos", {"phone": "123123123", "is_primary_phone": 1, "is_primary_mobile_no": 1} - ) + customer.append("phone_nos", {"phone": "123123123", "is_primary_phone": 1, "is_primary_mobile_no": 1}) customer.status = "Passive" customer.insert() return customer diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 81658c42e91c..2e1ec6869145 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -68,7 +68,7 @@ class MaxSampleAlreadyRetainedError(frappe.ValidationError): class StockEntry(StockController): def __init__(self, *args, **kwargs): - super(StockEntry, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.purchase_order: self.subcontract_data = frappe._dict( { @@ -98,9 +98,7 @@ def onload(self): def before_validate(self): from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule - apply_rule = self.apply_putaway_rule and ( - self.purpose in ["Material Transfer", "Material Receipt"] - ) + apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"]) if self.get("items") and apply_rule: apply_putaway_rule(self.doctype, self.get("items"), self.company, purpose=self.purpose) @@ -268,7 +266,11 @@ def delete_linked_stock_entry(self): if self.purpose == "Send to Warehouse": for d in frappe.get_all( "Stock Entry", - filters={"docstatus": 0, "outgoing_stock_entry": self.name, "purpose": "Receive at Warehouse"}, + filters={ + "docstatus": 0, + "outgoing_stock_entry": self.name, + "purpose": "Receive at Warehouse", + }, ): frappe.delete_doc("Stock Entry", d.name) @@ -422,7 +424,7 @@ def validate_fg_completed_qty(self): return precision = frappe.get_precision("Stock Entry Detail", "qty") - fg_item = list(fg_qty.keys())[0] + fg_item = next(iter(fg_qty.keys())) fg_item_qty = flt(fg_qty[fg_item], precision) fg_completed_qty = flt(self.fg_completed_qty, precision) @@ -605,14 +607,13 @@ def check_duplicate_entry_for_work_order(self): production_item, qty = frappe.db.get_value( "Work Order", self.work_order, ["production_item", "qty"] ) - args = other_ste + [production_item] + args = [*other_ste, production_item] fg_qty_already_entered = frappe.db.sql( """select sum(transfer_qty) from `tabStock Entry Detail` - where parent in (%s) - and item_code = %s - and ifnull(s_warehouse,'')='' """ - % (", ".join(["%s" * len(other_ste)]), "%s"), + where parent in ({}) + and item_code = {} + and ifnull(s_warehouse,'')='' """.format(", ".join(["%s" * len(other_ste)]), "%s"), args, )[0][0] if fg_qty_already_entered and fg_qty_already_entered >= qty: @@ -690,9 +691,7 @@ def set_basic_rate(self, reset_outgoing_rate=True, raise_error_if_no_rate=True): Set rate for outgoing, scrapped and finished items """ # Set rate for outgoing items - outgoing_items_cost = self.set_rate_for_outgoing_items( - reset_outgoing_rate, raise_error_if_no_rate - ) + outgoing_items_cost = self.set_rate_for_outgoing_items(reset_outgoing_rate, raise_error_if_no_rate) finished_item_qty = sum(d.transfer_qty for d in self.items if d.is_finished_item) items = [] @@ -856,8 +855,6 @@ def set_purpose_for_stock_entry(self): self.purpose = frappe.get_cached_value("Stock Entry Type", self.stock_entry_type, "purpose") def validate_duplicate_serial_no(self): - warehouse_wise_serial_nos = {} - # In case of repack the source and target serial nos could be same for warehouse in ["s_warehouse", "t_warehouse"]: serial_nos = [] @@ -895,13 +892,17 @@ def validate_subcontract_order(self): item_code = se_item.original_item or se_item.item_code precision = cint(frappe.db.get_default("float_precision")) or 3 required_qty = sum( - [flt(d.required_qty) for d in subcontract_order.supplied_items if d.rm_item_code == item_code] + [ + flt(d.required_qty) + for d in subcontract_order.supplied_items + if d.rm_item_code == item_code + ] ) total_allowed = required_qty + (required_qty * (qty_allowance / 100)) if not required_qty: - bom_no = frappe.db.get_value( + frappe.db.get_value( f"{self.subcontract_data.order_doctype} Item", { "parent": self.get(self.subcontract_data.order_field), @@ -947,7 +948,10 @@ def validate_subcontract_order(self): & (se.docstatus == 1) & (se_detail.item_code == se_item.item_code) & ( - ((se.purchase_order == self.purchase_order) & (se_detail.po_detail == se_item.po_detail)) + ( + (se.purchase_order == self.purchase_order) + & (se_detail.po_detail == se_item.po_detail) + ) if self.subcontract_data.order_doctype == "Purchase Order" else ( (se.subcontracting_order == self.subcontracting_order) @@ -1000,7 +1004,9 @@ def validate_subcontract_order(self): else: if not se_item.allow_alternative_item: frappe.throw( - _("Row {0}# Item {1} not found in 'Raw Materials Supplied' table in {2} {3}").format( + _( + "Row {0}# Item {1} not found in 'Raw Materials Supplied' table in {2} {3}" + ).format( se_item.idx, se_item.item_code, self.subcontract_data.order_doctype, @@ -1187,12 +1193,18 @@ def get_sle_for_source_warehouse(self, sl_entries, finished_item_row): for d in self.get("items"): if cstr(d.s_warehouse): sle = self.get_sl_entries( - d, {"warehouse": cstr(d.s_warehouse), "actual_qty": -flt(d.transfer_qty), "incoming_rate": 0} + d, + { + "warehouse": cstr(d.s_warehouse), + "actual_qty": -flt(d.transfer_qty), + "incoming_rate": 0, + }, ) if cstr(d.t_warehouse): sle.dependant_sle_voucher_detail_no = d.name elif finished_item_row and ( - finished_item_row.item_code != d.item_code or finished_item_row.t_warehouse != d.s_warehouse + finished_item_row.item_code != d.item_code + or finished_item_row.t_warehouse != d.s_warehouse ): sle.dependant_sle_voucher_detail_no = finished_item_row.name @@ -1215,7 +1227,7 @@ def get_sle_for_target_warehouse(self, sl_entries, finished_item_row): sl_entries.append(sle) def get_gl_entries(self, warehouse_account): - gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account) + gl_entries = super().get_gl_entries(warehouse_account) if self.purpose in ("Repack", "Manufacture"): total_basic_amount = sum(flt(t.basic_amount) for t in self.get("items") if t.is_finished_item) @@ -1248,9 +1260,9 @@ def get_gl_entries(self, warehouse_account): flt(t.amount * multiply_based_on) / divide_based_on ) - item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account]["base_amount"] += ( - flt(t.base_amount * multiply_based_on) / divide_based_on - ) + item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account][ + "base_amount" + ] += flt(t.base_amount * multiply_based_on) / divide_based_on if item_account_wise_additional_cost: for d in self.get("items"): @@ -1282,7 +1294,9 @@ def get_gl_entries(self, warehouse_account): "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": -1 - * amount["base_amount"], # put it as negative credit instead of debit purposefully + * amount[ + "base_amount" + ], # put it as negative credit instead of debit purposefully }, item=d, ) @@ -1415,7 +1429,10 @@ def get_item_details(self, args=None, for_update=False): ): subcontract_items = frappe.get_all( self.subcontract_data.order_supplied_items_field, - {"parent": self.get(self.subcontract_data.order_field), "rm_item_code": args.get("item_code")}, + { + "parent": self.get(self.subcontract_data.order_field), + "rm_item_code": args.get("item_code"), + }, "main_item_code", ) @@ -1465,7 +1482,6 @@ def get_items(self): ) if self.bom_no: - backflush_based_on = frappe.db.get_single_value( "Manufacturing Settings", "backflush_raw_materials_based_on" ) @@ -1479,7 +1495,6 @@ def get_items(self): "Material Transfer for Manufacture", "Material Consumption for Manufacture", ]: - if self.work_order and self.purpose == "Material Transfer for Manufacture": item_dict = self.get_pending_raw_materials(backflush_based_on) if self.to_warehouse and self.pro_doc: @@ -1489,7 +1504,10 @@ def get_items(self): elif ( self.work_order - and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture") + and ( + self.purpose == "Manufacture" + or self.purpose == "Material Consumption for Manufacture" + ) and not self.pro_doc.skip_transfer and self.flags.backflush_based_on == "Material Transferred for Manufacture" ): @@ -1497,7 +1515,10 @@ def get_items(self): elif ( self.work_order - and (self.purpose == "Manufacture" or self.purpose == "Material Consumption for Manufacture") + and ( + self.purpose == "Manufacture" + or self.purpose == "Material Consumption for Manufacture" + ) and self.flags.backflush_based_on == "BOM" and frappe.db.get_single_value("Manufacturing Settings", "material_consumption") == 1 ): @@ -1510,7 +1531,10 @@ def get_items(self): item_dict = self.get_bom_raw_materials(self.fg_completed_qty) # Get Subcontract Order Supplied Items Details - if self.get(self.subcontract_data.order_field) and self.purpose == "Send to Subcontractor": + if ( + self.get(self.subcontract_data.order_field) + and self.purpose == "Send to Subcontractor" + ): # Get Subcontract Order Supplied Items Details parent = frappe.qb.DocType(self.subcontract_data.order_doctype) child = frappe.qb.DocType(self.subcontract_data.order_supplied_items_field) @@ -1529,9 +1553,14 @@ def get_items(self): if self.pro_doc and cint(self.pro_doc.from_wip_warehouse): item["from_warehouse"] = self.pro_doc.wip_warehouse # Get Reserve Warehouse from Subcontract Order - if self.get(self.subcontract_data.order_field) and self.purpose == "Send to Subcontractor": + if ( + self.get(self.subcontract_data.order_field) + and self.purpose == "Send to Subcontractor" + ): item["from_warehouse"] = item_wh.get(item.item_code) - item["to_warehouse"] = self.to_warehouse if self.purpose == "Send to Subcontractor" else "" + item["to_warehouse"] = ( + self.to_warehouse if self.purpose == "Send to Subcontractor" else "" + ) self.add_to_stock_entry_detail(item_dict) @@ -1727,9 +1756,7 @@ def get_bom_scrap_material(self, qty): from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict if ( - frappe.db.get_single_value( - "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies" - ) + frappe.db.get_single_value("Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies") and self.work_order and frappe.get_cached_value("Work Order", self.work_order, "use_multi_level_bom") ): @@ -1885,7 +1912,7 @@ def add_transfered_raw_materials_in_items(self) -> None: as_dict=1, ) - for key, row in available_materials.items(): + for _key, row in available_materials.items(): remaining_qty_to_produce = flt(wo_data.trans_qty) - flt(wo_data.produced_qty) if remaining_qty_to_produce <= 0 and not self.is_return: continue @@ -2029,9 +2056,7 @@ def get_pro_order_required_items(self, backflush_based_on=None): continue transfer_pending = flt(d.required_qty) > flt(d.transferred_qty) - can_transfer = transfer_pending or ( - backflush_based_on == "Material Transferred for Manufacture" - ) + can_transfer = transfer_pending or (backflush_based_on == "Material Transferred for Manufacture") if not can_transfer: continue @@ -2046,7 +2071,9 @@ def get_pro_order_required_items(self, backflush_based_on=None): ) item_row["job_card_item"] = job_card_item or None - if d.source_warehouse and not frappe.db.get_value("Warehouse", d.source_warehouse, "is_group"): + if d.source_warehouse and not frappe.db.get_value( + "Warehouse", d.source_warehouse, "is_group" + ): item_row["from_warehouse"] = d.source_warehouse item_row["to_warehouse"] = wip_warehouse @@ -2101,9 +2128,9 @@ def add_to_stock_entry_detail(self, item_dict, bom_no=None): if item_row.get(field): se_child.set(field, item_row.get(field)) - if se_child.s_warehouse == None: + if se_child.s_warehouse is None: se_child.s_warehouse = self.from_warehouse - if se_child.t_warehouse == None: + if se_child.t_warehouse is None: se_child.t_warehouse = self.to_warehouse # in stock uom @@ -2159,15 +2186,20 @@ def validate_batch(self): expiry_date = frappe.db.get_value("Batch", item.batch_no, "expiry_date") if expiry_date: if getdate(self.posting_date) > getdate(expiry_date): - frappe.throw(_("Batch {0} of Item {1} has expired.").format(item.batch_no, item.item_code)) + frappe.throw( + _("Batch {0} of Item {1} has expired.").format( + item.batch_no, item.item_code + ) + ) else: - frappe.throw(_("Batch {0} of Item {1} is disabled.").format(item.batch_no, item.item_code)) + frappe.throw( + _("Batch {0} of Item {1} is disabled.").format(item.batch_no, item.item_code) + ) def update_subcontract_order_supplied_items(self): if self.get(self.subcontract_data.order_field) and ( self.purpose in ["Send to Subcontractor", "Material Transfer"] or self.is_return ): - # Get Subcontract Order Supplied Items Details order_supplied_items = frappe.db.get_all( self.subcontract_data.order_supplied_items_field, @@ -2268,8 +2300,8 @@ def update_transferred_qty(self): cond = "" for data, transferred_qty in stock_entries.items(): - cond += """ WHEN (parent = %s and name = %s) THEN %s - """ % ( + cond += """ WHEN (parent = {} and name = {}) THEN {} + """.format( frappe.db.escape(data[0]), frappe.db.escape(data[1]), transferred_qty, @@ -2325,7 +2357,9 @@ def set_material_request_transfer_status(self, status): material_request = item.material_request or None if self.purpose == "Material Transfer" and material_request not in material_requests: if self.outgoing_stock_entry and parent_se: - material_request = frappe.get_value("Stock Entry Detail", item.ste_detail, "material_request") + material_request = frappe.get_value( + "Stock Entry Detail", item.ste_detail, "material_request" + ) if material_request and material_request not in material_requests: material_requests.append(material_request) @@ -2530,9 +2564,7 @@ def get_operating_cost_per_unit(work_order=None, bom_no=None): ) ) ): - operating_cost_per_unit += flt(work_order.corrective_operation_cost) / flt( - work_order.produced_qty - ) + operating_cost_per_unit += flt(work_order.corrective_operation_cost) / flt(work_order.produced_qty) return operating_cost_per_unit @@ -2545,24 +2577,20 @@ def get_used_alternative_items( if subcontract_order: cond = f"and ste.purpose = 'Send to Subcontractor' and ste.{subcontract_order_field} = '{subcontract_order}'" elif work_order: - cond = "and ste.purpose = 'Material Transfer for Manufacture' and ste.work_order = '{0}'".format( - work_order - ) + cond = f"and ste.purpose = 'Material Transfer for Manufacture' and ste.work_order = '{work_order}'" if not cond: return {} used_alternative_items = {} data = frappe.db.sql( - """ select sted.original_item, sted.uom, sted.conversion_factor, + f""" select sted.original_item, sted.uom, sted.conversion_factor, sted.item_code, sted.item_name, sted.conversion_factor,sted.stock_uom, sted.description from `tabStock Entry` ste, `tabStock Entry Detail` sted where sted.parent = ste.name and ste.docstatus = 1 and sted.original_item != sted.item_code - {0} """.format( - cond - ), + {cond} """, as_dict=1, ) @@ -2600,9 +2628,7 @@ def get_uom_details(item_code, uom, qty): conversion_factor = get_conversion_factor(item_code, uom).get("conversion_factor") if not conversion_factor: - frappe.msgprint( - _("UOM conversion factor required for UOM: {0} in Item: {1}").format(uom, item_code) - ) + frappe.msgprint(_("UOM conversion factor required for UOM: {0} in Item: {1}").format(uom, item_code)) ret = {"uom": ""} else: ret = { @@ -2712,9 +2738,7 @@ def get_supplied_items( else: supplied_item.supplied_qty += row.transfer_qty - supplied_item.total_supplied_qty = flt(supplied_item.supplied_qty) - flt( - supplied_item.returned_qty - ) + supplied_item.total_supplied_qty = flt(supplied_item.supplied_qty) - flt(supplied_item.returned_qty) return supplied_item_details @@ -2804,7 +2828,11 @@ def get_stock_entry_data(work_order): & (stock_entry_detail.s_warehouse.isnotnull()) & ( stock_entry.purpose.isin( - ["Manufacture", "Material Consumption for Manufacture", "Material Transfer for Manufacture"] + [ + "Manufacture", + "Material Consumption for Manufacture", + "Material Transfer for Manufacture", + ] ) ) ) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index 0f9001392df0..c3b8e3bc0b92 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -2,7 +2,7 @@ # See license.txt -from typing import TYPE_CHECKING, Optional, overload +from typing import TYPE_CHECKING, overload import frappe from frappe.utils import cint, flt @@ -18,15 +18,15 @@ def make_stock_entry( *, item_code: str, qty: float, - company: Optional[str] = None, - from_warehouse: Optional[str] = None, - to_warehouse: Optional[str] = None, - rate: Optional[float] = None, - serial_no: Optional[str] = None, - batch_no: Optional[str] = None, - posting_date: Optional[str] = None, - posting_time: Optional[str] = None, - purpose: Optional[str] = None, + company: str | None = None, + from_warehouse: str | None = None, + to_warehouse: str | None = None, + rate: float | None = None, + serial_no: str | None = None, + batch_no: str | None = None, + posting_date: str | None = None, + posting_time: str | None = None, + purpose: str | None = None, do_not_save: bool = False, do_not_submit: bool = False, inspection_required: bool = False, diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index c6814558ce17..d45207e23a00 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -5,7 +5,7 @@ import frappe from frappe.permissions import add_user_permission, remove_user_permission from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import add_days, add_to_date, flt, nowdate, nowtime, today +from frappe.utils import add_days, flt, nowdate, nowtime, today from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.stock.doctype.item.test_item import ( @@ -14,7 +14,7 @@ make_item_variant, set_item_variant_settings, ) -from erpnext.stock.doctype.serial_no.serial_no import * # noqa +from erpnext.stock.doctype.serial_no.serial_no import * from erpnext.stock.doctype.stock_entry.stock_entry import ( FinishedGoodError, make_stock_in_entry, @@ -35,7 +35,7 @@ def get_sle(**args): condition, values = "", [] for key, value in args.items(): condition += " and " if condition else " where " - condition += "`{0}`=%s".format(key) + condition += f"`{key}`=%s" values.append(value) return frappe.db.sql( @@ -136,8 +136,7 @@ def _test_auto_material_request( ) projected_qty = ( - frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "projected_qty") - or 0 + frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "projected_qty") or 0 ) frappe.db.set_value("Stock Settings", None, "auto_indent", 1) @@ -664,14 +663,10 @@ def test_serial_move(self): se.set_stock_entry_type() se.insert() se.submit() - self.assertTrue( - frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse 1 - _TC" - ) + self.assertTrue(frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse 1 - _TC") se.cancel() - self.assertTrue( - frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse - _TC" - ) + self.assertTrue(frappe.db.get_value("Serial No", serial_no, "warehouse"), "_Test Warehouse - _TC") def test_serial_warehouse_error(self): make_serialized_item(target_warehouse="_Test Warehouse 1 - _TC") @@ -719,9 +714,7 @@ def test_serial_batch_item_stock_entry(self): else: item = frappe.get_doc("Item", {"item_name": "Batched and Serialised Item"}) - se = make_stock_entry( - item_code=item.item_code, target="_Test Warehouse - _TC", qty=1, basic_rate=100 - ) + se = make_stock_entry(item_code=item.item_code, target="_Test Warehouse - _TC", qty=1, basic_rate=100) batch_no = se.items[0].batch_no serial_no = get_serial_nos(se.items[0].serial_no)[0] batch_qty = get_batch_qty(batch_no, "_Test Warehouse - _TC", item.item_code) @@ -797,7 +790,7 @@ def test_serial_batch_item_qty_deduction(self): self.assertEqual(frappe.db.get_value("Serial No", serial_no2, "status"), "Inactive") def test_warehouse_company_validation(self): - company = frappe.db.get_value("Warehouse", "_Test Warehouse 2 - _TC1", "company") + frappe.db.get_value("Warehouse", "_Test Warehouse 2 - _TC1", "company") frappe.get_doc("User", "test2@example.com").add_roles( "Sales User", "Sales Manager", "Stock User", "Stock Manager" ) @@ -903,12 +896,8 @@ def test_work_order(self): for d in stock_entry.get("items"): if d.item_code != "_Test FG Item 2": rm_cost += flt(d.amount) - fg_cost = list(filter(lambda x: x.item_code == "_Test FG Item 2", stock_entry.get("items")))[ - 0 - ].amount - self.assertEqual( - fg_cost, flt(rm_cost + bom_operation_cost + work_order.additional_operating_cost, 2) - ) + fg_cost = next(filter(lambda x: x.item_code == "_Test FG Item 2", stock_entry.get("items"))).amount + self.assertEqual(fg_cost, flt(rm_cost + bom_operation_cost + work_order.additional_operating_cost, 2)) @change_settings("Manufacturing Settings", {"material_consumption": 1}) def test_work_order_manufacture_with_material_consumption(self): @@ -951,8 +940,8 @@ def test_work_order_manufacture_with_material_consumption(self): for d in s.get("items"): if d.s_warehouse: rm_cost += d.amount - fg_cost = list(filter(lambda x: x.item_code == "_Test FG Item", s.get("items")))[0].amount - scrap_cost = list(filter(lambda x: x.is_scrap_item, s.get("items")))[0].amount + fg_cost = next(filter(lambda x: x.item_code == "_Test FG Item", s.get("items"))).amount + scrap_cost = next(filter(lambda x: x.is_scrap_item, s.get("items"))).amount self.assertEqual(fg_cost, flt(rm_cost - scrap_cost, 2)) # When Stock Entry has only FG + Scrap @@ -966,13 +955,11 @@ def test_work_order_manufacture_with_material_consumption(self): rm_cost += d.amount self.assertEqual(rm_cost, 0) expected_fg_cost = s.get_basic_rate_for_manufactured_item(1) - fg_cost = list(filter(lambda x: x.item_code == "_Test FG Item", s.get("items")))[0].amount + fg_cost = next(filter(lambda x: x.item_code == "_Test FG Item", s.get("items"))).amount self.assertEqual(flt(fg_cost, 2), flt(expected_fg_cost, 2)) def test_variant_work_order(self): - bom_no = frappe.db.get_value( - "BOM", {"item": "_Test Variant Item", "is_default": 1, "docstatus": 1} - ) + bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item", "is_default": 1, "docstatus": 1}) make_item_variant() # make variant of _Test Variant Item if absent @@ -1073,9 +1060,7 @@ def test_retain_sample(self): receipt_entry.insert() receipt_entry.submit() - retention_data = move_sample_to_retention_warehouse( - receipt_entry.company, receipt_entry.get("items") - ) + retention_data = move_sample_to_retention_warehouse(receipt_entry.company, receipt_entry.get("items")) retention_entry = frappe.new_doc("Stock Entry") retention_entry.company = retention_data.company retention_entry.purpose = retention_data.purpose @@ -1126,9 +1111,7 @@ def test_quality_check(self): self.assertRaises(frappe.ValidationError, repack.submit) def test_customer_provided_parts_se(self): - create_item( - "CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0 - ) + create_item("CUST-0987", is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0) se = make_stock_entry( item_code="CUST-0987", purpose="Material Receipt", qty=4, to_warehouse="_Test Warehouse - _TC" ) @@ -1243,9 +1226,7 @@ def test_total_basic_amount_zero(self): self.check_gl_entries( "Stock Entry", se.name, - sorted( - [["Stock Adjustment - TCP1", 100.0, 0.0], ["Miscellaneous Expenses - TCP1", 0.0, 100.0]] - ), + sorted([["Stock Adjustment - TCP1", 100.0, 0.0], ["Miscellaneous Expenses - TCP1", 0.0, 100.0]]), ) def test_conversion_factor_change(self): @@ -1409,7 +1390,7 @@ def test_future_negative_sle_batch(self): ) batch_nos.append(se2.items[0].batch_no) - with self.assertRaises(NegativeStockError) as nse: + with self.assertRaises(NegativeStockError): make_stock_entry( item_code=item_code, qty=1, @@ -1455,7 +1436,7 @@ def test_multi_batch_value_diff(self): item_code=item_code, qty=1, from_warehouse=warehouse, purpose="Material Issue", do_not_save=True ) issue.append("items", frappe.copy_doc(issue.items[0], ignore_no_copy=False)) - for row, batch_no in zip(issue.items, batch_nos): + for row, batch_no in zip(issue.items, batch_nos, strict=False): row.batch_no = batch_no issue.save() issue.submit() @@ -1663,15 +1644,12 @@ def test_batch_expiry(self): self.assertRaises(BatchExpiredError, se.save) def test_negative_stock_reco(self): - from erpnext.controllers.stock_controller import BatchExpiredError - from erpnext.stock.doctype.batch.test_batch import make_new_batch - frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 0) item_code = "Test Negative Item - 001" - item_doc = create_item(item_code=item_code, is_stock_item=1, valuation_rate=10) + create_item(item_code=item_code, is_stock_item=1, valuation_rate=10) - se1 = make_stock_entry( + make_stock_entry( item_code=item_code, posting_date=add_days(today(), -3), posting_time="00:00:00", @@ -1680,7 +1658,7 @@ def test_negative_stock_reco(self): to_warehouse="_Test Warehouse - _TC", ) - se2 = make_stock_entry( + make_stock_entry( item_code=item_code, posting_date=today(), posting_time="00:00:00", 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 da4f2c9db808..523a1d15cee2 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -222,7 +222,9 @@ def check_stock_frozen_date(self): ) if older_than_x_days_ago and stock_settings.stock_auth_role not in frappe.get_roles(): frappe.throw( - _("Not allowed to update stock transactions older than {0}").format(stock_frozen_upto_days), + _("Not allowed to update stock transactions older than {0}").format( + stock_frozen_upto_days + ), StockFreezeError, ) @@ -240,7 +242,9 @@ def validate_batch(self): expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date") if expiry_date: if getdate(self.posting_date) > getdate(expiry_date): - frappe.throw(_("Batch {0} of Item {1} has expired.").format(self.batch_no, self.item_code)) + frappe.throw( + _("Batch {0} of Item {1} has expired.").format(self.batch_no, self.item_code) + ) def validate_and_set_fiscal_year(self): if not self.fiscal_year: @@ -273,7 +277,7 @@ def validate_with_last_transaction_posting_time(self): (self.item_code, self.warehouse), )[0][0] - cur_doc_posting_datetime = "%s %s" % ( + cur_doc_posting_datetime = "{} {}".format( self.posting_date, self.get("posting_time") or "00:00:00", ) @@ -282,7 +286,9 @@ def validate_with_last_transaction_posting_time(self): last_transaction_time ): msg = _("Last Stock Transaction for item {0} under warehouse {1} was on {2}.").format( - frappe.bold(self.item_code), frappe.bold(self.warehouse), frappe.bold(last_transaction_time) + frappe.bold(self.item_code), + frappe.bold(self.warehouse), + frappe.bold(last_transaction_time), ) msg += "

    " + _( 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 6154910c2f11..80a44d902a36 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 @@ -8,7 +8,6 @@ import frappe from frappe.core.page.permission_manager.permission_manager import reset from frappe.custom.doctype.property_setter.property_setter import make_property_setter -from frappe.query_builder.functions import CombineDatetime from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, add_to_date, flt, today @@ -35,8 +34,7 @@ def setUp(self): # delete SLE and BINs for all items frappe.db.sql( - "delete from `tabStock Ledger Entry` where item_code in (%s)" - % (", ".join(["%s"] * len(items))), + "delete from `tabStock Ledger Entry` where item_code in (%s)" % (", ".join(["%s"] * len(items))), items, ) frappe.db.sql( @@ -122,7 +120,7 @@ def test_item_cost_reposting(self): self.assertEqual(finished_item_sle.get("valuation_rate"), 540) # Reconciliation for _Test Item for Reposting at Stores on 12-04-2020: Qty = 50, Rate = 150 - sr = create_stock_reconciliation( + create_stock_reconciliation( item_code="_Test Item for Reposting", warehouse="Stores - _TC", qty=50, @@ -484,7 +482,7 @@ def test_batchwise_item_valuation_moving_average(self): expected_incoming_rates = expected_abs_svd = [75, 125, 75, 125] self.assertEqual(expected_abs_svd, svd_list, "Incorrect 'Stock Value Difference' values") - for dn, incoming_rate in zip(dns, expected_incoming_rates): + for dn, incoming_rate in zip(dns, expected_incoming_rates, strict=False): self.assertEqual( dn.items[0].incoming_rate, incoming_rate, @@ -556,9 +554,7 @@ def test_batch_wise_valuation_across_warehouse(self): ], ) - reciept = make_stock_entry( - item_code=item_code, target=source, batch_no=batches[0], qty=5, rate=10 - ) + reciept = make_stock_entry(item_code=item_code, target=source, batch_no=batches[0], qty=5, rate=10) self.assertSLEs( reciept, [ @@ -680,9 +676,7 @@ def test_intermediate_average_batch_wise_valuation(self): ], ) - consume_today = make_stock_entry( - item_code=item_code, source=warehouse, batch_no=batches[0], qty=1 - ) + consume_today = make_stock_entry(item_code=item_code, source=warehouse, batch_no=batches[0], qty=1) self.assertSLEs( consume_today, [ @@ -715,8 +709,8 @@ def test_legacy_item_valuation_stock_entry(self): item, warehouses, batches = setup_item_valuation_test(use_batchwise_valuation=0) def check_sle_details_against_expected(sle_details, expected_sle_details, detail, columns): - for i, (sle_vals, ex_sle_vals) in enumerate(zip(sle_details, expected_sle_details)): - for col, sle_val, ex_sle_val in zip(columns, sle_vals, ex_sle_vals): + for i, (sle_vals, ex_sle_vals) in enumerate(zip(sle_details, expected_sle_details, strict=False)): + for col, sle_val, ex_sle_val in zip(columns, sle_vals, ex_sle_vals, strict=False): if col == "stock_queue": sle_val = get_stock_value_from_q(sle_val) ex_sle_val = get_stock_value_from_q(ex_sle_val) @@ -746,9 +740,7 @@ def check_sle_details_against_expected(sle_details, expected_sle_details, detail se_entry_list_mi = [ (item, warehouses[0], None, batches[1], 1, None, "2021-01-29"), ] - ses = create_stock_entry_entries_for_batchwise_item_valuation_test( - se_entry_list_mi, "Material Issue" - ) + ses = create_stock_entry_entries_for_batchwise_item_valuation_test(se_entry_list_mi, "Material Issue") sle_details = fetch_sle_details_for_doc_list(ses, columns=columns, as_dict=0) expected_sle_details = [(-50.0, 100.0, -1.0, 1.0, "[[1, 100.0]]")] details_list.append((sle_details, expected_sle_details, "Material Issue Entries", columns)) @@ -771,9 +763,7 @@ def update_invariants(exp_sles): sle["qty_after_transaction"] = state["qty"] return exp_sles - old1 = make_stock_entry( - item_code=item_code, target=warehouse, batch_no=batches[0], qty=10, rate=10 - ) + old1 = make_stock_entry(item_code=item_code, target=warehouse, batch_no=batches[0], qty=10, rate=10) self.assertSLEs( old1, update_invariants( @@ -782,20 +772,20 @@ def update_invariants(exp_sles): ] ), ) - old2 = make_stock_entry( - item_code=item_code, target=warehouse, batch_no=batches[1], qty=10, rate=20 - ) + old2 = make_stock_entry(item_code=item_code, target=warehouse, batch_no=batches[1], qty=10, rate=20) self.assertSLEs( old2, update_invariants( [ - {"actual_qty": 10, "stock_value_difference": 10 * 20, "stock_queue": [[10, 10], [10, 20]]}, + { + "actual_qty": 10, + "stock_value_difference": 10 * 20, + "stock_queue": [[10, 10], [10, 20]], + }, ] ), ) - old3 = make_stock_entry( - item_code=item_code, target=warehouse, batch_no=batches[0], qty=5, rate=15 - ) + old3 = make_stock_entry(item_code=item_code, target=warehouse, batch_no=batches[0], qty=5, rate=15) self.assertSLEs( old3, @@ -842,9 +832,7 @@ def update_invariants(exp_sles): ) # consume old batch as per FIFO - consume_old1 = make_stock_entry( - item_code=item_code, source=warehouse, qty=15, batch_no=batches[0] - ) + consume_old1 = make_stock_entry(item_code=item_code, source=warehouse, qty=15, batch_no=batches[0]) self.assertSLEs( consume_old1, update_invariants( @@ -859,22 +847,22 @@ def update_invariants(exp_sles): ) # consume new batch as per batch - consume_new2 = make_stock_entry( - item_code=item_code, source=warehouse, qty=10, batch_no=batches[-1] - ) + consume_new2 = make_stock_entry(item_code=item_code, source=warehouse, qty=10, batch_no=batches[-1]) self.assertSLEs( consume_new2, update_invariants( [ - {"actual_qty": -10, "stock_value_difference": -10 * 42, "stock_queue": [[5, 20], [5, 15]]}, + { + "actual_qty": -10, + "stock_value_difference": -10 * 42, + "stock_queue": [[5, 20], [5, 15]], + }, ] ), ) # finish all old batches - consume_old2 = make_stock_entry( - item_code=item_code, source=warehouse, qty=10, batch_no=batches[1] - ) + consume_old2 = make_stock_entry(item_code=item_code, source=warehouse, qty=10, batch_no=batches[1]) self.assertSLEs( consume_old2, update_invariants( @@ -885,9 +873,7 @@ def update_invariants(exp_sles): ) # finish all new batches - consume_new1 = make_stock_entry( - item_code=item_code, source=warehouse, qty=10, batch_no=batches[-2] - ) + consume_new1 = make_stock_entry(item_code=item_code, source=warehouse, qty=10, batch_no=batches[-2]) self.assertSLEs( consume_new1, update_invariants( @@ -938,9 +924,7 @@ def test_fifo_multi_item_repack_consumption(self): rates = [10 * i for i in range(1, 5)] - receipt = make_stock_entry( - item_code=rm.name, target=warehouse, qty=10, do_not_save=True, rate=10 - ) + receipt = make_stock_entry(item_code=rm.name, target=warehouse, qty=10, do_not_save=True, rate=10) for rate in rates[1:]: row = frappe.copy_doc(receipt.items[0], ignore_no_copy=False) row.basic_rate = rate @@ -970,9 +954,7 @@ def test_fifo_multi_item_repack_consumption(self): repack.submit() # same exact queue should be transferred - self.assertSLEs( - repack, [{"incoming_rate": sum(rates) * 10}], sle_filters={"item_code": packed.name} - ) + self.assertSLEs(repack, [{"incoming_rate": sum(rates) * 10}], sle_filters={"item_code": packed.name}) def test_negative_fifo_valuation(self): """ @@ -982,7 +964,7 @@ def test_negative_fifo_valuation(self): item = make_item(properties={"allow_negative_stock": 1}).name warehouse = "_Test Warehouse - _TC" - receipt = make_stock_entry(item_code=item, target=warehouse, qty=10, rate=10) + make_stock_entry(item_code=item, target=warehouse, qty=10, rate=10) consume1 = make_stock_entry(item_code=item, source=warehouse, qty=15) self.assertSLEs(consume1, [{"stock_value": -5 * 10, "stock_queue": [[-5, 10]]}]) @@ -1022,27 +1004,21 @@ def _day(days): self.assertEqual(50, _get_stock_credit(depdendent_consumption)) # backdated receipt - should trigger GL repost of all previous stock entries - bd_receipt = make_stock_entry( - item_code=item, to_warehouse=A, qty=5, rate=20, posting_date=_day(-1) - ) + bd_receipt = make_stock_entry(item_code=item, to_warehouse=A, qty=5, rate=20, posting_date=_day(-1)) self.assertEqual(100, _get_stock_credit(depdendent_consumption)) # cancelling receipt should reset it back bd_receipt.cancel() self.assertEqual(50, _get_stock_credit(depdendent_consumption)) - bd_receipt2 = make_stock_entry( - item_code=item, to_warehouse=A, qty=2, rate=20, posting_date=_day(-2) - ) + bd_receipt2 = make_stock_entry(item_code=item, to_warehouse=A, qty=2, rate=20, posting_date=_day(-2)) # total as per FIFO -> 2 * 20 + 3 * 10 = 70 self.assertEqual(70, _get_stock_credit(depdendent_consumption)) # transfer WIP material to final destination and consume it all depdendent_consumption.cancel() make_stock_entry(item_code=item, from_warehouse=B, to_warehouse=C, qty=5, posting_date=_day(3)) - final_consumption = make_stock_entry( - item_code=item, from_warehouse=C, qty=5, posting_date=_day(4) - ) + final_consumption = make_stock_entry(item_code=item, from_warehouse=C, qty=5, posting_date=_day(4)) # exact amount gets consumed self.assertEqual(70, _get_stock_credit(final_consumption)) @@ -1109,11 +1085,10 @@ def ordered_qty_after_transaction(): self.assertEqual([1], ordered_qty_after_transaction()) def test_timestamp_clash(self): - item = make_item().name warehouse = "_Test Warehouse - _TC" - reciept = make_stock_entry( + make_stock_entry( item_code=item, to_warehouse=warehouse, qty=100, @@ -1122,7 +1097,7 @@ def test_timestamp_clash(self): posting_time="01:00:00", ) - consumption = make_stock_entry( + make_stock_entry( item_code=item, from_warehouse=warehouse, qty=50, @@ -1141,11 +1116,10 @@ def test_timestamp_clash(self): try: backdated_receipt.cancel() - except Exception as e: + except Exception: self.fail("Double processing of qty for clashing timestamp.") def test_previous_sle_with_clashed_timestamp(self): - item = make_item().name warehouse = "_Test Warehouse - _TC" @@ -1186,7 +1160,6 @@ def test_previous_sle_with_clashed_timestamp(self): self.assertEqual(sle[0].actual_qty, 5) def test_backdated_sle_with_same_timestamp(self): - item = make_item().name warehouse = "_Test Warehouse - _TC" @@ -1429,12 +1402,13 @@ def create_items(items=None, uoms=None): def setup_item_valuation_test( - valuation_method="FIFO", suffix=None, use_batchwise_valuation=1, batches_list=["X", "Y"] + valuation_method="FIFO", suffix=None, use_batchwise_valuation=1, batches_list=None ): - from erpnext.stock.doctype.batch.batch import make_batch from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + if batches_list is None: + batches_list = ["X", "Y"] if not suffix: suffix = get_unique_suffix() @@ -1448,7 +1422,7 @@ def setup_item_valuation_test( for i, batch_id in enumerate(batches): if not frappe.db.exists("Batch", batch_id): ubw = use_batchwise_valuation - if isinstance(use_batchwise_valuation, (list, tuple)): + if isinstance(use_batchwise_valuation, list | tuple): ubw = use_batchwise_valuation[i] batch = frappe.get_doc( frappe._dict( @@ -1479,9 +1453,7 @@ def create_delivery_note_entries_for_batchwise_item_valuation_test(dn_entry_list dns = [] for item, warehouse, batch_no, qty, rate in dn_entry_list: - so = make_sales_order( - rate=rate, qty=qty, item=item, warehouse=warehouse, against_blanket_order=0 - ) + so = make_sales_order(rate=rate, qty=qty, item=item, warehouse=warehouse, against_blanket_order=0) dn = make_delivery_note(so.name) dn.items[0].batch_no = batch_no diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index c7608cc2dd91..6aaecb1c1658 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from typing import Optional import frappe from frappe import _, bold, msgprint @@ -27,7 +26,7 @@ class EmptyStockReconciliationItemsError(frappe.ValidationError): class StockReconciliation(StockController): def __init__(self, *args, **kwargs): - super(StockReconciliation, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"] def validate(self): @@ -87,7 +86,9 @@ def _changed(item): if not item.batch_no and not item.serial_no: for dimension in get_inventory_dimensions(): if item.get(dimension.get("fieldname")): - inventory_dimensions_dict[dimension.get("fieldname")] = item.get(dimension.get("fieldname")) + inventory_dimensions_dict[dimension.get("fieldname")] = item.get( + dimension.get("fieldname") + ) item_dict = get_stock_balance_for( item.item_code, @@ -189,19 +190,27 @@ def _get_msg(row_num, msg): # do not allow negative valuation if flt(row.valuation_rate) < 0: - self.validation_messages.append(_get_msg(row_num, _("Negative Valuation Rate is not allowed"))) + self.validation_messages.append( + _get_msg(row_num, _("Negative Valuation Rate is not allowed")) + ) if row.batch_no and frappe.get_cached_value("Batch", row.batch_no, "item") != row.item_code: self.validation_messages.append( _get_msg( row_num, - _("Batch {0} does not belong to item {1}").format(bold(row.batch_no), bold(row.item_code)), + _("Batch {0} does not belong to item {1}").format( + bold(row.batch_no), bold(row.item_code) + ), ) ) if row.qty and row.valuation_rate in ["", None]: row.valuation_rate = get_stock_balance( - row.item_code, row.warehouse, self.posting_date, self.posting_time, with_valuation_rate=True + row.item_code, + row.warehouse, + self.posting_date, + self.posting_time, + with_valuation_rate=True, )[1] if not row.valuation_rate: # try if there is a buying price list in default currency @@ -263,11 +272,10 @@ def update_stock_ledger(self): sl_entries = [] has_serial_no = False - has_batch_no = False for row in self.items: item = frappe.get_doc("Item", row.item_code) if item.has_batch_no: - has_batch_no = True + pass if not row.qty and not row.valuation_rate and not row.current_qty: self.make_adjustment_entry(row, sl_entries) @@ -551,9 +559,7 @@ def get_gl_entries(self, warehouse_account=None): if not self.cost_center: msgprint(_("Please enter Cost Center"), raise_exception=1) - return super(StockReconciliation, self).get_gl_entries( - warehouse_account, self.expense_account, self.cost_center - ) + return super().get_gl_entries(warehouse_account, self.expense_account, self.cost_center) def validate_expense_account(self): if not cint(erpnext.is_perpetual_inventory_enabled(self.company)): @@ -648,7 +654,12 @@ def recalculate_current_qty(self, voucher_detail_no, sle_creation, add_new_sle=F row.current_valuation_rate = item_dict.get("rate") else: current_qty = get_batch_qty_for_stock_reco( - row.item_code, row.warehouse, row.batch_no, self.posting_date, self.posting_time, self.name + row.item_code, + row.warehouse, + row.batch_no, + self.posting_date, + self.posting_time, + self.name, ) precesion = row.precision("current_qty") @@ -708,9 +719,7 @@ def has_negative_stock_allowed(self): return allow_negative_stock -def get_batch_qty_for_stock_reco( - item_code, warehouse, batch_no, posting_date, posting_time, voucher_no -): +def get_batch_qty_for_stock_reco(item_code, warehouse, batch_no, posting_date, posting_time, voucher_no): ledger = frappe.qb.DocType("Stock Ledger Entry") query = ( @@ -740,9 +749,7 @@ def get_batch_qty_for_stock_reco( @frappe.whitelist() -def get_items( - warehouse, posting_date, posting_time, company, item_code=None, ignore_empty_stock=False -): +def get_items(warehouse, posting_date, posting_time, company, item_code=None, ignore_empty_stock=False): ignore_empty_stock = cint(ignore_empty_stock) items = [] if item_code and warehouse: @@ -913,16 +920,14 @@ def get_stock_balance_for( warehouse: str, posting_date, posting_time, - batch_no: Optional[str] = None, + batch_no: str | None = None, with_valuation_rate: bool = True, inventory_dimensions_dict=None, voucher_no=None, ): frappe.has_permission("Stock Reconciliation", "write", throw=True) - item_dict = frappe.get_cached_value( - "Item", item_code, ["has_serial_no", "has_batch_no"], as_dict=1 - ) + item_dict = frappe.get_cached_value("Item", item_code, ["has_serial_no", "has_batch_no"], as_dict=1) if not item_dict: # In cases of data upload to Items table @@ -956,9 +961,7 @@ def get_stock_balance_for( qty, rate = data if item_dict.get("has_batch_no"): - qty = ( - get_batch_qty(batch_no, warehouse, posting_date=posting_date, posting_time=posting_time) or 0 - ) + qty = get_batch_qty(batch_no, warehouse, posting_date=posting_date, posting_time=posting_time) or 0 return {"qty": qty, "rate": rate, "serial_nos": serial_nos} diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 9499566f341f..8f3c98913345 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -101,7 +101,8 @@ def _test_reco_sle_gle(self, valuation_method): # no gl entries self.assertTrue( frappe.db.get_value( - "Stock Ledger Entry", {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name} + "Stock Ledger Entry", + {"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}, ) ) @@ -147,7 +148,6 @@ def test_get_items(self): def test_stock_reco_for_serialized_item(self): to_delete_records = [] - to_delete_serial_nos = [] # Add new serial nos serial_item_code = "Stock-Reco-Serial-Item-1" @@ -215,7 +215,7 @@ def test_stock_reco_for_merge_serialized_item(self): purpose="Opening Stock", ) - for i in range(3): + for _i in range(3): sr.append( "items", { @@ -394,9 +394,7 @@ def test_stock_reco_for_serial_and_batch_item_with_future_dependent_entry(self): def test_customer_provided_items(self): item_code = "Stock-Reco-customer-Item-100" - create_item( - item_code, is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0 - ) + create_item(item_code, is_customer_provided_item=1, customer="_Test Customer", is_purchase_item=0) sr = create_stock_reconciliation(item_code=item_code, qty=10, rate=420) @@ -579,18 +577,18 @@ def test_intermediate_sr_bin_update(self): item_code = self.make_item().name warehouse = "_Test Warehouse - _TC" - sr = create_stock_reconciliation( + create_stock_reconciliation( item_code=item_code, warehouse=warehouse, qty=10, rate=100, posting_date=add_days(nowdate(), 10) ) - dn = create_delivery_note( + create_delivery_note( item_code=item_code, warehouse=warehouse, qty=5, rate=120, posting_date=add_days(nowdate(), 12) ) old_bin_qty = frappe.db.get_value( "Bin", {"item_code": item_code, "warehouse": warehouse}, "actual_qty" ) - sr2 = create_stock_reconciliation( + create_stock_reconciliation( item_code=item_code, warehouse=warehouse, qty=11, rate=100, posting_date=add_days(nowdate(), 11) ) new_bin_qty = frappe.db.get_value( @@ -830,7 +828,7 @@ def test_update_stock_reconciliation_while_reposting(self): warehouse = "_Test Warehouse - _TC" # Stock Value => 100 * 100 = 10000 - se = make_stock_entry( + make_stock_entry( item_code=item_code, target=warehouse, qty=100, @@ -1118,9 +1116,7 @@ def test_backdated_purchase_receipt_with_stock_reco(self): self.assertEqual(d.actual_qty, 5.0) self.assertAlmostEqual(d.stock_value_difference, 500.0) - active_serial_no = frappe.get_all( - "Serial No", filters={"status": "Active", "item_code": item_code} - ) + active_serial_no = frappe.get_all("Serial No", filters={"status": "Active", "item_code": item_code}) self.assertEqual(len(active_serial_no), 5) @@ -1213,9 +1209,7 @@ def create_stock_reconciliation(**args): ) ) if frappe.get_all("Stock Ledger Entry", {"company": sr.company}) - else frappe.get_cached_value( - "Account", {"account_type": "Temporary", "company": sr.company}, "name" - ) + else frappe.get_cached_value("Account", {"account_type": "Temporary", "company": sr.company}, "name") ) sr.cost_center = ( args.cost_center diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py index 305459116b5e..963b0650fae6 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/stock_settings.py @@ -61,9 +61,9 @@ def validate_warehouses(self): for field in warehouse_fields: if frappe.db.get_value("Warehouse", self.get(field), "is_group"): frappe.throw( - _("Group Warehouses cannot be used in transactions. Please change the value of {0}").format( - frappe.bold(self.meta.get_field(field).label) - ), + _( + "Group Warehouses cannot be used in transactions. Please change the value of {0}" + ).format(frappe.bold(self.meta.get_field(field).label)), title=_("Incorrect Warehouse"), ) diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.py b/erpnext/stock/doctype/stock_settings/test_stock_settings.py index 974e16339b70..b9e9f75fced3 100644 --- a/erpnext/stock/doctype/stock_settings/test_stock_settings.py +++ b/erpnext/stock/doctype/stock_settings/test_stock_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -import unittest import frappe from frappe.tests.utils import FrappeTestCase diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py index 5a7228a50683..02d64cadfe6a 100644 --- a/erpnext/stock/doctype/warehouse/test_warehouse.py +++ b/erpnext/stock/doctype/warehouse/test_warehouse.py @@ -58,7 +58,7 @@ def test_unlinking_warehouse_from_item_defaults(self): warehouse_ids.append(warehouse_id) item_names = [f"_Test Item {i} for Unlinking" for i in range(2)] - for item, warehouse in zip(item_names, warehouse_ids): + for item, warehouse in zip(item_names, warehouse_ids, strict=False): create_item(item, warehouse=warehouse, company=company) # Delete warehouses @@ -78,7 +78,6 @@ def test_unlinking_warehouse_from_item_defaults(self): ) def test_group_non_group_conversion(self): - warehouse = frappe.get_doc("Warehouse", create_warehouse("TestGroupConversion")) convert_to_group_or_ledger(warehouse.name) diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index 430a8d17e01e..a8c2c2891257 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -26,9 +26,7 @@ def autoname(self): def onload(self): """load account name for General Ledger Report""" - if self.company and cint( - frappe.db.get_value("Company", self.company, "enable_perpetual_inventory") - ): + if self.company and cint(frappe.db.get_value("Company", self.company, "enable_perpetual_inventory")): account = self.account or get_warehouse_account(self) if account: diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 33abdcb53216..fe66f747f07c 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -189,19 +189,14 @@ def set_valuation_rate(out, args): def update_bin_details(args, out, doc): - if ( - args.get("doctype") == "Material Request" - and args.get("material_request_type") == "Material Transfer" - ): + if args.get("doctype") == "Material Request" and args.get("material_request_type") == "Material Transfer": out.update(get_bin_details(args.item_code, args.get("from_warehouse"))) elif out.get("warehouse"): company = args.company if (doc and doc.get("doctype") == "Purchase Order") else None # calculate company_total_stock only for po - bin_details = get_bin_details( - args.item_code, out.warehouse, company, include_child_warehouses=True - ) + bin_details = get_bin_details(args.item_code, out.warehouse, company, include_child_warehouses=True) out.update(bin_details) @@ -308,9 +303,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): if not item: item = frappe.get_doc("Item", args.get("item_code")) - if ( - item.variant_of and not item.taxes and frappe.db.exists("Item Tax", {"parent": item.variant_of}) - ): + if item.variant_of and not item.taxes and frappe.db.exists("Item Tax", {"parent": item.variant_of}): item.update_template_tables() item_defaults = get_item_defaults(item.name, args.company) @@ -355,9 +348,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): # Set stock UOM in args, so that it can be used while fetching item price args.stock_uom = item.stock_uom - if args.get("batch_no") and item.name != frappe.get_cached_value( - "Batch", args.get("batch_no"), "item" - ): + if args.get("batch_no") and item.name != frappe.get_cached_value("Batch", args.get("batch_no"), "item"): args["batch_no"] = "" out = frappe._dict( @@ -378,9 +369,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): "provisional_expense_account": get_provisional_account( args, item_defaults, item_group_defaults, brand_defaults ), - "cost_center": get_default_cost_center( - args, item_defaults, item_group_defaults, brand_defaults - ), + "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults), "has_serial_no": item.has_serial_no, "has_batch_no": item.has_batch_no, "batch_no": args.get("batch_no"), @@ -406,9 +395,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0, "is_fixed_asset": item.is_fixed_asset, - "last_purchase_rate": item.last_purchase_rate - if args.get("doctype") in ["Purchase Order"] - else 0, + "last_purchase_rate": item.last_purchase_rate if args.get("doctype") in ["Purchase Order"] else 0, "transaction_date": args.get("transaction_date"), "against_blanket_order": args.get("against_blanket_order"), "bom_no": item.get("default_bom"), @@ -544,9 +531,7 @@ def get_barcode_data(items_list): itemwise_barcode = {} for item in items_list: - barcodes = frappe.db.get_all( - "Item Barcode", filters={"parent": item.item_code}, fields="barcode" - ) + barcodes = frappe.db.get_all("Item Barcode", filters={"parent": item.item_code}, fields="barcode") for barcode in barcodes: if item.item_code not in itemwise_barcode: @@ -566,13 +551,13 @@ def get_item_tax_info(company, tax_category, item_codes, item_rates=None, item_t if item_rates is None: item_rates = {} - if isinstance(item_codes, (str,)): + if isinstance(item_codes, str): item_codes = json.loads(item_codes) - if isinstance(item_rates, (str,)): + if isinstance(item_rates, str): item_rates = json.loads(item_rates) - if isinstance(item_tax_templates, (str,)): + if isinstance(item_tax_templates, str): item_tax_templates = json.loads(item_tax_templates) for item_code in item_codes: @@ -640,9 +625,7 @@ def _get_item_tax_template(args, taxes, out=None, for_validate=False): taxes_with_no_validity.append(tax) if taxes_with_validity: - taxes = sorted( - taxes_with_validity, key=lambda i: i.valid_from or tax.maximum_net_rate, reverse=True - ) + taxes = sorted(taxes_with_validity, key=lambda i: i.valid_from or tax.maximum_net_rate, reverse=True) else: taxes = taxes_with_no_validity @@ -795,7 +778,7 @@ def get_default_cost_center(args, item=None, item_group=None, brand=None, compan elif not cost_center and args.get("item_code") and company: for method in ["get_item_defaults", "get_item_group_defaults", "get_brand_defaults"]: - path = "erpnext.stock.get_item_details.{0}".format(method) + path = f"erpnext.stock.get_item_details.{method}" data = frappe.get_attr(path)(args.get("item_code"), company) if data and (data.selling_cost_center or data.buying_cost_center): @@ -810,11 +793,7 @@ def get_default_cost_center(args, item=None, item_group=None, brand=None, compan if not cost_center and args.get("cost_center"): cost_center = args.get("cost_center") - if ( - company - and cost_center - and frappe.get_cached_value("Cost Center", cost_center, "company") != company - ): + if company and cost_center and frappe.get_cached_value("Cost Center", cost_center, "company") != company: return None if not cost_center and company: @@ -824,11 +803,7 @@ def get_default_cost_center(args, item=None, item_group=None, brand=None, compan def get_default_supplier(args, item, item_group, brand): - return ( - item.get("default_supplier") - or item_group.get("default_supplier") - or brand.get("default_supplier") - ) + return item.get("default_supplier") or item_group.get("default_supplier") or brand.get("default_supplier") def get_price_list_rate(args, item_doc, out=None): @@ -863,9 +838,7 @@ def get_price_list_rate(args, item_doc, out=None): if not price_list_rate: return out - out.price_list_rate = ( - flt(price_list_rate) * flt(args.plc_conversion_rate) / flt(args.conversion_rate) - ) + out.price_list_rate = flt(price_list_rate) * flt(args.plc_conversion_rate) / flt(args.conversion_rate) if frappe.db.get_single_value("Buying Settings", "disable_last_purchase_rate"): return out @@ -880,9 +853,7 @@ def get_price_list_rate(args, item_doc, out=None): def insert_item_price(args): """Insert Item Price if Price List and Price List Rate are specified and currency is the same""" - if frappe.db.get_value( - "Price List", args.price_list, "currency", cache=True - ) == args.currency and cint( + if frappe.db.get_value("Price List", args.price_list, "currency", cache=True) == args.currency and cint( frappe.db.get_single_value("Stock Settings", "auto_insert_price_list_rate_if_missing") ): if frappe.has_permission("Item Price", "write"): @@ -904,7 +875,9 @@ def insert_item_price(args): ): frappe.db.set_value("Item Price", item_price.name, "price_list_rate", price_list_rate) frappe.msgprint( - _("Item Price updated for {0} in Price List {1}").format(args.item_code, args.price_list), + _("Item Price updated for {0} in Price List {1}").format( + args.item_code, args.price_list + ), alert=True, ) else: @@ -1044,11 +1017,7 @@ def validate_conversion_rate(args, meta): if not args.conversion_rate and args.currency == company_currency: args.conversion_rate = 1.0 - if ( - not args.ignore_conversion_rate - and args.conversion_rate == 1 - and args.currency != company_currency - ): + if not args.ignore_conversion_rate and args.conversion_rate == 1 and args.currency != company_currency: args.conversion_rate = ( get_exchange_rate(args.currency, company_currency, args.transaction_date, "for_buying") or 1.0 ) @@ -1083,7 +1052,9 @@ def validate_conversion_rate(args, meta): if meta.get_field("plc_conversion_rate"): args.plc_conversion_rate = flt( args.plc_conversion_rate, - get_field_precision(meta.get_field("plc_conversion_rate"), frappe._dict({"fields": args})), + get_field_precision( + meta.get_field("plc_conversion_rate"), frappe._dict({"fields": args}) + ), ) @@ -1264,9 +1235,7 @@ def get_serial_no_details(item_code, warehouse, stock_qty, serial_no): @frappe.whitelist() -def get_bin_details_and_serial_nos( - item_code, warehouse, has_batch_no=None, stock_qty=None, serial_no=None -): +def get_bin_details_and_serial_nos(item_code, warehouse, has_batch_no=None, stock_qty=None, serial_no=None): bin_details_and_serial_nos = {} bin_details_and_serial_nos.update(get_bin_details(item_code, warehouse)) if flt(stock_qty) > 0: @@ -1276,9 +1245,7 @@ def get_bin_details_and_serial_nos( bin_details_and_serial_nos.update({"serial_no": serial_no}) return bin_details_and_serial_nos - bin_details_and_serial_nos.update( - get_serial_no_details(item_code, warehouse, stock_qty, serial_no) - ) + bin_details_and_serial_nos.update(get_serial_no_details(item_code, warehouse, stock_qty, serial_no)) return bin_details_and_serial_nos @@ -1390,9 +1357,7 @@ def get_price_list_currency_and_exchange_rate(args): company_currency = get_company_currency(args.company) if (not plc_conversion_rate) or ( - price_list_currency - and args.price_list_currency - and price_list_currency != args.price_list_currency + price_list_currency and args.price_list_currency and price_list_currency != args.price_list_currency ): # cksgb 19/09/2016: added args.transaction_date as posting_date argument for get_exchange_rate plc_conversion_rate = ( @@ -1414,9 +1379,7 @@ def get_price_list_currency_and_exchange_rate(args): @frappe.whitelist() def get_default_bom(item_code=None): def _get_bom(item): - bom = frappe.get_all( - "BOM", dict(item=item, is_active=True, is_default=True, docstatus=1), limit=1 - ) + bom = frappe.get_all("BOM", dict(item=item, is_active=True, is_default=True, docstatus=1), limit=1) return bom[0].name if bom else None if not item_code: @@ -1456,7 +1419,7 @@ def get_valuation_rate(item_code, company, warehouse=None): pi_item = frappe.qb.DocType("Purchase Invoice Item") valuation_rate = ( frappe.qb.from_(pi_item) - .select((Sum(pi_item.base_net_amount) / Sum(pi_item.qty * pi_item.conversion_factor))) + .select(Sum(pi_item.base_net_amount) / Sum(pi_item.qty * pi_item.conversion_factor)) .where((pi_item.docstatus == 1) & (pi_item.item_code == item_code)) ).run() diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index de4242893c6c..c859506ce8ad 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -58,9 +58,7 @@ def add_to_material_request(**kwargs): item_warehouse_projected_qty.get(kwargs.item_code, {}).get(kwargs.warehouse_group) ) else: - projected_qty = flt( - item_warehouse_projected_qty.get(kwargs.item_code, {}).get(kwargs.warehouse) - ) + projected_qty = flt(item_warehouse_projected_qty.get(kwargs.item_code, {}).get(kwargs.warehouse)) if (reorder_level or reorder_qty) and projected_qty < reorder_level: deficiency = reorder_level - projected_qty @@ -188,13 +186,12 @@ def get_item_warehouse_projected_qty(items_to_consider): for item_code, warehouse, projected_qty in frappe.db.sql( """select item_code, warehouse, projected_qty - from tabBin where item_code in ({0}) + from tabBin where item_code in ({}) and (warehouse != '' and warehouse is not null)""".format( ", ".join(["%s"] * len(items_to_consider)) ), items_to_consider, ): - if item_code not in item_warehouse_projected_qty: item_warehouse_projected_qty.setdefault(item_code, {}) @@ -242,7 +239,9 @@ def _log_exception(mr): { "company": company, "transaction_date": nowdate(), - "material_request_type": "Material Transfer" if request_type == "Transfer" else request_type, + "material_request_type": "Material Transfer" + if request_type == "Transfer" + else request_type, } ) @@ -257,7 +256,9 @@ def _log_exception(mr): if uom != item.stock_uom: conversion_factor = ( frappe.db.get_value( - "UOM Conversion Detail", {"parent": item.name, "uom": uom}, "conversion_factor" + "UOM Conversion Detail", + {"parent": item.name, "uom": uom}, + "conversion_factor", ) or 1.0 ) @@ -323,9 +324,7 @@ def send_email_notification(company_wise_mr): msg = frappe.render_template("templates/emails/reorder_item.html", {"mr_list": mr_list}) - frappe.sendmail( - recipients=email_list, subject=_("Auto Material Requests Generated"), message=msg - ) + frappe.sendmail(recipients=email_list, subject=_("Auto Material Requests Generated"), message=msg) def get_email_list(company): @@ -378,7 +377,7 @@ def notify_errors(exceptions_list): for exception in exceptions_list: try: exception = json.loads(exception) - error_message = """
    {0}

    """.format( + error_message = """
    {}

    """.format( _(exception.get("message")) ) content += error_message diff --git a/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py b/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py index 5661e8b26096..3820b3e1566b 100644 --- a/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py +++ b/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py @@ -28,15 +28,15 @@ def validate_filters(filters): def get_columns(): - return ( - [_("Item") + ":Link/Item:150"] - + [_("Item Name") + "::150"] - + [_("Batch") + ":Link/Batch:150"] - + [_("Stock UOM") + ":Link/UOM:100"] - + [_("Quantity") + ":Float:100"] - + [_("Expires On") + ":Date:100"] - + [_("Expiry (In Days)") + ":Int:130"] - ) + return [ + _("Item") + ":Link/Item:150", + _("Item Name") + "::150", + _("Batch") + ":Link/Batch:150", + _("Stock UOM") + ":Link/UOM:100", + _("Quantity") + ":Float:100", + _("Expires On") + ":Date:100", + _("Expiry (In Days)") + ":Int:130", + ] def get_data(filters): @@ -76,9 +76,7 @@ def get_batch_details(filters): .where( (batch.disabled == 0) & (batch.batch_qty > 0) - & ( - (Date(batch.creation) >= filters["from_date"]) & (Date(batch.creation) <= filters["to_date"]) - ) + & ((Date(batch.creation) >= filters["from_date"]) & (Date(batch.creation) <= filters["to_date"])) ) .orderby(batch.creation) ) diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py index e6490f1717aa..50b5efd6a081 100644 --- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py +++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py @@ -69,18 +69,18 @@ def execute(filters=None): def get_columns(filters): """return columns based on filters""" - columns = ( - [_("Item") + ":Link/Item:100"] - + [_("Item Name") + "::150"] - + [_("Description") + "::150"] - + [_("Warehouse") + ":Link/Warehouse:100"] - + [_("Batch") + ":Link/Batch:100"] - + [_("Opening Qty") + ":Float:90"] - + [_("In Qty") + ":Float:80"] - + [_("Out Qty") + ":Float:80"] - + [_("Balance Qty") + ":Float:90"] - + [_("UOM") + "::90"] - ) + columns = [ + _("Item") + ":Link/Item:100", + _("Item Name") + "::150", + _("Description") + "::150", + _("Warehouse") + ":Link/Warehouse:100", + _("Batch") + ":Link/Batch:100", + _("Opening Qty") + ":Float:90", + _("In Qty") + ":Float:80", + _("Out Qty") + ":Float:80", + _("Balance Qty") + ":Float:90", + _("UOM") + "::90", + ] return columns @@ -141,7 +141,9 @@ def get_item_warehouse_batch_map(filters, float_precision): ) elif d.posting_date >= from_date and d.posting_date <= to_date: if flt(d.actual_qty) > 0: - qty_dict.in_qty = flt(qty_dict.in_qty, float_precision) + flt(d.actual_qty, float_precision) + qty_dict.in_qty = flt(qty_dict.in_qty, float_precision) + flt( + d.actual_qty, float_precision + ) else: qty_dict.out_qty = flt(qty_dict.out_qty, float_precision) + abs( flt(d.actual_qty, float_precision) @@ -154,9 +156,7 @@ def get_item_warehouse_batch_map(filters, float_precision): def get_item_details(filters): item_map = {} - for d in (frappe.qb.from_("Item").select("name", "item_name", "description", "stock_uom")).run( - as_dict=1 - ): + for d in (frappe.qb.from_("Item").select("name", "item_name", "description", "stock_uom")).run(as_dict=1): item_map.setdefault(d.name, d) return item_map diff --git a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py index 4642a535b630..b3c8e93e4e17 100644 --- a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py +++ b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py @@ -3,7 +3,7 @@ import datetime from collections import OrderedDict -from typing import Dict, List, Tuple, Union +from typing import Union import frappe from frappe import _ @@ -13,15 +13,15 @@ Filters = frappe._dict Row = frappe._dict -Data = List[Row] -Columns = List[Dict[str, str]] +Data = list[Row] +Columns = list[dict[str, str]] DateTime = Union[datetime.date, datetime.datetime] -FilteredEntries = List[Dict[str, Union[str, float, DateTime, None]]] -ItemGroupsDict = Dict[Tuple[int, int], Dict[str, Union[str, int]]] -SVDList = List[frappe._dict] +FilteredEntries = list[dict[str, str | float | DateTime | None]] +ItemGroupsDict = dict[tuple[int, int], dict[str, str | int]] +SVDList = list[frappe._dict] -def execute(filters: Filters) -> Tuple[Columns, Data]: +def execute(filters: Filters) -> tuple[Columns, Data]: update_filters_with_account(filters) validate_filters(filters) columns = get_columns() @@ -158,7 +158,7 @@ def assign_item_groups_to_svd_list(svd_list: SVDList) -> None: item.item_group = ig_map[item.get("item_code")] -def get_item_groups_map(svd_list: SVDList) -> Dict[str, str]: +def get_item_groups_map(svd_list: SVDList) -> dict[str, str]: item_codes = set(i["item_code"] for i in svd_list) ig_list = frappe.get_list( "Item", fields=["item_code", "item_group"], filters=[("item_code", "in", item_codes)] @@ -168,9 +168,7 @@ def get_item_groups_map(svd_list: SVDList) -> Dict[str, str]: def get_item_groups_dict() -> ItemGroupsDict: item_groups_list = frappe.get_all("Item Group", fields=("name", "is_group", "lft", "rgt")) - return { - (i["lft"], i["rgt"]): {"name": i["name"], "is_group": i["is_group"]} for i in item_groups_list - } + return {(i["lft"], i["rgt"]): {"name": i["name"], "is_group": i["is_group"]} for i in item_groups_list} def update_leveled_dict(leveled_dict: OrderedDict) -> None: diff --git a/erpnext/stock/report/delayed_item_report/delayed_item_report.py b/erpnext/stock/report/delayed_item_report/delayed_item_report.py index 546a834da8ca..0bfb4da06a06 100644 --- a/erpnext/stock/report/delayed_item_report/delayed_item_report.py +++ b/erpnext/stock/report/delayed_item_report/delayed_item_report.py @@ -13,7 +13,7 @@ def execute(filters=None, consolidated=False): return data, columns -class DelayedItemReport(object): +class DelayedItemReport: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) diff --git a/erpnext/stock/report/delayed_order_report/delayed_order_report.py b/erpnext/stock/report/delayed_order_report/delayed_order_report.py index 197218d7ff43..24be939f05b5 100644 --- a/erpnext/stock/report/delayed_order_report/delayed_order_report.py +++ b/erpnext/stock/report/delayed_order_report/delayed_order_report.py @@ -20,7 +20,7 @@ def run(self): return self.get_columns(), self.get_data(consolidated=True) or [] def get_data(self, consolidated=False): - data = super(DelayedOrderReport, self).get_data(consolidated) or [] + data = super().get_data(consolidated) or [] so_list = [] result = [] diff --git a/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.py b/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.py index 9e140336c9ac..404a58b799d5 100644 --- a/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.py +++ b/erpnext/stock/report/fifo_queue_vs_qty_after_transaction_comparison/fifo_queue_vs_qty_after_transaction_comparison.py @@ -40,19 +40,18 @@ def get_data(filters): def get_stock_ledger_entries(filters): - sle_filters = {"is_cancelled": 0} if filters.warehouse: children = get_descendants_of("Warehouse", filters.warehouse) - sle_filters["warehouse"] = ("in", children + [filters.warehouse]) + sle_filters["warehouse"] = ("in", [*children, filters.warehouse]) if filters.item_code: sle_filters["item_code"] = filters.item_code elif filters.get("item_group"): item_group = filters.get("item_group") children = get_descendants_of("Item Group", item_group) - item_group_filter = {"item_group": ("in", children + [item_group])} + item_group_filter = {"item_group": ("in", [*children, item_group])} sle_filters["item_code"] = ( "in", frappe.get_all("Item", filters=item_group_filter, pluck="name", order_by=None), diff --git a/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py b/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py index b68db356ead0..163e7ab88436 100644 --- a/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py +++ b/erpnext/stock/report/incorrect_balance_qty_after_transaction/incorrect_balance_qty_after_transaction.py @@ -27,7 +27,7 @@ def get_data(filters): def validate_data(itewise_balance_qty): res = [] - for key, data in itewise_balance_qty.items(): + for _key, data in itewise_balance_qty.items(): row = get_incorrect_data(data) if row: res.append(row) diff --git a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py index 39d84a7d5bed..4d740bd829a3 100644 --- a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py +++ b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py @@ -43,11 +43,9 @@ def prepare_serial_nos(data): def get_incorrect_serial_nos(serial_nos_data): result = [] - total_value = frappe._dict( - {"qty": 0, "valuation_rate": 0, "serial_no": frappe.bold(_("Balance"))} - ) + total_value = frappe._dict({"qty": 0, "valuation_rate": 0, "serial_no": frappe.bold(_("Balance"))}) - for serial_no, data in serial_nos_data.items(): + for _serial_no, data in serial_nos_data.items(): total_dict = frappe._dict({"qty": 0, "valuation_rate": 0, "serial_no": frappe.bold(_("Total"))}) if check_incorrect_serial_data(data, total_dict): diff --git a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py index da958a8b0f12..7be88314ffdd 100644 --- a/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py +++ b/erpnext/stock/report/incorrect_stock_value_report/incorrect_stock_value_report.py @@ -16,9 +16,7 @@ def execute(filters=None): if not erpnext.is_perpetual_inventory_enabled(filters.company): frappe.throw( - _("Perpetual inventory required for the company {0} to view this report.").format( - filters.company - ) + _("Perpetual inventory required for the company {0} to view this report.").format(filters.company) ) data = get_data(filters) @@ -83,9 +81,7 @@ def get_data(report_filters): closing_date = add_days(from_date, -1) for key, stock_data in voucher_wise_dict.items(): - prev_stock_value = get_stock_value_on( - posting_date=closing_date, item_code=key[0], warehouses=key[1] - ) + prev_stock_value = get_stock_value_on(posting_date=closing_date, item_code=key[0], warehouses=key[1]) for data in stock_data: expected_stock_value = prev_stock_value + data.stock_value_difference if abs(data.stock_value - expected_stock_value) > 0.1: diff --git a/erpnext/stock/report/item_prices/item_prices.py b/erpnext/stock/report/item_prices/item_prices.py index a53a9f24f542..5c5b84f8393c 100644 --- a/erpnext/stock/report/item_prices/item_prices.py +++ b/erpnext/stock/report/item_prices/item_prices.py @@ -111,9 +111,7 @@ def get_price_list(): ).run(as_dict=True) for d in price_list: - d.update( - {"price": "{0} {1} - {2}".format(d.currency, round(d.price_list_rate, 2), d.price_list)} - ) + d.update({"price": f"{d.currency} {round(d.price_list_rate, 2)} - {d.price_list}"}) d.pop("currency") d.pop("price_list_rate") d.pop("price_list") diff --git a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py index c4358b809fcc..dffe9486a64c 100644 --- a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py +++ b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py @@ -24,9 +24,7 @@ def execute(filters=None): data = [] for item in items: - total_outgoing = flt(consumed_item_map.get(item.name, 0)) + flt( - delivered_item_map.get(item.name, 0) - ) + total_outgoing = flt(consumed_item_map.get(item.name, 0)) + flt(delivered_item_map.get(item.name, 0)) avg_daily_outgoing = flt(total_outgoing / diff, float_precision) reorder_level = (avg_daily_outgoing * flt(item.lead_time_days)) + flt(item.safety_stock) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index d0929a082ce4..a1aee987cb6d 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -3,7 +3,6 @@ from operator import itemgetter -from typing import Dict, List, Tuple, Union import frappe from frappe import _ @@ -14,7 +13,7 @@ Filters = frappe._dict -def execute(filters: Filters = None) -> Tuple: +def execute(filters: Filters = None) -> tuple: to_date = filters["to_date"] columns = get_columns(filters) @@ -26,14 +25,14 @@ def execute(filters: Filters = None) -> Tuple: return columns, data, None, chart_data -def format_report_data(filters: Filters, item_details: Dict, to_date: str) -> List[Dict]: +def format_report_data(filters: Filters, item_details: dict, to_date: str) -> list[dict]: "Returns ordered, formatted data with ranges." _func = itemgetter(1) data = [] precision = cint(frappe.db.get_single_value("System Settings", "float_precision", cache=True)) - for item, item_dict in item_details.items(): + for _item, item_dict in item_details.items(): if not flt(item_dict.get("total_qty"), precision): continue @@ -74,12 +73,12 @@ def format_report_data(filters: Filters, item_details: Dict, to_date: str) -> Li return data -def get_average_age(fifo_queue: List, to_date: str) -> float: +def get_average_age(fifo_queue: list, to_date: str) -> float: batch_age = age_qty = total_qty = 0.0 for batch in fifo_queue: batch_age = date_diff(to_date, batch[1]) - if isinstance(batch[0], (int, float)): + if isinstance(batch[0], int | float): age_qty += batch_age * batch[0] total_qty += batch[0] else: @@ -89,8 +88,7 @@ def get_average_age(fifo_queue: List, to_date: str) -> float: return flt(age_qty / total_qty, 2) if total_qty else 0.0 -def get_range_age(filters: Filters, fifo_queue: List, to_date: str, item_dict: Dict) -> Tuple: - +def get_range_age(filters: Filters, fifo_queue: list, to_date: str, item_dict: dict) -> tuple: precision = cint(frappe.db.get_single_value("System Settings", "float_precision", cache=True)) range1 = range2 = range3 = above_range3 = 0.0 @@ -111,7 +109,7 @@ def get_range_age(filters: Filters, fifo_queue: List, to_date: str, item_dict: D return range1, range2, range3, above_range3 -def get_columns(filters: Filters) -> List[Dict]: +def get_columns(filters: Filters) -> list[dict]: range_columns = [] setup_ageing_columns(filters, range_columns) columns = [ @@ -169,7 +167,7 @@ def get_columns(filters: Filters) -> List[Dict]: return columns -def get_chart_data(data: List, filters: Filters) -> Dict: +def get_chart_data(data: list, filters: Filters) -> dict: if not data: return [] @@ -193,7 +191,7 @@ def get_chart_data(data: List, filters: Filters) -> Dict: } -def setup_ageing_columns(filters: Filters, range_columns: List): +def setup_ageing_columns(filters: Filters, range_columns: list): ranges = [ f"0 - {filters['range1']}", f"{cint(filters['range1']) + 1} - {cint(filters['range2'])}", @@ -205,23 +203,21 @@ def setup_ageing_columns(filters: Filters, range_columns: List): add_column(range_columns, label=_("Age ({0})").format(label), fieldname=fieldname) -def add_column( - range_columns: List, label: str, fieldname: str, fieldtype: str = "Float", width: int = 140 -): +def add_column(range_columns: list, label: str, fieldname: str, fieldtype: str = "Float", width: int = 140): range_columns.append(dict(label=label, fieldname=fieldname, fieldtype=fieldtype, width=width)) class FIFOSlots: "Returns FIFO computed slots of inwarded stock as per date." - def __init__(self, filters: Dict = None, sle: List = None): + def __init__(self, filters: dict | None = None, sle: list | None = None): self.item_details = {} self.transferred_item_details = {} self.serial_no_batch_purchase_details = {} self.filters = filters self.sle = sle - def generate(self) -> Dict: + def generate(self) -> dict: """ Returns dict of the foll.g structure: Key = Item A / (Item A, Warehouse A) @@ -257,7 +253,7 @@ def generate(self) -> Dict: return self.item_details - def __init_key_stores(self, row: Dict) -> Tuple: + def __init_key_stores(self, row: dict) -> tuple: "Initialise keys and FIFO Queue." key = (row.name, row.warehouse) @@ -269,9 +265,7 @@ def __init_key_stores(self, row: Dict) -> Tuple: return key, fifo_queue, transferred_item_key - def __compute_incoming_stock( - self, row: Dict, fifo_queue: List, transfer_key: Tuple, serial_nos: List - ): + def __compute_incoming_stock(self, row: dict, fifo_queue: list, transfer_key: tuple, serial_nos: list): "Update FIFO Queue on inward stock." transfer_data = self.transferred_item_details.get(transfer_key) @@ -297,9 +291,7 @@ def __compute_incoming_stock( self.serial_no_batch_purchase_details.setdefault(serial_no, row.posting_date) fifo_queue.append([serial_no, row.posting_date]) - def __compute_outgoing_stock( - self, row: Dict, fifo_queue: List, transfer_key: Tuple, serial_nos: List - ): + def __compute_outgoing_stock(self, row: dict, fifo_queue: list, transfer_key: tuple, serial_nos: list): "Update FIFO Queue on outward stock." if serial_nos: fifo_queue[:] = [serial_no for serial_no in fifo_queue if serial_no[0] not in serial_nos] @@ -325,7 +317,7 @@ def __compute_outgoing_stock( self.transferred_item_details[transfer_key].append([qty_to_pop, slot[1]]) qty_to_pop = 0 - def __adjust_incoming_transfer_qty(self, transfer_data: Dict, fifo_queue: List, row: Dict): + def __adjust_incoming_transfer_qty(self, transfer_data: dict, fifo_queue: list, row: dict): "Add previously removed stock back to FIFO Queue." transfer_qty_to_pop = flt(row.actual_qty) @@ -352,7 +344,7 @@ def add_to_fifo_queue(slot): add_to_fifo_queue([transfer_qty_to_pop, transfer_data[0][1]]) transfer_qty_to_pop = 0 - def __update_balances(self, row: Dict, key: Union[Tuple, str]): + def __update_balances(self, row: dict, key: tuple | str): self.item_details[key]["qty_after_transaction"] = row.qty_after_transaction if "total_qty" not in self.item_details[key]: @@ -362,7 +354,7 @@ def __update_balances(self, row: Dict, key: Union[Tuple, str]): self.item_details[key]["has_serial_no"] = row.has_serial_no - def __aggregate_details_by_item(self, wh_wise_data: Dict) -> Dict: + def __aggregate_details_by_item(self, wh_wise_data: dict) -> dict: "Aggregate Item-Wh wise data into single Item entry." item_aggregated_data = {} for key, row in wh_wise_data.items(): @@ -370,7 +362,12 @@ def __aggregate_details_by_item(self, wh_wise_data: Dict) -> Dict: if not item_aggregated_data.get(item): item_aggregated_data.setdefault( item, - {"details": frappe._dict(), "fifo_queue": [], "qty_after_transaction": 0.0, "total_qty": 0.0}, + { + "details": frappe._dict(), + "fifo_queue": [], + "qty_after_transaction": 0.0, + "total_qty": 0.0, + }, ) item_row = item_aggregated_data.get(item) item_row["details"].update(row["details"]) @@ -381,7 +378,7 @@ def __aggregate_details_by_item(self, wh_wise_data: Dict) -> Dict: return item_aggregated_data - def __get_stock_ledger_entries(self) -> List[Dict]: + def __get_stock_ledger_entries(self) -> list[dict]: sle = frappe.qb.DocType("Stock Ledger Entry") item = self.__get_item_query() # used as derived table in sle query diff --git a/erpnext/stock/report/stock_analytics/stock_analytics.py b/erpnext/stock/report/stock_analytics/stock_analytics.py index ab48181c48d2..920c315352cd 100644 --- a/erpnext/stock/report/stock_analytics/stock_analytics.py +++ b/erpnext/stock/report/stock_analytics/stock_analytics.py @@ -1,7 +1,6 @@ # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt import datetime -from typing import List import frappe from frappe import _, scrub @@ -48,12 +47,10 @@ def get_columns(filters): ranges = get_period_date_ranges(filters) - for dummy, end_date in ranges: + for _dummy, end_date in ranges: period = get_period(end_date, filters) - columns.append( - {"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120} - ) + columns.append({"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120}) return columns @@ -67,7 +64,7 @@ def get_period_date_ranges(filters): increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(filters.range, 1) periodic_daterange = [] - for dummy in range(1, 53, increment): + for _dummy in range(1, 53, increment): if filters.range == "Weekly": period_end_date = from_date + relativedelta(days=6) else: @@ -116,9 +113,7 @@ def get_period(posting_date, filters): elif filters.range == "Monthly": period = _(str(months[posting_date.month - 1])) + " " + str(posting_date.year) elif filters.range == "Quarterly": - period = _("Quarter {0} {1}").format( - str(((posting_date.month - 1) // 3) + 1), str(posting_date.year) - ) + period = _("Quarter {0} {1}").format(str(((posting_date.month - 1) // 3) + 1), str(posting_date.year)) else: year = get_fiscal_year(posting_date, company=filters.company) period = str(year[2]) @@ -188,15 +183,13 @@ def get_periodic_data(entry, filters): periodic_data.setdefault(d.item_code, {}).setdefault(period, {}).setdefault(d.warehouse, 0.0) periodic_data[d.item_code]["balance"][d.warehouse] += value - periodic_data[d.item_code][period][d.warehouse] = periodic_data[d.item_code]["balance"][ - d.warehouse - ] + periodic_data[d.item_code][period][d.warehouse] = periodic_data[d.item_code]["balance"][d.warehouse] return periodic_data def fill_intermediate_periods( - periodic_data, item_code: str, current_period: str, all_periods: List[str] + periodic_data, item_code: str, current_period: str, all_periods: list[str] ) -> None: """There might be intermediate periods where no stock ledger entry exists, copy previous previous data. @@ -235,7 +228,7 @@ def get_data(filters): today = getdate() - for dummy, item_data in item_details.items(): + for _dummy, item_data in item_details.items(): row = { "name": item_data.name, "item_name": item_data.item_name, @@ -273,7 +266,7 @@ def get_items(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]) + item_filters["item_group"] = ("in", [*children, item_group]) if brand := filters.get("brand"): item_filters["brand"] = brand diff --git a/erpnext/stock/report/stock_analytics/test_stock_analytics.py b/erpnext/stock/report/stock_analytics/test_stock_analytics.py index dd8f8d803856..b4f086c36317 100644 --- a/erpnext/stock/report/stock_analytics/test_stock_analytics.py +++ b/erpnext/stock/report/stock_analytics/test_stock_analytics.py @@ -3,7 +3,7 @@ import frappe from frappe import _dict from frappe.tests.utils import FrappeTestCase -from frappe.utils.data import add_to_date, get_datetime, getdate, nowdate +from frappe.utils.data import add_to_date, getdate from erpnext.accounts.utils import get_fiscal_year from erpnext.stock.doctype.item.test_item import make_item @@ -55,7 +55,6 @@ def compare_analytics_row(self, report_row, columns, expected_buckets): self.assertEqual(actual_buckets, expected_buckets) def test_get_period_date_ranges(self): - filters = _dict(range="Monthly", from_date="2020-12-28", to_date="2021-02-06") ranges = get_period_date_ranges(filters) @@ -69,7 +68,6 @@ def test_get_period_date_ranges(self): self.assertEqual(ranges, expected_ranges) def test_get_period_date_ranges_yearly(self): - filters = _dict(range="Yearly", from_date="2021-01-28", to_date="2021-02-06") ranges = get_period_date_ranges(filters) 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 416cf48871ab..67e340d0f70e 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 @@ -14,9 +14,7 @@ def execute(filters=None): if not erpnext.is_perpetual_inventory_enabled(filters.company): frappe.throw( - _("Perpetual inventory required for the company {0} to view this report.").format( - filters.company - ) + _("Perpetual inventory required for the company {0} to view this report.").format(filters.company) ) data = get_data(filters) @@ -34,7 +32,7 @@ def get_data(report_filters): "posting_date": ("<=", report_filters.as_on_date), } - currency_precision = get_currency_precision() or 2 + get_currency_precision() or 2 stock_ledger_entries = get_stock_ledger_data(report_filters, filters) voucher_wise_gl_data = get_gl_data(report_filters, filters) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 6b0bbf3f44dc..f0fddac2c648 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -3,7 +3,7 @@ from operator import itemgetter -from typing import Any, Dict, List, Optional, TypedDict +from typing import Any, TypedDict import frappe from frappe import _ @@ -20,27 +20,27 @@ class StockBalanceFilter(TypedDict): - company: Optional[str] + company: str | None from_date: str to_date: str - item_group: Optional[str] - item: Optional[str] - warehouse: Optional[str] - warehouse_type: Optional[str] - include_uom: Optional[str] # include extra info in converted UOM + item_group: str | None + item: str | None + warehouse: str | None + warehouse_type: str | None + include_uom: str | None # include extra info in converted UOM show_stock_ageing_data: bool show_variant_attributes: bool -SLEntry = Dict[str, Any] +SLEntry = dict[str, Any] -def execute(filters: Optional[StockBalanceFilter] = None): +def execute(filters: StockBalanceFilter | None = None): return StockBalanceReport(filters).run() -class StockBalanceReport(object): - def __init__(self, filters: Optional[StockBalanceFilter]) -> None: +class StockBalanceReport: + def __init__(self, filters: StockBalanceFilter | None) -> None: self.filters = filters self.from_date = getdate(filters.get("from_date")) self.to_date = getdate(filters.get("to_date")) @@ -48,7 +48,7 @@ def __init__(self, filters: Optional[StockBalanceFilter]) -> None: self.start_from = None self.data = [] self.columns = [] - self.sle_entries: List[SLEntry] = [] + self.sle_entries: list[SLEntry] = [] self.set_company_currency() def set_company_currency(self) -> None: @@ -104,7 +104,7 @@ def prepare_new_data(self): if self.filters.get("show_variant_attributes"): variant_values = self.get_variant_values_for() - for key, report_data in self.item_warehouse_map.items(): + for _key, report_data in self.item_warehouse_map.items(): if variant_data := variant_values.get(report_data.item_code): report_data.update(variant_data) @@ -184,7 +184,6 @@ def prepare_item_warehouse_map(self, item_warehouse_map, entry, group_by_key): qty_dict.opening_val += value_diff elif entry.posting_date >= self.from_date and entry.posting_date <= self.to_date: - if flt(qty_diff, self.float_precision) >= 0: qty_dict.in_qty += qty_diff qty_dict.in_val += value_diff @@ -230,7 +229,7 @@ def get_group_by_key(self, row) -> tuple: return tuple(group_by_key) - def get_closing_balance(self) -> List[Dict[str, Any]]: + def get_closing_balance(self) -> list[dict[str, Any]]: if self.filters.get("ignore_closing_balance"): return [] @@ -325,7 +324,7 @@ def apply_warehouse_filters(self, query, sle) -> str: def apply_items_filters(self, query, item_table) -> str: if item_group := self.filters.get("item_group"): children = get_descendants_of("Item Group", item_group, ignore_permissions=True) - query = query.where(item_table.item_group.isin(children + [item_group])) + query = query.where(item_table.item_group.isin([*children, item_group])) for field in ["item_code", "brand"]: if not self.filters.get(field): @@ -542,7 +541,9 @@ def get_opening_vouchers(self): frappe.qb.from_(sr) .select(sr.name, Coalesce("Stock Reconciliation").as_("voucher_type")) .where( - (sr.docstatus == 1) & (sr.posting_date <= self.to_date) & (sr.purpose == "Opening Stock") + (sr.docstatus == 1) + & (sr.posting_date <= self.to_date) + & (sr.purpose == "Opening Stock") ) ) ).select("voucher_type", "name") @@ -568,7 +569,7 @@ def get_opening_fifo_queue(report_data): def filter_items_with_no_transactions( - iwb_map, float_precision: float, inventory_dimensions: list = None + iwb_map, float_precision: float, inventory_dimensions: list | None = None ): pop_keys = [] for group_by_key in iwb_map: @@ -605,6 +606,6 @@ def filter_items_with_no_transactions( return iwb_map -def get_variants_attributes() -> List[str]: +def get_variants_attributes() -> list[str]: """Return all item variant attributes.""" return frappe.get_all("Item Attribute", pluck="name") diff --git a/erpnext/stock/report/stock_balance/test_stock_balance.py b/erpnext/stock/report/stock_balance/test_stock_balance.py index e963de293ab9..8b3dbee7c8d2 100644 --- a/erpnext/stock/report/stock_balance/test_stock_balance.py +++ b/erpnext/stock/report/stock_balance/test_stock_balance.py @@ -1,4 +1,4 @@ -from typing import Any, Dict +from typing import Any import frappe from frappe import _dict @@ -32,12 +32,11 @@ def setUp(self): def tearDown(self): frappe.db.rollback() - def assertPartialDictEq(self, expected: Dict[str, Any], actual: Dict[str, Any]): + def assertPartialDictEq(self, expected: dict[str, Any], actual: dict[str, Any]): for k, v in expected.items(): self.assertEqual(v, actual[k], msg=f"{expected=}\n{actual=}") def generate_stock_ledger(self, item_code: str, movements): - for movement in map(_dict, movements): if "to_warehouse" not in movement: movement.to_warehouse = "_Test Warehouse - _TC" @@ -128,7 +127,6 @@ def test_opening_balance(self): self.assertPartialDictEq({"opening_qty": 6, "in_qty": 0}, rows[0]) def test_uom_converted_info(self): - self.item.append("uoms", {"conversion_factor": 5, "uom": "Box"}) self.item.save() @@ -167,8 +165,6 @@ def test_show_item_attr(self): variant.save() self.generate_stock_ledger(variant.name, [_dict(qty=5, rate=10)]) - rows = stock_balance( - self.filters.update({"show_variant_attributes": 1, "item_code": variant.name}) - ) + rows = stock_balance(self.filters.update({"show_variant_attributes": 1, "item_code": variant.name})) self.assertPartialDictEq(attributes, rows[0]) self.assertInvariants(rows) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 21b90c4b026e..a9f74149d51d 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -437,11 +437,8 @@ def get_opening_balance(filters, columns, sl_entries): def get_warehouse_condition(warehouse): warehouse_details = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"], as_dict=1) if warehouse_details: - return ( - " exists (select name from `tabWarehouse` wh \ - where wh.lft >= %s and wh.rgt <= %s and warehouse = wh.name)" - % (warehouse_details.lft, warehouse_details.rgt) - ) + return f" exists (select name from `tabWarehouse` wh \ + where wh.lft >= {warehouse_details.lft} and wh.rgt <= {warehouse_details.rgt} and warehouse = wh.name)" return "" @@ -452,22 +449,17 @@ def get_item_group_condition(item_group, item_table=None): if item_table: ig = frappe.qb.DocType("Item Group") return item_table.item_group.isin( - ( - frappe.qb.from_(ig) - .select(ig.name) - .where( - (ig.lft >= item_group_details.lft) - & (ig.rgt <= item_group_details.rgt) - & (item_table.item_group == ig.name) - ) + frappe.qb.from_(ig) + .select(ig.name) + .where( + (ig.lft >= item_group_details.lft) + & (ig.rgt <= item_group_details.rgt) + & (item_table.item_group == ig.name) ) ) else: - return ( - "item.item_group in (select ig.name from `tabItem Group` ig \ - where ig.lft >= %s and ig.rgt <= %s and item.item_group = ig.name)" - % (item_group_details.lft, item_group_details.rgt) - ) + return f"item.item_group in (select ig.name from `tabItem Group` ig \ + where ig.lft >= {item_group_details.lft} and ig.rgt <= {item_group_details.rgt} and item.item_group = ig.name)" def check_inventory_dimension_filters_applied(filters) -> bool: diff --git a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py index 189a90aa4711..0b7e551c86f2 100644 --- a/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py +++ b/erpnext/stock/report/stock_ledger_variance/stock_ledger_variance.py @@ -228,7 +228,7 @@ def get_data(filters=None): return data -def get_item_warehouse_combinations(filters: dict = None) -> dict: +def get_item_warehouse_combinations(filters: dict | None = None) -> dict: filters = frappe._dict(filters or {}) bin = frappe.qb.DocType("Bin") @@ -284,7 +284,5 @@ def has_difference(row, precision, difference_in, valuation_method): return True elif difference_in == "Valuation" and valuation_diff: return True - elif difference_in not in ["Qty", "Value", "Valuation"] and ( - qty_diff or value_diff or valuation_diff - ): + elif difference_in not in ["Qty", "Value", "Valuation"] and (qty_diff or value_diff or valuation_diff): return True diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py index 31c756da822a..743656c6472c 100644 --- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py +++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py @@ -250,9 +250,7 @@ def get_bin_list(filters): query = query.where(bin.item_code == filters.item_code) if filters.warehouse: - warehouse_details = frappe.db.get_value( - "Warehouse", filters.warehouse, ["lft", "rgt"], as_dict=1 - ) + warehouse_details = frappe.db.get_value("Warehouse", filters.warehouse, ["lft", "rgt"], as_dict=1) if warehouse_details: wh = frappe.qb.DocType("Warehouse") @@ -286,7 +284,9 @@ def get_item_map(item_code, include_uom): (item.is_stock_item == 1) & (item.disabled == 0) & ( - (item.end_of_life > today()) | (item.end_of_life.isnull()) | (item.end_of_life == "0000-00-00") + (item.end_of_life > today()) + | (item.end_of_life.isnull()) + | (item.end_of_life == "0000-00-00") ) & (ExistsCriterion(frappe.qb.from_(bin).select(bin.name).where(bin.item_code == item.name))) ) diff --git a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py index 8c76908cc3c7..e28b2d79228b 100644 --- a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py +++ b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py @@ -20,7 +20,6 @@ def execute(filters=None): total_qty = total_amount = 0.0 if consumed_details.get(item_code): for cd in consumed_details.get(item_code): - if cd.voucher_no not in material_transfer_vouchers: if cd.voucher_type in ["Delivery Note", "Sales Invoice"]: delivered_qty += abs(flt(cd.actual_qty)) @@ -54,19 +53,19 @@ def execute(filters=None): def get_columns(filters): """return columns based on filters""" - columns = ( - [_("Item") + ":Link/Item:100"] - + [_("Item Name") + "::100"] - + [_("Description") + "::150"] - + [_("UOM") + ":Link/UOM:90"] - + [_("Consumed Qty") + ":Float:110"] - + [_("Consumed Amount") + ":Currency:130"] - + [_("Delivered Qty") + ":Float:110"] - + [_("Delivered Amount") + ":Currency:130"] - + [_("Total Qty") + ":Float:110"] - + [_("Total Amount") + ":Currency:130"] - + [_("Supplier(s)") + "::250"] - ) + columns = [ + _("Item") + ":Link/Item:100", + _("Item Name") + "::100", + _("Description") + "::150", + _("UOM") + ":Link/UOM:90", + _("Consumed Qty") + ":Float:110", + _("Consumed Amount") + ":Currency:130", + _("Delivered Qty") + ":Float:110", + _("Delivered Amount") + ":Currency:130", + _("Total Qty") + ":Float:110", + _("Total Amount") + ":Currency:130", + _("Supplier(s)") + "::250", + ] return columns @@ -173,9 +172,7 @@ def get_suppliers_details(filters): def get_material_transfer_vouchers(): se = frappe.qb.DocType("Stock Entry") query = ( - frappe.qb.from_(se) - .select(se.name) - .where((se.purpose == "Material Transfer") & (se.docstatus == 1)) + frappe.qb.from_(se).select(se.name).where((se.purpose == "Material Transfer") & (se.docstatus == 1)) ) return [r[0] for r in query.run()] diff --git a/erpnext/stock/report/test_reports.py b/erpnext/stock/report/test_reports.py index d118d8e56945..74c6afa204b1 100644 --- a/erpnext/stock/report/test_reports.py +++ b/erpnext/stock/report/test_reports.py @@ -1,5 +1,4 @@ import unittest -from typing import List, Tuple import frappe @@ -14,7 +13,7 @@ batch = frappe.db.get_value("Batch", fieldname=["name"], as_dict=True, order_by="creation desc") -REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [ +REPORT_FILTER_TEST_CASES: list[tuple[ReportName, ReportFilters]] = [ ("Stock Ledger", {"_optional": True}), ("Stock Ledger", {"batch_no": batch}), ("Stock Ledger", {"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"}), diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.py b/erpnext/stock/report/total_stock_summary/total_stock_summary.py index c3155bd1a5eb..4848c216e819 100644 --- a/erpnext/stock/report/total_stock_summary/total_stock_summary.py +++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.py @@ -8,7 +8,6 @@ def execute(filters=None): - if not filters: filters = {} columns = get_columns(filters) @@ -54,8 +53,8 @@ def get_total_stock(filters): else: query = query.select(wh.company).groupby(wh.company) - query = query.select( - item.item_code, item.description, Sum(bin.actual_qty).as_("actual_qty") - ).groupby(item.item_code) + query = query.select(item.item_code, item.description, Sum(bin.actual_qty).as_("actual_qty")).groupby( + item.item_code + ) return query.run() diff --git a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py index 5dbdceff2473..e1cce31329ec 100644 --- a/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py +++ b/erpnext/stock/report/warehouse_wise_item_balance_age_and_value/warehouse_wise_item_balance_age_and_value.py @@ -40,7 +40,7 @@ def execute(filters=None): item_balance = {} item_value = {} - for (company, item, warehouse) in sorted(iwb_map): + for company, item, warehouse in sorted(iwb_map): if not item_map.get(item): continue @@ -71,7 +71,7 @@ def execute(filters=None): row += [average_age] - bal_qty = [sum(bal_qty) for bal_qty in zip(*wh_balance)] + bal_qty = [sum(bal_qty) for bal_qty in zip(*wh_balance, strict=False)] total_qty = sum(bal_qty) if len(warehouse_list) > 1: row += [total_qty] diff --git a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py index a0e994482f87..39baa548daf1 100644 --- a/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py +++ b/erpnext/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.py @@ -1,7 +1,7 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from typing import Any, Dict, List, Optional, TypedDict +from typing import Any, TypedDict import frappe from frappe import _ @@ -9,12 +9,12 @@ class StockBalanceFilter(TypedDict): - company: Optional[str] - warehouse: Optional[str] - show_disabled_warehouses: Optional[int] + company: str | None + warehouse: str | None + show_disabled_warehouses: int | None -SLEntry = Dict[str, Any] +SLEntry = dict[str, Any] def execute(filters=None): @@ -25,7 +25,7 @@ def execute(filters=None): return columns, data -def get_warehouse_wise_balance(filters: StockBalanceFilter) -> List[SLEntry]: +def get_warehouse_wise_balance(filters: StockBalanceFilter) -> list[SLEntry]: sle = frappe.qb.DocType("Stock Ledger Entry") query = ( @@ -95,7 +95,7 @@ def update_balance(warehouse, balance): update_balance(warehouse, warehouse.stock_balance) -def get_columns(filters: StockBalanceFilter) -> List[Dict]: +def get_columns(filters: StockBalanceFilter) -> list[dict]: columns = [ { "label": _("Warehouse"), diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index 439ed7a8e097..05d21950ad2f 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -15,9 +15,7 @@ def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, frappe.db.auto_commit_on_many_writes = 1 if allow_negative_stock: - existing_allow_negative_stock = frappe.db.get_value( - "Stock Settings", None, "allow_negative_stock" - ) + existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock") frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) item_warehouses = frappe.db.sql( @@ -37,9 +35,7 @@ def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, frappe.db.rollback() if allow_negative_stock: - frappe.db.set_value( - "Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock - ) + frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock) frappe.db.auto_commit_on_many_writes = 0 @@ -51,7 +47,6 @@ def repost_stock( only_bin=False, allow_negative_stock=False, ): - if not only_bin: repost_actual_qty(item_code, warehouse, allow_zero_rate, allow_negative_stock) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 96a554de72b3..99930768ea53 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -2,7 +2,6 @@ # License: GNU General Public License v3. See license.txt import json -from typing import Optional, Set, Tuple import frappe from frappe import _ @@ -185,9 +184,7 @@ def repost_future_sle( if not args: args = [] # set args to empty list if None to avoid enumerate error - items_to_be_repost = get_items_to_be_repost( - voucher_type=voucher_type, voucher_no=voucher_no, doc=doc - ) + items_to_be_repost = get_items_to_be_repost(voucher_type=voucher_type, voucher_no=voucher_no, doc=doc) if items_to_be_repost: args = items_to_be_repost @@ -212,12 +209,10 @@ def repost_future_sle( ) affected_transactions.update(obj.affected_transactions) - distinct_item_warehouses[ - (args[i].get("item_code"), args[i].get("warehouse")) - ].reposting_status = True + distinct_item_warehouses[(args[i].get("item_code"), args[i].get("warehouse"))].reposting_status = True if obj.new_items_found: - for item_wh, data in distinct_item_warehouses.items(): + for _item_wh, data in distinct_item_warehouses.items(): if ("args_idx" not in data and not data.reposting_status) or ( data.sle_changed and data.reposting_status ): @@ -242,9 +237,7 @@ def validate_item_warehouse(args): frappe.throw(_(validation_msg)) -def update_args_in_repost_item_valuation( - doc, index, args, distinct_item_warehouses, affected_transactions -): +def update_args_in_repost_item_valuation(doc, index, args, distinct_item_warehouses, affected_transactions): doc.db_set( { "items_to_be_repost": json.dumps(args, default=str), @@ -300,7 +293,7 @@ def get_distinct_item_warehouse(args=None, doc=None): return distinct_item_warehouses -def get_affected_transactions(doc) -> Set[Tuple[str, str]]: +def get_affected_transactions(doc) -> set[tuple[str, str]]: if not doc.affected_transactions: return set() @@ -313,7 +306,7 @@ def get_current_index(doc=None): return doc.current_index -class update_entries_after(object): +class update_entries_after: """ update valution rate and qty after transaction from the current time-bucket onwards @@ -355,7 +348,7 @@ def __init__( self.new_items_found = False self.distinct_item_warehouses = args.get("distinct_item_warehouses", frappe._dict()) - self.affected_transactions: Set[Tuple[str, str]] = set() + self.affected_transactions: set[tuple[str, str]] = set() self.data = frappe._dict() self.initialize_previous_data(self.args) @@ -433,9 +426,7 @@ def process_sle_against_current_timestamp(self): self.process_sle(sle) def get_sle_against_current_voucher(self): - self.args["posting_datetime"] = get_combine_datetime( - self.args.posting_date, self.args.posting_time - ) + self.args["posting_datetime"] = get_combine_datetime(self.args.posting_date, self.args.posting_time) return frappe.db.sql( """ @@ -473,9 +464,7 @@ def get_dependent_entries_to_fix(self, entries_to_fix, sle): if not dependant_sle: return entries_to_fix - elif ( - dependant_sle.item_code == self.item_code and dependant_sle.warehouse == self.args.warehouse - ): + elif dependant_sle.item_code == self.item_code and dependant_sle.warehouse == self.args.warehouse: return entries_to_fix elif dependant_sle.item_code != self.item_code: self.update_distinct_item_warehouses(dependant_sle) @@ -495,9 +484,7 @@ def update_distinct_item_warehouses(self, dependant_sle): self.distinct_item_warehouses[key] = val self.new_items_found = True else: - existing_sle_posting_date = ( - self.distinct_item_warehouses[key].get("sle", {}).get("posting_date") - ) + existing_sle_posting_date = self.distinct_item_warehouses[key].get("sle", {}).get("posting_date") dependent_voucher_detail_nos = self.get_dependent_voucher_detail_nos(key) @@ -584,7 +571,9 @@ def process_sle(self, sle): self.wh_data.valuation_rate ) if self.valuation_method != "Moving Average": - self.wh_data.stock_queue = [[self.wh_data.qty_after_transaction, self.wh_data.valuation_rate]] + self.wh_data.stock_queue = [ + [self.wh_data.qty_after_transaction, self.wh_data.valuation_rate] + ] else: if self.valuation_method == "Moving Average": self.get_moving_average_values(sle) @@ -927,9 +916,7 @@ def get_serialized_values(self, sle): self.wh_data.valuation_rate = new_stock_value / new_stock_qty if not self.wh_data.valuation_rate and sle.voucher_detail_no: - allow_zero_rate = self.check_if_allow_zero_valuation_rate( - sle.voucher_type, sle.voucher_detail_no - ) + allow_zero_rate = self.check_if_allow_zero_valuation_rate(sle.voucher_type, sle.voucher_detail_no) if not allow_zero_rate: self.wh_data.valuation_rate = self.get_fallback_rate(sle) @@ -1044,9 +1031,7 @@ def rate_generator() -> float: stock_value_difference = stock_value - prev_stock_value self.wh_data.stock_queue = stock_queue.state - self.wh_data.stock_value = round_off_if_near_zero( - self.wh_data.stock_value + stock_value_difference - ) + self.wh_data.stock_value = round_off_if_near_zero(self.wh_data.stock_value + stock_value_difference) if not self.wh_data.stock_queue: self.wh_data.stock_queue.append( @@ -1083,9 +1068,7 @@ def update_batched_values(self, sle): outgoing_rate = self.get_fallback_rate(sle) stock_value_difference = outgoing_rate * actual_qty - self.wh_data.stock_value = round_off_if_near_zero( - self.wh_data.stock_value + stock_value_difference - ) + self.wh_data.stock_value = round_off_if_near_zero(self.wh_data.stock_value + stock_value_difference) if self.wh_data.qty_after_transaction: self.wh_data.valuation_rate = self.wh_data.stock_value / self.wh_data.qty_after_transaction @@ -1135,7 +1118,6 @@ def raise_exceptions(self): exceptions[0]["voucher_type"], exceptions[0]["voucher_no"], ) in frappe.local.flags.currently_saving: - msg = _("{0} units of {1} needed in {2} to complete this transaction.").format( abs(deficiency), frappe.get_desk_link("Item", exceptions[0]["item_code"]), @@ -1201,7 +1183,7 @@ def get_previous_sle_of_current_voucher(args, operator="<", exclude_current_vouc voucher_condition = f"and voucher_no != '{voucher_no}'" sle = frappe.db.sql( - """ + f""" select *, posting_datetime as "timestamp" from `tabStock Ledger Entry` where item_code = %(item_code)s @@ -1213,10 +1195,7 @@ def get_previous_sle_of_current_voucher(args, operator="<", exclude_current_vouc ) order by posting_datetime desc, creation desc limit 1 - for update""".format( - operator=operator, - voucher_condition=voucher_condition, - ), + for update""", args, as_dict=1, ) @@ -1256,7 +1235,7 @@ def get_stock_ledger_entries( extra_cond=None, ): """get stock ledger entries filtered by specific posting datetime conditions""" - conditions = " and posting_datetime {0} %(posting_datetime)s".format(operator) + conditions = f" and posting_datetime {operator} %(posting_datetime)s" if previous_sle.get("warehouse"): conditions += " and warehouse = %(warehouse)s" elif previous_sle.get("warehouse_condition"): @@ -1268,17 +1247,17 @@ def get_stock_ledger_entries( conditions += ( """ and ( - serial_no = {0} - or serial_no like {1} - or serial_no like {2} - or serial_no like {3} + serial_no = {} + or serial_no like {} + or serial_no like {} + or serial_no like {} ) """ ).format( frappe.db.escape(serial_no), - frappe.db.escape("{}\n%".format(serial_no)), - frappe.db.escape("%\n{}".format(serial_no)), - frappe.db.escape("%\n{}\n%".format(serial_no)), + frappe.db.escape(f"{serial_no}\n%"), + frappe.db.escape(f"%\n{serial_no}"), + frappe.db.escape(f"%\n{serial_no}\n%"), ) if not previous_sle.get("posting_date"): @@ -1301,17 +1280,16 @@ def get_stock_ledger_entries( """ select *, posting_datetime as "timestamp" from `tabStock Ledger Entry` - where item_code = %%(item_code)s + where item_code = %(item_code)s and is_cancelled = 0 - %(conditions)s - order by posting_datetime %(order)s, creation %(order)s - %(limit)s %(for_update)s""" - % { - "conditions": conditions, - "limit": limit or "", - "for_update": for_update and "for update" or "", - "order": order, - }, + {conditions} + order by posting_datetime {order}, creation {order} + {limit} {for_update}""".format( + conditions=conditions, + limit=limit or "", + for_update=for_update and "for update" or "", + order=order, + ), previous_sle, as_dict=1, debug=debug, @@ -1336,10 +1314,7 @@ def get_sle_by_voucher_detail_no(voucher_detail_no, excluded_sle=None): ) -def get_batch_incoming_rate( - item_code, warehouse, batch_no, posting_date, posting_time, creation=None -): - +def get_batch_incoming_rate(item_code, warehouse, batch_no, posting_date, posting_time, creation=None): import datetime sle = frappe.qb.DocType("Stock Ledger Entry") @@ -1350,9 +1325,9 @@ def get_batch_incoming_rate( timestamp_condition = sle.posting_datetime < posting_datetime if creation: - timestamp_condition |= ( - sle.posting_datetime == get_combine_datetime(posting_date, posting_time) - ) & (sle.creation < creation) + timestamp_condition |= (sle.posting_datetime == get_combine_datetime(posting_date, posting_time)) & ( + sle.creation < creation + ) batch_details = ( frappe.qb.from_(sle) @@ -1381,7 +1356,6 @@ def get_valuation_rate( raise_error_if_no_rate=True, batch_no=None, ): - if not company: company = frappe.get_cached_value("Warehouse", warehouse, "company") @@ -1457,7 +1431,7 @@ def get_valuation_rate( solutions += ( "
  • " + _("If not, you can Cancel / Submit this entry") - + " {0} ".format(frappe.bold("after")) + + " {} ".format(frappe.bold("after")) + _("performing either one below:") + "
  • " ) @@ -1591,9 +1565,7 @@ def validate_negative_qty_in_future_sle(args, allow_negative_stock=False): neg_sle = get_future_sle_with_negative_qty(args) if is_negative_with_precision(neg_sle): - message = _( - "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." - ).format( + message = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format( abs(neg_sle[0]["qty_after_transaction"]), frappe.get_desk_link("Item", args.item_code), frappe.get_desk_link("Warehouse", args.warehouse), @@ -1609,9 +1581,7 @@ def validate_negative_qty_in_future_sle(args, allow_negative_stock=False): neg_batch_sle = get_future_sle_with_negative_batch_qty(args) if is_negative_with_precision(neg_batch_sle, is_batch=True): - message = _( - "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." - ).format( + message = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format( abs(neg_batch_sle[0]["cumulative_total"]), frappe.get_desk_link("Batch", args.batch_no), frappe.get_desk_link("Warehouse", args.warehouse), @@ -1689,7 +1659,7 @@ def get_future_sle_with_negative_batch_qty(args): ) -def is_negative_stock_allowed(*, item_code: Optional[str] = None) -> bool: +def is_negative_stock_allowed(*, item_code: str | None = None) -> bool: if cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock", cache=True)): return True if item_code and cint(frappe.db.get_value("Item", item_code, "allow_negative_stock", cache=True)): diff --git a/erpnext/stock/tests/test_get_item_details.py b/erpnext/stock/tests/test_get_item_details.py index b53e29e9e8e1..30f748a65e00 100644 --- a/erpnext/stock/tests/test_get_item_details.py +++ b/erpnext/stock/tests/test_get_item_details.py @@ -1,5 +1,3 @@ -import json - import frappe from frappe.test_runner import make_test_records from frappe.tests.utils import FrappeTestCase @@ -16,7 +14,6 @@ def setUp(self): super().setUp() def test_get_item_detail_purchase_order(self): - args = frappe._dict( { "item_code": "_Test Item", @@ -29,7 +26,6 @@ def test_get_item_detail_purchase_order(self): "name": None, "supplier": "_Test Supplier", "transaction_date": None, - "conversion_rate": 1.0, "price_list": "_Test Buying Price List", "is_subcontracted": 0, "ignore_pricing_rule": 1, diff --git a/erpnext/stock/tests/test_utils.py b/erpnext/stock/tests/test_utils.py index 4e93ac93cb77..bc646fae45ce 100644 --- a/erpnext/stock/tests/test_utils.py +++ b/erpnext/stock/tests/test_utils.py @@ -28,7 +28,7 @@ def assertSLEs(self, doc, expected_sles, sle_filters=None): ) self.assertGreaterEqual(len(sles), len(expected_sles)) - for exp_sle, act_sle in zip(expected_sles, sles): + for exp_sle, act_sle in zip(expected_sles, sles, strict=False): for k, v in exp_sle.items(): act_value = act_sle[k] if k == "stock_queue": @@ -51,7 +51,7 @@ def assertGLEs(self, doc, expected_gles, gle_filters=None, order_by=None): order_by=order_by or "posting_date, creation", ) self.assertGreaterEqual(len(actual_gles), len(expected_gles)) - for exp_gle, act_gle in zip(expected_gles, actual_gles): + for exp_gle, act_gle in zip(expected_gles, actual_gles, strict=False): for k, exp_value in exp_gle.items(): act_value = act_gle[k] self.assertEqual(exp_value, act_value, msg=f"{k} doesn't match \n{exp_gle}\n{act_gle}") diff --git a/erpnext/stock/tests/test_valuation.py b/erpnext/stock/tests/test_valuation.py index 4d8990ae40bf..47b8f0b5cf5d 100644 --- a/erpnext/stock/tests/test_valuation.py +++ b/erpnext/stock/tests/test_valuation.py @@ -28,9 +28,7 @@ def assertTotalQty(self, qty): self.assertAlmostEqual(sum(q for q, _ in self.queue), qty, msg=f"queue: {self.queue}", places=4) def assertTotalValue(self, value): - self.assertAlmostEqual( - sum(q * r for q, r in self.queue), value, msg=f"queue: {self.queue}", places=2 - ) + self.assertAlmostEqual(sum(q * r for q, r in self.queue), value, msg=f"queue: {self.queue}", places=2) def test_simple_addition(self): self.queue.add_stock(1, 10) @@ -210,9 +208,7 @@ def assertTotalQty(self, qty): self.assertAlmostEqual(sum(q for q, _ in self.stack), qty, msg=f"stack: {self.stack}", places=4) def assertTotalValue(self, value): - self.assertAlmostEqual( - sum(q * r for q, r in self.stack), value, msg=f"stack: {self.stack}", places=2 - ) + self.assertAlmostEqual(sum(q * r for q, r in self.stack), value, msg=f"stack: {self.stack}", places=2) def test_simple_addition(self): self.stack.add_stock(1, 10) @@ -355,7 +351,6 @@ def assertStockQueue(self, se, expected_queue): self.assertEqual(stock_queue, expected_queue) def test_lifo_values(self): - in1 = self._make_stock_entry(1, 1) self.assertStockQueue(in1, [[1, 1]]) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 0c3e15ac487d..058db2a6e20a 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -3,7 +3,6 @@ import json -from typing import Dict, Optional import frappe from frappe import _ @@ -14,7 +13,7 @@ from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses from erpnext.stock.valuation import FIFOValuation, LIFOValuation -BarcodeScanResult = Dict[str, Optional[str]] +BarcodeScanResult = dict[str, str | None] class InvalidWarehouseCompany(frappe.ValidationError): @@ -55,7 +54,7 @@ def get_stock_value_from_bin(warehouse=None, item_code=None): def get_stock_value_on( - warehouses: list | str = None, posting_date: str = None, item_code: str = None + warehouses: list | str | None = None, posting_date: str | None = None, item_code: str | None = None ) -> float: if not posting_date: posting_date = nowdate() @@ -140,9 +139,7 @@ def get_stock_balance( else (0.0, 0.0, None) ) else: - return ( - (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0) - ) + return (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0) else: return last_entry.qty_after_transaction if last_entry else 0.0 @@ -205,10 +202,8 @@ def get_latest_stock_qty(item_code, warehouse=None): condition += " AND warehouse = %s" actual_qty = frappe.db.sql( - """select sum(actual_qty) from tabBin - where item_code=%s {0}""".format( - condition - ), + f"""select sum(actual_qty) from tabBin + where item_code=%s {condition}""", values, )[0][0] @@ -337,9 +332,7 @@ def get_valuation_method(item_code): """get valuation method from item or default""" val_method = frappe.db.get_value("Item", item_code, "valuation_method", cache=True) if not val_method: - val_method = ( - frappe.db.get_value("Stock Settings", None, "valuation_method", cache=True) or "FIFO" - ) + val_method = frappe.db.get_value("Stock Settings", None, "valuation_method", cache=True) or "FIFO" return val_method @@ -414,7 +407,6 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto if not include_uom or not conversion_factors: return - convertible_cols = {} is_dict_obj = False if isinstance(result[0], dict): is_dict_obj = True @@ -429,8 +421,8 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto columns.insert( idx + 1, { - "label": "{0} (per {1})".format(d.get("label"), include_uom), - "fieldname": "{0}_{1}".format(d.get("fieldname"), frappe.scrub(include_uom)), + "label": "{} (per {})".format(d.get("label"), include_uom), + "fieldname": "{}_{}".format(d.get("fieldname"), frappe.scrub(include_uom)), "fieldtype": "Currency" if d.get("convertible") == "rate" else "Float", }, ) @@ -453,7 +445,7 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto if not is_dict_obj: row.insert(key + 1, new_value) else: - new_key = "{0}_{1}".format(key, frappe.scrub(include_uom)) + new_key = f"{key}_{frappe.scrub(include_uom)}" update_dict_values.append([row, new_key, new_value]) for data in update_dict_values: @@ -487,9 +479,9 @@ def add_additional_uom_columns(columns, result, include_uom, conversion_factors) {"converted_col": columns[next_col]["fieldname"], "for_type": col.get("convertible")} ) if col.get("convertible") == "rate": - columns[next_col]["label"] += " (per {})".format(include_uom) + columns[next_col]["label"] += f" (per {include_uom})" else: - columns[next_col]["label"] += " ({})".format(include_uom) + columns[next_col]["label"] += f" ({include_uom})" for row_idx, row in enumerate(result): for convertible_col, data in convertible_column_map.items(): @@ -563,7 +555,7 @@ def scan_barcode(search_value: str) -> BarcodeScanResult: def set_cache(data: BarcodeScanResult): frappe.cache().set_value(f"erpnext:barcode_scan:{search_value}", data, expires_in_sec=120) - def get_cache() -> Optional[BarcodeScanResult]: + def get_cache() -> BarcodeScanResult | None: if data := frappe.cache().get_value(f"erpnext:barcode_scan:{search_value}"): return data @@ -609,7 +601,7 @@ def get_cache() -> Optional[BarcodeScanResult]: return {} -def _update_item_info(scan_result: Dict[str, Optional[str]]) -> Dict[str, Optional[str]]: +def _update_item_info(scan_result: dict[str, str | None]) -> dict[str, str | None]: if item_code := scan_result.get("item_code"): if item_info := frappe.get_cached_value( "Item", diff --git a/erpnext/stock/valuation.py b/erpnext/stock/valuation.py index 35f4f12235d1..b1df982c9066 100644 --- a/erpnext/stock/valuation.py +++ b/erpnext/stock/valuation.py @@ -1,9 +1,10 @@ from abc import ABC, abstractmethod, abstractproperty -from typing import Callable, List, NewType, Optional, Tuple +from collections.abc import Callable +from typing import NewType from frappe.utils import flt -StockBin = NewType("StockBin", List[float]) # [[qty, rate], ...] +StockBin = NewType("StockBin", list[float]) # [[qty, rate], ...] # Indexes of values inside FIFO bin 2-tuple QTY = 0 @@ -17,15 +18,15 @@ def add_stock(self, qty: float, rate: float) -> None: @abstractmethod def remove_stock( - self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] = None - ) -> List[StockBin]: + self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] | None = None + ) -> list[StockBin]: pass @abstractproperty - def state(self) -> List[StockBin]: + def state(self) -> list[StockBin]: pass - def get_total_stock_and_value(self) -> Tuple[float, float]: + def get_total_stock_and_value(self) -> tuple[float, float]: total_qty = 0.0 total_value = 0.0 @@ -62,11 +63,11 @@ class FIFOValuation(BinWiseValuation): # ref: https://docs.python.org/3/reference/datamodel.html#slots __slots__ = ["queue"] - def __init__(self, state: Optional[List[StockBin]]): - self.queue: List[StockBin] = state if state is not None else [] + def __init__(self, state: list[StockBin] | None): + self.queue: list[StockBin] = state if state is not None else [] @property - def state(self) -> List[StockBin]: + def state(self) -> list[StockBin]: """Get current state of queue.""" return self.queue @@ -95,8 +96,8 @@ def add_stock(self, qty: float, rate: float) -> None: self.queue[-1][QTY] = qty def remove_stock( - self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] = None - ) -> List[StockBin]: + self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] | None = None + ) -> list[StockBin]: """Remove stock from the queue and return popped bins. args: @@ -166,11 +167,11 @@ class LIFOValuation(BinWiseValuation): # ref: https://docs.python.org/3/reference/datamodel.html#slots __slots__ = ["stack"] - def __init__(self, state: Optional[List[StockBin]]): - self.stack: List[StockBin] = state if state is not None else [] + def __init__(self, state: list[StockBin] | None): + self.stack: list[StockBin] = state if state is not None else [] @property - def state(self) -> List[StockBin]: + def state(self) -> list[StockBin]: """Get current state of stack.""" return self.stack @@ -201,8 +202,8 @@ def add_stock(self, qty: float, rate: float) -> None: self.stack[-1][QTY] = qty def remove_stock( - self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] = None - ) -> List[StockBin]: + self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] | None = None + ) -> list[StockBin]: """Remove stock from the stack and return popped bins. args: diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 4ed8a0eab160..187bea1e9f7c 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -15,7 +15,7 @@ class SubcontractingOrder(SubcontractingController): def __init__(self, *args, **kwargs): - super(SubcontractingOrder, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { @@ -32,10 +32,10 @@ def __init__(self, *args, **kwargs): ] def before_validate(self): - super(SubcontractingOrder, self).before_validate() + super().before_validate() def validate(self): - super(SubcontractingOrder, self).validate() + super().validate() self.validate_purchase_order_for_subcontracting() self.validate_items() self.validate_service_items() @@ -136,9 +136,7 @@ def update_ordered_qty_for_subcontracting(self, sco_item_rows=None): ): 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": self.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): @@ -212,7 +210,10 @@ def update_status(self, status=None, update_modified=True): elif self.per_received > 0 and self.per_received < 100: status = "Partially Received" for item in self.supplied_items: - if not item.returned_qty or (item.supplied_qty - item.consumed_qty - item.returned_qty) > 0: + if ( + not item.returned_qty + or (item.supplied_qty - item.consumed_qty - item.returned_qty) > 0 + ): break else: status = "Closed" diff --git a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py index fbdea6ddbee5..5762522b93f8 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py @@ -211,7 +211,7 @@ def test_make_rm_stock_entry_for_batch_items_with_less_transfer(self): item["qty"] -= 1 itemwise_transfer_qty[item["item_code"]] += item["qty"] - ste = make_stock_transfer_entry( + make_stock_transfer_entry( sco_no=sco.name, rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details), diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 3e5e2b42c046..7e3863766244 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -12,7 +12,7 @@ class SubcontractingReceipt(SubcontractingController): def __init__(self, *args, **kwargs): - super(SubcontractingReceipt, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.status_updater = [ { "target_dt": "Subcontracting Order Item", @@ -31,9 +31,7 @@ def __init__(self, *args, **kwargs): def onload(self): self.set_onload( "backflush_based_on", - frappe.db.get_single_value( - "Buying Settings", "backflush_raw_materials_of_subcontract_based_on" - ), + frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on"), ) def update_status_updater_args(self): @@ -64,7 +62,7 @@ def update_status_updater_args(self): ) def before_validate(self): - super(SubcontractingReceipt, self).before_validate() + super().before_validate() self.validate_items_qty() self.set_items_bom() self.set_items_cost_center() @@ -77,7 +75,7 @@ def validate(self): ) and not self.has_serial_batch_items(): self.supplied_items = [] - super(SubcontractingReceipt, self).validate() + super().validate() self.set_missing_values() self.validate_posting_time() self.validate_rejected_warehouse() @@ -144,7 +142,9 @@ def set_available_qty_for_consumption(self): .select( sco_supplied_item.rm_item_code, sco_supplied_item.reference_name, - (sco_supplied_item.total_supplied_qty - sco_supplied_item.consumed_qty).as_("available_qty"), + (sco_supplied_item.total_supplied_qty - sco_supplied_item.consumed_qty).as_( + "available_qty" + ), ) .where( (sco_supplied_item.parent == item.subcontracting_order) @@ -157,7 +157,9 @@ def set_available_qty_for_consumption(self): supplied_items_details[item.name] = {} for supplied_item in supplied_items: - supplied_items_details[item.name][supplied_item.rm_item_code] = supplied_item.available_qty + supplied_items_details[item.name][ + supplied_item.rm_item_code + ] = supplied_item.available_qty else: for item in self.get("supplied_items"): item.available_qty_for_consumption = supplied_items_details.get(item.reference_name, {}).get( @@ -233,7 +235,9 @@ def validate_items_qty(self): for item in self.items: if not (item.qty or item.rejected_qty): frappe.throw( - _("Row {0}: Accepted Qty and Rejected Qty can't be zero at the same time.").format(item.idx) + _("Row {0}: Accepted Qty and Rejected Qty can't be zero at the same time.").format( + item.idx + ) ) def set_items_bom(self): @@ -328,10 +332,12 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): warehouse_account_name = warehouse_account[item.warehouse]["account"] warehouse_account_currency = warehouse_account[item.warehouse]["account_currency"] - supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") - supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( - "account_currency" + supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get( + "account" ) + supplier_warehouse_account_currency = warehouse_account.get( + self.supplier_warehouse, {} + ).get("account_currency") remarks = self.get("remarks") or _("Accounting Entry for Stock") # FG Warehouse Account (Debit) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index b05ed755c7f9..b2b0f0e98432 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 frappe from frappe.tests.utils import FrappeTestCase -from frappe.utils import add_days, cint, cstr, flt, today +from frappe.utils import add_days, cint, flt, today import erpnext from erpnext.accounts.doctype.account.test_account import get_inventory_account @@ -43,9 +43,7 @@ def setUp(self): def test_subcontracting(self): set_backflush_based_on("BOM") - make_stock_entry( - item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100 - ) + make_stock_entry(item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100) make_stock_entry( item_code="_Test Item Home Desktop 100", qty=100, @@ -77,9 +75,7 @@ def test_subcontracting(self): self.assertEqual(scr.get("items")[0].rm_supp_cost, flt(rm_supp_cost)) def test_available_qty_for_consumption(self): - make_stock_entry( - item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100 - ) + make_stock_entry(item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100) make_stock_entry( item_code="_Test Item Home Desktop 100", qty=100, @@ -206,12 +202,8 @@ def test_subcontracting_over_receipt(self): make_stock_entry( target="_Test Warehouse - _TC", item_code="Test Extra Item 1", qty=10, basic_rate=100 ) - make_stock_entry( - target="_Test Warehouse - _TC", item_code="_Test FG Item", qty=1, basic_rate=100 - ) - make_stock_entry( - target="_Test Warehouse - _TC", item_code="Test Extra Item 2", qty=1, basic_rate=100 - ) + make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test FG Item", qty=1, basic_rate=100) + make_stock_entry(target="_Test Warehouse - _TC", item_code="Test Extra Item 2", qty=1, basic_rate=100) rm_items = [ { @@ -476,9 +468,7 @@ def test_supplied_items_consumed_qty(self): set_backflush_based_on("Material Transferred for Subcontract") # Create Material Receipt for RM's - make_stock_entry( - item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100 - ) + make_stock_entry(item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100) make_stock_entry( item_code="_Test Item Home Desktop 100", qty=100, @@ -732,9 +722,7 @@ def test_subcontracting_receipt_cancel_with_batch(self): def make_return_subcontracting_receipt(**args): args = frappe._dict(args) return_doc = make_return_doc("Subcontracting Receipt", args.scr_name) - return_doc.supplier_warehouse = ( - args.supplier_warehouse or args.warehouse or "_Test Warehouse 1 - _TC" - ) + return_doc.supplier_warehouse = args.supplier_warehouse or args.warehouse or "_Test Warehouse 1 - _TC" if args.qty: for item in return_doc.items: diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 25041b1973b4..0cb56e6375ce 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -19,7 +19,7 @@ class Issue(Document): def get_feed(self): - return "{0}: {1}".format(_(self.status), self.subject) + return f"{_(self.status)}: {self.subject}" def validate(self): if self.is_new() and self.via_customer_portal: @@ -122,7 +122,7 @@ def split_issue(self, subject, communication_id): "comment_type": "Info", "reference_doctype": "Issue", "reference_name": replicated_issue.name, - "content": " - Split the Issue from {1}".format( + "content": " - Split the Issue from {}".format( self.name, frappe.bold(self.name) ), } @@ -176,7 +176,6 @@ def get_issue_list(doctype, txt, filters, limit_start, limit_page_length=20, ord @frappe.whitelist() def set_multiple_status(names, status): - for name in json.loads(names): frappe.db.set_value("Issue", name, "status", status) @@ -258,9 +257,7 @@ def set_first_response_time(communication, method): if communication.get("reference_doctype") == "Issue": issue = get_parent_doc(communication) if is_first_response(issue) and issue.service_level_agreement: - first_response_time = calculate_first_response_time( - issue, get_datetime(issue.first_responded_on) - ) + first_response_time = calculate_first_response_time(issue, get_datetime(issue.first_responded_on)) issue.db_set("first_response_time", first_response_time) diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py index a44012444cab..8cc9db9da93b 100644 --- a/erpnext/support/doctype/issue/test_issue.py +++ b/erpnext/support/doctype/issue/test_issue.py @@ -29,23 +29,21 @@ def test_response_time_and_resolution_time_based_on_different_sla(self): creation = get_datetime("2019-03-04 12:00") # make issue with customer specific SLA - customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory") + create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "_Test Customer", 1) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with customer_group specific SLA - customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") + create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "__Test Customer", 2) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with territory specific SLA - customer = create_customer( - "___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory" - ) + create_customer("___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory") issue = make_issue(creation, "___Test Customer", 3) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) @@ -147,16 +145,15 @@ def test_issue_close_after_on_hold(self): self.assertEqual(issue.agreement_status, "Fulfilled") def test_issue_open_after_closed(self): - # Created on -> 1 pm, Response Time -> 4 hrs, Resolution Time -> 6 hrs frappe.flags.current_time = get_datetime("2021-11-01 13:00") issue = make_issue( frappe.flags.current_time, index=1, issue_type="Critical" ) # Applies 24hr working time SLA create_communication(issue.name, "test@example.com", "Received", frappe.flags.current_time) - self.assertEquals(issue.agreement_status, "First Response Due") - self.assertEquals(issue.response_by, get_datetime("2021-11-01 17:00")) - self.assertEquals(issue.resolution_by, get_datetime("2021-11-01 19:00")) + self.assertEqual(issue.agreement_status, "First Response Due") + self.assertEqual(issue.response_by, get_datetime("2021-11-01 17:00")) + self.assertEqual(issue.resolution_by, get_datetime("2021-11-01 19:00")) # Replied on → 2 pm frappe.flags.current_time = get_datetime("2021-11-01 14:00") @@ -164,19 +161,19 @@ def test_issue_open_after_closed(self): issue.reload() issue.status = "Replied" issue.save() - self.assertEquals(issue.agreement_status, "Resolution Due") - self.assertEquals(issue.on_hold_since, frappe.flags.current_time) - self.assertEquals(issue.first_responded_on, frappe.flags.current_time) + self.assertEqual(issue.agreement_status, "Resolution Due") + self.assertEqual(issue.on_hold_since, frappe.flags.current_time) + self.assertEqual(issue.first_responded_on, frappe.flags.current_time) # Customer Replied → 3 pm frappe.flags.current_time = get_datetime("2021-11-01 15:00") create_communication(issue.name, "test@example.com", "Received", frappe.flags.current_time) issue.reload() - self.assertEquals(issue.status, "Open") + self.assertEqual(issue.status, "Open") # Hold Time + 1 Hrs - self.assertEquals(issue.total_hold_time, 3600) + self.assertEqual(issue.total_hold_time, 3600) # Resolution By should increase by one hrs - self.assertEquals(issue.resolution_by, get_datetime("2021-11-01 20:00")) + self.assertEqual(issue.resolution_by, get_datetime("2021-11-01 20:00")) # Replied on → 4 pm, Open → 1 hr, Resolution Due → 8 pm frappe.flags.current_time = get_datetime("2021-11-01 16:00") @@ -184,37 +181,37 @@ def test_issue_open_after_closed(self): issue.reload() issue.status = "Replied" issue.save() - self.assertEquals(issue.agreement_status, "Resolution Due") + self.assertEqual(issue.agreement_status, "Resolution Due") # Customer Closed → 10 pm frappe.flags.current_time = get_datetime("2021-11-01 22:00") issue.status = "Closed" issue.save() # Hold Time + 6 Hrs - self.assertEquals(issue.total_hold_time, 3600 + 21600) + self.assertEqual(issue.total_hold_time, 3600 + 21600) # Resolution By should increase by 6 hrs - self.assertEquals(issue.resolution_by, get_datetime("2021-11-02 02:00")) - self.assertEquals(issue.agreement_status, "Fulfilled") - self.assertEquals(issue.resolution_date, frappe.flags.current_time) + self.assertEqual(issue.resolution_by, get_datetime("2021-11-02 02:00")) + self.assertEqual(issue.agreement_status, "Fulfilled") + self.assertEqual(issue.resolution_date, frappe.flags.current_time) # Customer Open → 3 am i.e after resolution by is crossed frappe.flags.current_time = get_datetime("2021-11-02 03:00") create_communication(issue.name, "test@example.com", "Received", frappe.flags.current_time) issue.reload() # Since issue was Resolved, Resolution By should be increased by 5 hrs (3am - 10pm) - self.assertEquals(issue.total_hold_time, 3600 + 21600 + 18000) + self.assertEqual(issue.total_hold_time, 3600 + 21600 + 18000) # Resolution By should increase by 5 hrs - self.assertEquals(issue.resolution_by, get_datetime("2021-11-02 07:00")) - self.assertEquals(issue.agreement_status, "Resolution Due") + self.assertEqual(issue.resolution_by, get_datetime("2021-11-02 07:00")) + self.assertEqual(issue.agreement_status, "Resolution Due") self.assertFalse(issue.resolution_date) # We Closed → 4 am, SLA should be Fulfilled frappe.flags.current_time = get_datetime("2021-11-02 04:00") issue.status = "Closed" issue.save() - self.assertEquals(issue.resolution_by, get_datetime("2021-11-02 07:00")) - self.assertEquals(issue.agreement_status, "Fulfilled") - self.assertEquals(issue.resolution_date, frappe.flags.current_time) + self.assertEqual(issue.resolution_by, get_datetime("2021-11-02 07:00")) + self.assertEqual(issue.agreement_status, "Fulfilled") + self.assertEqual(issue.resolution_date, frappe.flags.current_time) def test_recording_of_assignment_on_first_reponse_failure(self): from frappe.desk.form.assign_to import add as add_assignment @@ -255,8 +252,8 @@ def test_agreement_status_on_response(self): create_communication(issue.name, "test@admin.com", "Sent", frappe.flags.current_time) issue.reload() - self.assertEquals(issue.first_responded_on, frappe.flags.current_time) - self.assertEquals(issue.agreement_status, "Resolution Due") + self.assertEqual(issue.first_responded_on, frappe.flags.current_time) + self.assertEqual(issue.agreement_status, "Resolution Due") class TestFirstResponseTime(TestSetUp): @@ -547,7 +544,7 @@ def make_issue(creation=None, customer=None, index=0, priority=None, issue_type= issue = frappe.get_doc( { "doctype": "Issue", - "subject": "Service Level Agreement Issue {0}".format(index), + "subject": f"Service Level Agreement Issue {index}", "customer": customer, "raised_by": "test@example.com", "description": "Service Level Agreement Issue", @@ -564,7 +561,6 @@ def make_issue(creation=None, customer=None, index=0, priority=None, issue_type= def create_customer(name, customer_group, territory): - create_customer_group(customer_group) create_territory(territory) @@ -580,7 +576,6 @@ def create_customer(name, customer_group, territory): def create_customer_group(customer_group): - if not frappe.db.exists("Customer Group", {"customer_group_name": customer_group}): frappe.get_doc({"doctype": "Customer Group", "customer_group_name": customer_group}).insert( ignore_permissions=True @@ -588,7 +583,6 @@ def create_customer_group(customer_group): def create_territory(territory): - if not frappe.db.exists("Territory", {"territory_name": territory}): frappe.get_doc( { 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 54d3c31cd80f..e984f927fa60 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -44,22 +44,26 @@ def check_priorities(self): # Check if response and resolution time is set for every priority if not priority.response_time: frappe.throw( - _("Set Response Time for Priority {0} in row {1}.").format(priority.priority, priority.idx) + _("Set Response Time for Priority {0} in row {1}.").format( + priority.priority, priority.idx + ) ) if self.apply_sla_for_resolution: if not priority.resolution_time: frappe.throw( - _("Set Response Time for Priority {0} in row {1}.").format(priority.priority, priority.idx) + _("Set Response Time for Priority {0} in row {1}.").format( + priority.priority, priority.idx + ) ) response = priority.response_time resolution = priority.resolution_time if response > resolution: frappe.throw( - _("Response Time for {0} priority in row {1} can't be greater than Resolution Time.").format( - priority.priority, priority.idx - ) + _( + "Response Time for {0} priority in row {1} can't be greater than Resolution Time." + ).format(priority.priority, priority.idx) ) priorities.append(priority.priority) @@ -323,7 +327,7 @@ def get_active_service_level_agreement_for(doc): "Service Level Agreement", "entity", "in", - [customer] + get_customer_group(customer) + get_customer_territory(customer), + [customer, *get_customer_group(customer), *get_customer_territory(customer)], ], ["Service Level Agreement", "entity_type", "is", "not set"], ] @@ -331,9 +335,7 @@ def get_active_service_level_agreement_for(doc): else: or_filters.append(["Service Level Agreement", "entity_type", "is", "not set"]) - default_sla_filter = filters + [ - ["Service Level Agreement", "default_service_level_agreement", "=", 1] - ] + default_sla_filter = [*filters, ["Service Level Agreement", "default_service_level_agreement", "=", 1]] default_sla = frappe.get_all( "Service Level Agreement", filters=default_sla_filter, @@ -374,7 +376,7 @@ def get_customer_group(customer): customer_group = frappe.db.get_value("Customer", customer, "customer_group") if customer else None if customer_group: ancestors = get_ancestors_of("Customer Group", customer_group) - customer_groups = [customer_group] + ancestors + customer_groups = [customer_group, *ancestors] return customer_groups @@ -384,7 +386,7 @@ def get_customer_territory(customer): customer_territory = frappe.db.get_value("Customer", customer, "territory") if customer else None if customer_territory: ancestors = get_ancestors_of("Territory", customer_territory) - customer_territories = [customer_territory] + ancestors + customer_territories = [customer_territory, *ancestors] return customer_territories @@ -408,7 +410,7 @@ def get_service_level_agreement_filters(doctype, name, customer=None): "Service Level Agreement", "entity", "in", - [""] + [customer] + get_customer_group(customer) + get_customer_territory(customer), + ["", customer, *get_customer_group(customer), *get_customer_territory(customer)], ] ) @@ -420,8 +422,7 @@ def get_service_level_agreement_filters(doctype, name, customer=None): ) ], "service_level_agreements": [ - d.name - for d in frappe.get_all("Service Level Agreement", filters=filters, or_filters=or_filters) + d.name for d in frappe.get_all("Service Level Agreement", filters=filters, or_filters=or_filters) ], } @@ -482,7 +483,6 @@ def remove_sla_if_applied(doc): def process_sla(doc, sla): - if not doc.creation: doc.creation = now_datetime(doc.get("owner")) if doc.meta.has_field("service_level_agreement_creation"): @@ -712,7 +712,6 @@ def change_service_level_agreement_and_priority(self): and frappe.db.exists("Issue", self.name) and frappe.db.get_single_value("Support Settings", "track_service_level_agreement") ): - if not self.priority == frappe.db.get_value("Issue", self.name, "priority"): self.set_response_and_resolution_time( priority=self.priority, service_level_agreement=self.service_level_agreement @@ -733,9 +732,7 @@ def change_service_level_agreement_and_priority(self): def get_response_and_resolution_duration(doc): sla = frappe.get_doc("Service Level Agreement", doc.service_level_agreement) priority = sla.get_service_level_agreement_priority(doc.priority) - priority.update( - {"support_and_resolution": sla.support_and_resolution, "holiday_list": sla.holiday_list} - ) + priority.update({"support_and_resolution": sla.support_and_resolution, "holiday_list": sla.holiday_list}) return priority @@ -752,7 +749,7 @@ def reset_service_level_agreement(doctype: str, docname: str, reason, user): "reference_doctype": doc.doctype, "reference_name": doc.name, "comment_email": user, - "content": " resetted Service Level Agreement - {0}".format(_(reason)), + "content": f" resetted Service Level Agreement - {_(reason)}", } ).insert(ignore_permissions=True) @@ -860,7 +857,7 @@ def record_assigned_users_on_failure(doc): if assigned_users: from frappe.utils import get_fullname - assigned_users = ", ".join((get_fullname(user) for user in assigned_users)) + assigned_users = ", ".join(get_fullname(user) for user in assigned_users) message = _("First Response SLA Failed by {}").format(assigned_users) doc.add_comment(comment_type="Assigned", text=message) diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index 472f6bc24eb9..aea3eb9fefeb 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -51,9 +51,7 @@ def test_service_level_agreement(self): resolution_time=21600, ) - get_default_service_level_agreement = get_service_level_agreement( - default_service_level_agreement=1 - ) + get_default_service_level_agreement = get_service_level_agreement(default_service_level_agreement=1) self.assertEqual( create_default_service_level_agreement.name, get_default_service_level_agreement.name @@ -198,9 +196,7 @@ def test_docfield_creation_for_sla_on_custom_dt(self): ) # check default SLA for custom dt - default_sla = get_service_level_agreement( - default_service_level_agreement=1, doctype=doctype.name - ) + default_sla = get_service_level_agreement(default_service_level_agreement=1, doctype=doctype.name) self.assertEqual(sla.name, default_sla.name) # check SLA docfields created @@ -390,14 +386,17 @@ def create_service_level_agreement( resolution_time=0, doctype="Issue", condition="", - sla_fulfilled_on=[], - pause_sla_on=[], + sla_fulfilled_on=None, + pause_sla_on=None, apply_sla_for_resolution=1, service_level=None, start_time="10:00:00", end_time="18:00:00", ): - + if pause_sla_on is None: + pause_sla_on = [] + if sla_fulfilled_on is None: + sla_fulfilled_on = [] make_holiday_list() make_priorities() @@ -484,9 +483,7 @@ def create_service_level_agreement( if sla: frappe.delete_doc("Service Level Agreement", sla, force=1) - return frappe.get_doc(service_level_agreement).insert( - ignore_permissions=True, ignore_if_duplicate=True - ) + return frappe.get_doc(service_level_agreement).insert(ignore_permissions=True, ignore_if_duplicate=True) def create_customer(): @@ -615,7 +612,12 @@ def create_custom_doctype(): "fields": [ {"label": "Date", "fieldname": "date", "fieldtype": "Date"}, {"label": "Description", "fieldname": "desc", "fieldtype": "Long Text"}, - {"label": "Email ID", "fieldname": "email_id", "fieldtype": "Link", "options": "Customer"}, + { + "label": "Email ID", + "fieldname": "email_id", + "fieldtype": "Link", + "options": "Customer", + }, { "label": "Status", "fieldname": "status", @@ -637,8 +639,8 @@ def make_lead(creation=None, index=0, company=None): return frappe.get_doc( { "doctype": "Lead", - "email_id": "test_lead1@example{0}.com".format(index), - "lead_name": "_Test Lead {0}".format(index), + "email_id": f"test_lead1@example{index}.com", + "lead_name": f"_Test Lead {index}", "status": "Open", "creation": creation, "service_level_agreement_creation": creation, diff --git a/erpnext/support/report/issue_analytics/issue_analytics.py b/erpnext/support/report/issue_analytics/issue_analytics.py index 00ba25a6a97a..7f023723c1f4 100644 --- a/erpnext/support/report/issue_analytics/issue_analytics.py +++ b/erpnext/support/report/issue_analytics/issue_analytics.py @@ -15,7 +15,7 @@ def execute(filters=None): return IssueAnalytics(filters).run() -class IssueAnalytics(object): +class IssueAnalytics: def __init__(self, filters=None): """Issue Analytics Report""" self.filters = frappe._dict(filters or {}) @@ -44,7 +44,13 @@ def get_columns(self): elif self.filters.based_on == "Assigned To": self.columns.append( - {"label": _("User"), "fieldname": "user", "fieldtype": "Link", "options": "User", "width": 200} + { + "label": _("User"), + "fieldname": "user", + "fieldtype": "Link", + "options": "User", + "width": 200, + } ) elif self.filters.based_on == "Issue Type": @@ -75,9 +81,7 @@ def get_columns(self): {"label": _(period), "fieldname": scrub(period), "fieldtype": "Int", "width": 120} ) - self.columns.append( - {"label": _("Total"), "fieldname": "total", "fieldtype": "Int", "width": 120} - ) + self.columns.append({"label": _("Total"), "fieldname": "total", "fieldtype": "Int", "width": 120}) def get_data(self): self.get_issues() @@ -109,9 +113,7 @@ def get_period_date_ranges(self): from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date) - increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get( - self.filters.range, 1 - ) + increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(self.filters.range, 1) if self.filters.range in ["Monthly", "Quarterly"]: from_date = from_date.replace(day=1) @@ -121,7 +123,7 @@ def get_period_date_ranges(self): from_date = from_date + relativedelta(from_date, weekday=MO(-1)) self.periodic_daterange = [] - for dummy in range(1, 53): + for _dummy in range(1, 53): if self.filters.range == "Weekly": period_end_date = add_days(from_date, 6) else: diff --git a/erpnext/support/report/issue_summary/issue_summary.py b/erpnext/support/report/issue_summary/issue_summary.py index c80ce88222d7..d976c2871b29 100644 --- a/erpnext/support/report/issue_summary/issue_summary.py +++ b/erpnext/support/report/issue_summary/issue_summary.py @@ -13,7 +13,7 @@ def execute(filters=None): return IssueSummary(filters).run() -class IssueSummary(object): +class IssueSummary: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) @@ -41,7 +41,13 @@ def get_columns(self): elif self.filters.based_on == "Assigned To": self.columns.append( - {"label": _("User"), "fieldname": "user", "fieldtype": "Link", "options": "User", "width": 200} + { + "label": _("User"), + "fieldname": "user", + "fieldtype": "Link", + "options": "User", + "width": 200, + } ) elif self.filters.based_on == "Issue Type": @@ -84,9 +90,7 @@ def get_columns(self): } for label, fieldname in self.sla_status_map.items(): - self.columns.append( - {"label": _(label), "fieldname": fieldname, "fieldtype": "Int", "width": 100} - ) + self.columns.append({"label": _(label), "fieldname": fieldname, "fieldtype": "Int", "width": 100}) self.metrics = [ "Avg First Response Time", @@ -185,8 +189,12 @@ def get_summary_data(self): if d._assign: for entry in json.loads(d._assign): self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault(status, 0.0) - self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault(agreement_status, 0.0) - self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault("total_issues", 0.0) + self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault( + agreement_status, 0.0 + ) + self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault( + "total_issues", 0.0 + ) self.issue_summary_data[entry][status] += 1 self.issue_summary_data[entry][agreement_status] += 1 self.issue_summary_data[entry]["total_issues"] += 1 @@ -229,14 +237,20 @@ def get_metrics_data(self): if d._assign: for entry in json.loads(d._assign): for metric in metrics_list: - self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault(metric, 0.0) + self.issue_summary_data.setdefault(entry, frappe._dict()).setdefault( + metric, 0.0 + ) - self.issue_summary_data[entry]["avg_response_time"] += d.get("avg_response_time") or 0.0 + self.issue_summary_data[entry]["avg_response_time"] += ( + d.get("avg_response_time") or 0.0 + ) self.issue_summary_data[entry]["avg_first_response_time"] += ( d.get("first_response_time") or 0.0 ) self.issue_summary_data[entry]["avg_hold_time"] += d.get("total_hold_time") or 0.0 - self.issue_summary_data[entry]["avg_resolution_time"] += d.get("resolution_time") or 0.0 + self.issue_summary_data[entry]["avg_resolution_time"] += ( + d.get("resolution_time") or 0.0 + ) self.issue_summary_data[entry]["avg_user_resolution_time"] += ( d.get("user_resolution_time") or 0.0 ) @@ -251,9 +265,9 @@ def get_metrics_data(self): else: data = frappe.db.sql( - """ + f""" SELECT - {0}, AVG(first_response_time) as avg_frt, + {field}, AVG(first_response_time) as avg_frt, AVG(avg_response_time) as avg_resp_time, AVG(total_hold_time) as avg_hold_time, AVG(resolution_time) as avg_resolution_time, @@ -261,10 +275,8 @@ def get_metrics_data(self): FROM `tabIssue` WHERE name IN %(issues)s - GROUP BY {0} - """.format( - field - ), + GROUP BY {field} + """, {"issues": issues}, as_dict=1, ) diff --git a/erpnext/support/report/support_hour_distribution/support_hour_distribution.py b/erpnext/support/report/support_hour_distribution/support_hour_distribution.py index 54967213af69..2a978310ddb2 100644 --- a/erpnext/support/report/support_hour_distribution/support_hour_distribution.py +++ b/erpnext/support/report/support_hour_distribution/support_hour_distribution.py @@ -37,8 +37,8 @@ def get_data(filters): hours_count = {"date": start_date} for key, value in time_slots.items(): start_time, end_time = value.split("-") - start_time = get_datetime("{0} {1}".format(start_date.strftime("%Y-%m-%d"), start_time)) - end_time = get_datetime("{0} {1}".format(start_date.strftime("%Y-%m-%d"), end_time)) + start_time = get_datetime("{} {}".format(start_date.strftime("%Y-%m-%d"), start_time)) + end_time = get_datetime("{} {}".format(start_date.strftime("%Y-%m-%d"), end_time)) hours_count[key] = get_hours_count(start_time, end_time) time_slot_wise_total_count[key] = time_slot_wise_total_count.get(key, 0) + hours_count[key] diff --git a/erpnext/telephony/doctype/call_log/call_log.py b/erpnext/telephony/doctype/call_log/call_log.py index 7725e71f19c4..52994c03009b 100644 --- a/erpnext/telephony/doctype/call_log/call_log.py +++ b/erpnext/telephony/doctype/call_log/call_log.py @@ -42,9 +42,7 @@ def after_insert(self): def on_update(self): def _is_call_missed(doc_before_save, doc_after_save): # FIXME: This works for Exotel but not for all telepony providers - return ( - doc_before_save.to != doc_after_save.to and doc_after_save.status not in END_CALL_STATUSES - ) + return doc_before_save.to != doc_after_save.to and doc_after_save.status not in END_CALL_STATUSES def _is_call_ended(doc_before_save, doc_after_save): return doc_before_save.status not in END_CALL_STATUSES and self.status in END_CALL_STATUSES @@ -57,11 +55,11 @@ def _is_call_ended(doc_before_save, doc_after_save): self.update_received_by() if _is_call_missed(doc_before_save, self): - frappe.publish_realtime("call_{id}_missed".format(id=self.id), self) + frappe.publish_realtime(f"call_{self.id}_missed", self) self.trigger_call_popup() if _is_call_ended(doc_before_save, self): - frappe.publish_realtime("call_{id}_ended".format(id=self.id), self) + frappe.publish_realtime(f"call_{self.id}_ended", self) def is_incoming_call(self): return self.type == "Incoming" @@ -155,7 +153,7 @@ def link_existing_conversations(doc, state): END )=0 """, - dict(phone_number="%{}".format(number), docname=doc.name, doctype=doc.doctype), + dict(phone_number=f"%{number}", docname=doc.name, doctype=doc.doctype), ) for log in logs: 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 5edf81df7369..78a441f99614 100644 --- a/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py +++ b/erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.py @@ -3,7 +3,6 @@ from datetime import datetime -from typing import Tuple import frappe from frappe import _ @@ -54,7 +53,7 @@ def validate_call_schedule_overlaps(self, schedule: list): frappe.throw(_("Please fix overlapping time slots for {0}.").format(day)) @staticmethod - def check_timeslots_overlap(ts1: Tuple[int, int], ts2: Tuple[int, int]) -> bool: + def check_timeslots_overlap(ts1: tuple[int, int], ts2: tuple[int, int]) -> bool: if (ts1[0] < ts2[0] and ts1[1] <= ts2[0]) or (ts1[0] >= ts2[1] and ts1[1] > ts2[1]): return False return True diff --git a/erpnext/templates/pages/home.py b/erpnext/templates/pages/home.py index 47fb89dea317..6045b76d6791 100644 --- a/erpnext/templates/pages/home.py +++ b/erpnext/templates/pages/home.py @@ -37,9 +37,7 @@ def get_context(context): ) # filter out homepage section which is used as hero section - homepage_hero_section = ( - homepage.hero_section_based_on == "Homepage Section" and homepage.hero_section - ) + homepage_hero_section = homepage.hero_section_based_on == "Homepage Section" and homepage.hero_section homepage_sections = frappe.get_all( "Homepage Section", filters=[["name", "!=", homepage_hero_section]] if homepage_hero_section else None, diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.py b/erpnext/templates/pages/integrations/gocardless_checkout.py index 655be52c55c7..864a0bff173f 100644 --- a/erpnext/templates/pages/integrations/gocardless_checkout.py +++ b/erpnext/templates/pages/integrations/gocardless_checkout.py @@ -38,9 +38,7 @@ def get_context(context): context["amount"] = flt(context["amount"]) gateway_controller = get_gateway_controller(context.reference_docname) - context["header_img"] = frappe.db.get_value( - "GoCardless Settings", gateway_controller, "header_img" - ) + context["header_img"] = frappe.db.get_value("GoCardless Settings", gateway_controller, "header_img") else: frappe.redirect_to_message( @@ -95,6 +93,6 @@ def check_mandate(data, reference_doctype, reference_docname): return {"redirect_to": redirect_flow.redirect_url} - except Exception as e: + except Exception: frappe.log_error("GoCardless Payment Error") return {"redirect_to": "/integrations/payment-failed"} diff --git a/erpnext/templates/pages/integrations/gocardless_confirmation.py b/erpnext/templates/pages/integrations/gocardless_confirmation.py index 559aa4806d93..0e7405de2027 100644 --- a/erpnext/templates/pages/integrations/gocardless_confirmation.py +++ b/erpnext/templates/pages/integrations/gocardless_confirmation.py @@ -33,7 +33,6 @@ def get_context(context): @frappe.whitelist(allow_guest=True) def confirm_payment(redirect_flow_id, reference_doctype, reference_docname): - client = gocardless_initialization(reference_docname) try: @@ -59,7 +58,7 @@ def confirm_payment(redirect_flow_id, reference_doctype, reference_docname): try: create_mandate(data) - except Exception as e: + except Exception: frappe.log_error("GoCardless Mandate Registration Error") gateway_controller = get_gateway_controller(reference_docname) @@ -67,7 +66,7 @@ def confirm_payment(redirect_flow_id, reference_doctype, reference_docname): return {"redirect_to": confirmation_url} - except Exception as e: + except Exception: frappe.log_error("GoCardless Payment Error") return {"redirect_to": "/integrations/payment-failed"} diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py index 13772d31295d..6219aac69780 100644 --- a/erpnext/templates/pages/order.py +++ b/erpnext/templates/pages/order.py @@ -41,9 +41,7 @@ def get_context(context): context.available_loyalty_points = 0.0 if context.doc.get("customer"): # check for the loyalty program of the customer - customer_loyalty_program = frappe.db.get_value( - "Customer", context.doc.customer, "loyalty_program" - ) + customer_loyalty_program = frappe.db.get_value("Customer", context.doc.customer, "loyalty_program") if customer_loyalty_program: from erpnext.accounts.doctype.loyalty_program.loyalty_program import ( diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py index 0768cc3fa697..c25b63fd6f54 100644 --- a/erpnext/templates/pages/product_search.py +++ b/erpnext/templates/pages/product_search.py @@ -56,10 +56,7 @@ def get_product_data(search=None, start=0, limit=12): search = "%" + cstr(search) + "%" # order by - query += """ ORDER BY ranking desc, modified desc limit %s offset %s""" % ( - cint(limit), - cint(start), - ) + query += f""" ORDER BY ranking desc, modified desc limit {cint(limit)} offset {cint(start)}""" return frappe.db.sql(query, {"search": search}, as_dict=1) # nosemgrep @@ -96,7 +93,9 @@ def product_search(query, limit=10, fuzzy_search=True): ac = AutoCompleter(make_key(WEBSITE_ITEM_NAME_AUTOCOMPLETE), conn=red) client = Client(make_key(WEBSITE_ITEM_INDEX), conn=red) suggestions = ac.get_suggestions( - query, num=limit, fuzzy=fuzzy_search and len(query) > 3 # Fuzzy on length < 3 can be real slow + query, + num=limit, + fuzzy=fuzzy_search and len(query) > 3, # Fuzzy on length < 3 can be real slow ) # Build a query @@ -132,7 +131,7 @@ def get_category_suggestions(query): # Redisearch module not enabled, query db categories = frappe.db.get_all( "Item Group", - filters={"name": ["like", "%{0}%".format(query)], "show_in_website": 1}, + filters={"name": ["like", f"%{query}%"], "show_in_website": 1}, fields=["name", "route"], ) search_results["results"] = categories diff --git a/erpnext/templates/pages/projects.py b/erpnext/templates/pages/projects.py index 4b3089b29166..e3e26fc82a6f 100644 --- a/erpnext/templates/pages/projects.py +++ b/erpnext/templates/pages/projects.py @@ -12,9 +12,7 @@ def get_context(context): ["user", "view_attachments"], as_dict=True, ) - if frappe.session.user != "Administrator" and ( - not project_user or frappe.session.user == "Guest" - ): + if frappe.session.user != "Administrator" and (not project_user or frappe.session.user == "Guest"): raise frappe.PermissionError context.no_cache = 1 @@ -38,7 +36,7 @@ def get_context(context): def get_tasks(project, start=0, search=None, item_status=None): filters = {"project": project} if search: - filters["subject"] = ("like", "%{0}%".format(search)) + filters["subject"] = ("like", f"%{search}%") tasks = frappe.get_all( "Task", filters=filters, @@ -83,7 +81,7 @@ def get_task_html(project, start=0, item_status=None): def get_timesheets(project, start=0, search=None): filters = {"project": project} if search: - filters["activity_type"] = ("like", "%{0}%".format(search)) + filters["activity_type"] = ("like", f"%{search}%") timesheets = frappe.get_all( "Timesheet Detail", diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py index 4b8364249114..8431486d1a37 100644 --- a/erpnext/templates/pages/rfq.py +++ b/erpnext/templates/pages/rfq.py @@ -23,9 +23,7 @@ def get_context(context): def get_supplier(): doctype = frappe.form_dict.doctype - parties_doctype = ( - "Request for Quotation Supplier" if doctype == "Request for Quotation" else doctype - ) + parties_doctype = "Request for Quotation Supplier" if doctype == "Request for Quotation" else doctype customers, suppliers = get_customers_suppliers(parties_doctype, frappe.session.user) return suppliers[0] if suppliers else "" @@ -44,7 +42,7 @@ def check_supplier_has_docname_access(supplier): def unauthorized_user(supplier): status = check_supplier_has_docname_access(supplier) or False - if status == False: + if status is False: frappe.throw(_("Not Permitted"), frappe.PermissionError) @@ -53,9 +51,7 @@ def update_supplier_details(context): context.doc.currency = supplier_doc.default_currency or frappe.get_cached_value( "Company", context.doc.company, "default_currency" ) - context.doc.currency_symbol = frappe.db.get_value( - "Currency", context.doc.currency, "symbol", cache=True - ) + context.doc.currency_symbol = frappe.db.get_value("Currency", context.doc.currency, "symbol", cache=True) context.doc.number_format = frappe.db.get_value( "Currency", context.doc.currency, "number_format", cache=True ) diff --git a/erpnext/templates/pages/search_help.py b/erpnext/templates/pages/search_help.py index d15816704289..18a0a67d0c88 100644 --- a/erpnext/templates/pages/search_help.py +++ b/erpnext/templates/pages/search_help.py @@ -47,9 +47,7 @@ def get_help_results_sections(text): def get_response(api, text): - response = requests.get( - api.base_url + "/" + api.query_route, data={api.search_term_param_name: text} - ) + response = requests.get(api.base_url + "/" + api.query_route, data={api.search_term_param_name: text}) response.raise_for_status() return response.json() diff --git a/erpnext/tests/test_init.py b/erpnext/tests/test_init.py index 18ce93ab8321..2b4ea9fa8dc8 100644 --- a/erpnext/tests/test_init.py +++ b/erpnext/tests/test_init.py @@ -9,36 +9,35 @@ class TestInit(unittest.TestCase): def test_encode_company_abbr(self): - abbr = "NFECT" names = [ "Warehouse Name", "ERPNext Foundation India", - "Gold - Member - {a}".format(a=abbr), - " - {a}".format(a=abbr), + f"Gold - Member - {abbr}", + f" - {abbr}", "ERPNext - Foundation - India", - "ERPNext Foundation India - {a}".format(a=abbr), - "No-Space-{a}".format(a=abbr), + f"ERPNext Foundation India - {abbr}", + f"No-Space-{abbr}", "- Warehouse", ] expected_names = [ - "Warehouse Name - {a}".format(a=abbr), - "ERPNext Foundation India - {a}".format(a=abbr), - "Gold - Member - {a}".format(a=abbr), - " - {a}".format(a=abbr), - "ERPNext - Foundation - India - {a}".format(a=abbr), - "ERPNext Foundation India - {a}".format(a=abbr), - "No-Space-{a} - {a}".format(a=abbr), - "- Warehouse - {a}".format(a=abbr), + f"Warehouse Name - {abbr}", + f"ERPNext Foundation India - {abbr}", + f"Gold - Member - {abbr}", + f" - {abbr}", + f"ERPNext - Foundation - India - {abbr}", + f"ERPNext Foundation India - {abbr}", + f"No-Space-{abbr} - {abbr}", + f"- Warehouse - {abbr}", ] for i in range(len(names)): enc_name = encode_company_abbr(names[i], abbr=abbr) self.assertTrue( enc_name == expected_names[i], - "{enc} is not same as {exp}".format(enc=enc_name, exp=expected_names[i]), + f"{enc_name} is not same as {expected_names[i]}", ) def test_translation_files(self): diff --git a/erpnext/tests/test_webform.py b/erpnext/tests/test_webform.py index 202467b54506..6ff668745dae 100644 --- a/erpnext/tests/test_webform.py +++ b/erpnext/tests/test_webform.py @@ -9,12 +9,8 @@ class TestWebsite(unittest.TestCase): def test_permission_for_custom_doctype(self): create_user("Supplier 1", "supplier1@gmail.com") create_user("Supplier 2", "supplier2@gmail.com") - create_supplier_with_contact( - "Supplier1", "All Supplier Groups", "Supplier 1", "supplier1@gmail.com" - ) - create_supplier_with_contact( - "Supplier2", "All Supplier Groups", "Supplier 2", "supplier2@gmail.com" - ) + create_supplier_with_contact("Supplier1", "All Supplier Groups", "Supplier 1", "supplier1@gmail.com") + create_supplier_with_contact("Supplier2", "All Supplier Groups", "Supplier 2", "supplier2@gmail.com") po1 = create_purchase_order(supplier="Supplier1") po2 = create_purchase_order(supplier="Supplier2") @@ -62,9 +58,9 @@ def create_user(name, email): def create_supplier_with_contact(name, group, contact_name, contact_email): - supplier = frappe.get_doc( - {"doctype": "Supplier", "supplier_name": name, "supplier_group": group} - ).insert(ignore_if_duplicate=True) + supplier = frappe.get_doc({"doctype": "Supplier", "supplier_name": name, "supplier_group": group}).insert( + ignore_if_duplicate=True + ) if not frappe.db.exists("Contact", contact_name + "-1-" + name): new_contact = frappe.new_doc("Contact") diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index 159ce7078e39..29980c000d1c 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -1,12 +1,12 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt -from typing import Any, Dict, NewType, Optional +from typing import Any, NewType import frappe from frappe.core.doctype.report.report import get_report_module_dotted_path -ReportFilters = Dict[str, Any] +ReportFilters = dict[str, Any] ReportName = NewType("ReportName", str) @@ -57,8 +57,8 @@ def execute_script_report( report_name: ReportName, module: str, filters: ReportFilters, - default_filters: Optional[ReportFilters] = None, - optional_filters: Optional[ReportFilters] = None, + default_filters: ReportFilters | None = None, + optional_filters: ReportFilters | None = None, ): """Util for testing execution of a report with specified filters. @@ -77,9 +77,7 @@ def execute_script_report( default_filters = {} test_filters = [] - report_execute_fn = frappe.get_attr( - get_report_module_dotted_path(module, report_name) + ".execute" - ) + report_execute_fn = frappe.get_attr(get_report_module_dotted_path(module, report_name) + ".execute") report_filters = frappe._dict(default_filters).copy().update(filters) test_filters.append(report_filters) diff --git a/erpnext/utilities/activation.py b/erpnext/utilities/activation.py index 4c8379e41c08..5a72f13b4a53 100644 --- a/erpnext/utilities/activation.py +++ b/erpnext/utilities/activation.py @@ -54,9 +54,7 @@ def get_level(): sales_data.append({"Communication": communication_number}) # recent login - if frappe.db.sql( - "select name from tabUser where last_login > date_sub(now(), interval 2 day) limit 1" - ): + if frappe.db.sql("select name from tabUser where last_login > date_sub(now(), interval 2 day) limit 1"): activation_level += 1 level = {"activation_level": activation_level, "sales_data": sales_data} diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index 17146e50d674..42cfc807aaa3 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -15,9 +15,7 @@ def transaction_processing(data, from_doctype, to_doctype): length_of_data = len(deserialized_data) - frappe.msgprint( - _("Started a background job to create {1} {0}").format(to_doctype, length_of_data) - ) + frappe.msgprint(_("Started a background job to create {1} {0}").format(to_doctype, length_of_data)) frappe.enqueue( job, deserialized_data=deserialized_data, @@ -57,7 +55,7 @@ def retry_failed_transactions(failed_docs: list | None): try: frappe.db.savepoint("before_creation_state") task(log.transaction_name, log.from_doctype, log.to_doctype) - except Exception as e: + except Exception: frappe.db.rollback(save_point="before_creation_state") update_log(log.name, "Failed", 1, str(frappe.get_traceback(with_context=True))) else: @@ -78,7 +76,7 @@ def job(deserialized_data, from_doctype, to_doctype): doc_name = d.get("name") frappe.db.savepoint("before_creation_state") task(doc_name, from_doctype, to_doctype) - except Exception as e: + except Exception: frappe.db.rollback(save_point="before_creation_state") fail_count += 1 create_log( @@ -90,9 +88,7 @@ def job(deserialized_data, from_doctype, to_doctype): log_date=str(date.today()), ) else: - create_log( - doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today()) - ) + create_log(doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today())) show_job_status(fail_count, len(deserialized_data), to_doctype) diff --git a/erpnext/utilities/doctype/video/video.py b/erpnext/utilities/doctype/video/video.py index 13b7877b21d8..bb494c1f0b09 100644 --- a/erpnext/utilities/doctype/video/video.py +++ b/erpnext/utilities/doctype/video/video.py @@ -92,9 +92,7 @@ def get_id_from_url(url): if not isinstance(url, str): frappe.throw(_("URL can only be a string"), title=_("Invalid URL")) - pattern = re.compile( - r'[a-z\:\//\.]+(youtube|youtu)\.(com|be)/(watch\?v=|embed/|.+\?v=)?([^"&?\s]{11})?' - ) + pattern = re.compile(r'[a-z\:\//\.]+(youtube|youtu)\.(com|be)/(watch\?v=|embed/|.+\?v=)?([^"&?\s]{11})?') id = pattern.match(url) return id.groups()[-1] diff --git a/erpnext/utilities/naming.py b/erpnext/utilities/naming.py index 52bbadef1486..84079efa2d77 100644 --- a/erpnext/utilities/naming.py +++ b/erpnext/utilities/naming.py @@ -6,9 +6,7 @@ class NamingSeriesNotSetError(frappe.ValidationError): pass -def set_by_naming_series( - doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1 -): +def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1): """Change a doctype's naming to user naming series""" from frappe.custom.doctype.property_setter.property_setter import make_property_setter @@ -24,9 +22,7 @@ def set_by_naming_series( try: frappe.db.sql( """update `tab{doctype}` set naming_series={s} where - ifnull(naming_series, '')=''""".format( - doctype=doctype, s="%s" - ), + ifnull(naming_series, '')=''""".format(doctype=doctype, s="%s"), get_default_naming_series(doctype), ) except NamingSeriesNotSetError: @@ -34,27 +30,19 @@ def set_by_naming_series( if hide_name_field: make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False) - make_property_setter( - doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False - ) + make_property_setter(doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False) else: - make_property_setter( - doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False - ) + make_property_setter(doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False) make_property_setter( doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False ) if hide_name_field: - make_property_setter( - doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False - ) + make_property_setter(doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False) make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False) # set values for mandatory frappe.db.sql( - """update `tab{doctype}` set `{fieldname}`=`name` where - ifnull({fieldname}, '')=''""".format( - doctype=doctype, fieldname=fieldname - ) + f"""update `tab{doctype}` set `{fieldname}`=`name` where + ifnull({fieldname}, '')=''""" ) diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 69559c1ed9b1..14a433d0ceda 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -57,9 +57,7 @@ def get_web_item_qty_in_stock(item_code, item_warehouse_field, warehouse=None): in_stock = int(total_stock > 0) - return frappe._dict( - {"in_stock": in_stock, "stock_qty": total_stock, "is_stock_item": is_stock_item} - ) + return frappe._dict({"in_stock": in_stock, "stock_qty": total_stock, "is_stock_item": is_stock_item}) def adjust_qty_for_expired_items(item_code, stock_qty, warehouse): @@ -150,7 +148,9 @@ def get_price(item_code, price_list, customer_group, company, qty=1): if pricing_rule.pricing_rule_for == "Rate": rate_discount = flt(mrp) - flt(pricing_rule.price_list_rate) if rate_discount > 0: - price_obj.formatted_discount_rate = fmt_money(rate_discount, currency=price_obj["currency"]) + price_obj.formatted_discount_rate = fmt_money( + rate_discount, currency=price_obj["currency"] + ) price_obj.price_list_rate = pricing_rule.price_list_rate or 0 if price_obj: @@ -198,9 +198,7 @@ def get_non_stock_item_status(item_code, item_warehouse_field): # if item is a product bundle, check if its bundle items are in stock if frappe.db.exists("Product Bundle", item_code): items = frappe.get_doc("Product Bundle", item_code).get_all_children() - bundle_warehouse = frappe.db.get_value( - "Website Item", {"item_code": item_code}, item_warehouse_field - ) + bundle_warehouse = frappe.db.get_value("Website Item", {"item_code": item_code}, item_warehouse_field) return all( get_web_item_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index b083614a5f7c..d89095ef3d35 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -58,9 +58,7 @@ def validate_with_previous_doc(self, ref): def compare_values(self, ref_doc, fields, doc=None): for reference_doctype, ref_dn_list in ref_doc.items(): - prev_doc_detail_map = self.get_prev_doc_reference_details( - ref_dn_list, reference_doctype, fields - ) + prev_doc_detail_map = self.get_prev_doc_reference_details(ref_dn_list, reference_doctype, fields) for reference_name in ref_dn_list: prevdoc_values = prev_doc_detail_map.get(reference_name) if not prevdoc_values: diff --git a/erpnext/www/all-products/index.py b/erpnext/www/all-products/index.py index fbf0dce0590b..bd4d706ee347 100644 --- a/erpnext/www/all-products/index.py +++ b/erpnext/www/all-products/index.py @@ -15,8 +15,6 @@ def get_context(context): context.field_filters = filter_engine.get_field_filters() context.attribute_filters = filter_engine.get_attribute_filters() - context.page_length = ( - cint(frappe.db.get_single_value("E Commerce Settings", "products_per_page")) or 20 - ) + context.page_length = cint(frappe.db.get_single_value("E Commerce Settings", "products_per_page")) or 20 context.no_cache = 1 From b087fb3d549462ea8c9d1e65e8622e952d4039f6 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 27 Mar 2024 12:16:13 +0530 Subject: [PATCH 50/72] fix(treewide): manual ruff fixes (cherry picked from commit f63396ef47abc6f667f4fd3fb96c52a0a6bd218a) (cherry picked from commit 7828eee01432e5c3125760308b09154e7ff7dfee) Signed-off-by: Akhil Narang --- .../chart_of_accounts/import_from_openerp.py | 2 +- .../bisect_accounting_statements.py | 20 ----------- erpnext/accounts/doctype/budget/budget.py | 7 ++-- .../test_invoice_discounting.py | 4 +-- .../payment_entry/test_payment_entry.py | 2 +- .../test_payment_ledger_entry.py | 16 ++++++--- .../test_payment_reconciliation.py | 20 ++++++++--- .../pos_invoice_merge_log.py | 2 +- .../process_payment_reconciliation.py | 2 +- .../purchase_invoice/test_purchase_invoice.py | 2 +- .../sales_invoice/test_sales_invoice.py | 35 ------------------- .../report/cash_flow/custom_cash_flow.py | 2 +- .../deferred_revenue_and_expense.py | 4 +-- .../report/general_ledger/general_ledger.py | 2 +- .../report/gross_profit/gross_profit.py | 2 +- .../report/gross_profit/test_gross_profit.py | 10 ++++-- .../purchase_order/test_purchase_order.py | 2 +- .../test_procurement_tracker.py | 9 ----- .../tests/test_accounts_controller.py | 10 ++++-- .../tests/test_subcontracting_controller.py | 4 +-- .../appointment_booking_settings.py | 3 +- .../variant_selector/item_variants_cache.py | 2 +- erpnext/e_commerce/variant_selector/utils.py | 2 +- .../gocardless_settings.py | 3 +- .../doctype/mpesa_settings/mpesa_settings.py | 3 +- .../production_plan/production_plan.py | 2 +- .../exponential_smoothing_forecasting.py | 2 +- .../patches/v12_0/update_due_date_in_gle.py | 6 ++-- .../selling/page/sales_funnel/sales_funnel.py | 2 +- .../doctype/holiday_list/test_holiday_list.py | 8 ++++- .../transaction_deletion_record.py | 7 +--- .../item_variant_settings.py | 4 +-- .../doctype/packed_item/test_packed_item.py | 8 ++--- .../doctype/stock_entry/test_stock_entry.py | 11 +++--- .../test_stock_ledger_entry.py | 6 ++-- .../stock_reconciliation.py | 4 +-- erpnext/stock/doctype/warehouse/warehouse.py | 2 +- .../cogs_by_item_group/cogs_by_item_group.py | 3 +- 38 files changed, 98 insertions(+), 137 deletions(-) delete mode 100644 erpnext/buying/report/procurement_tracker/test_procurement_tracker.py diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py index 928d51d98980..070447863f40 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/import_from_openerp.py @@ -253,7 +253,7 @@ def make_charts(): for key, val in chart["tree"].items(): if key in ["name", "parent_id"]: chart["tree"].pop(key) - if type(val) == dict: + if isinstance(val, dict): val["root_type"] = "" if chart: fpath = os.path.join( diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index da273b9f8917..f2ed299592b6 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -14,26 +14,6 @@ class BisectAccountingStatements(Document): - # begin: auto-generated types - # This code is auto-generated. Do not modify anything in this block. - - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from frappe.types import DF - - algorithm: DF.Literal["BFS", "DFS"] - b_s_summary: DF.Float - company: DF.Link | None - current_from_date: DF.Datetime | None - current_node: DF.Link | None - current_to_date: DF.Datetime | None - difference: DF.Float - from_date: DF.Datetime | None - p_l_summary: DF.Float - to_date: DF.Datetime | None - # end: auto-generated types - def validate(self): self.validate_dates() diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index bdff463a8690..f7b2c377f3a5 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -348,12 +348,9 @@ def get_actual_expense(args): args.update(lft_rgt) - condition2 = """and exists(select name from `tab{doctype}` + condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}` where lft>=%(lft)s and rgt<=%(rgt)s - and name=gle.{budget_against_field})""".format( - doctype=args.budget_against_doctype, - budget_against_field=budget_against_field, # nosec - ) + and name=gle.{budget_against_field})""" else: condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}` where name=gle.{budget_against_field} and diff --git a/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py index 65e3c3dcd6ad..01050c058e8c 100644 --- a/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py @@ -75,8 +75,8 @@ def test_gl_entries_in_base_currency(self): gle = get_gl_entries("Invoice Discounting", inv_disc.name) expected_gle = {inv.debit_to: [0.0, 200], self.ar_credit: [200, 0.0]} - for _i, gle in enumerate(gle): - self.assertEqual([gle.debit, gle.credit], expected_gle.get(gle.account)) + for _i, gle_value in enumerate(gle): + self.assertEqual([gle_value.debit, gle_value.credit], expected_gle.get(gle_value.account)) def test_loan_on_submit(self): inv = create_sales_invoice(rate=300) diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index ec3b4196bdec..c600198999eb 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -162,7 +162,7 @@ def test_payment_entry_for_blocked_supplier_payments_past_date(self): supplier.on_hold = 0 supplier.save() - except: + except Exception: pass else: raise Exception diff --git a/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py b/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py index c867e68d1a6f..3eac98d79100 100644 --- a/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py +++ b/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py @@ -84,11 +84,14 @@ def create_customer(self): self.customer = customer.name def create_sales_invoice( - self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False + self, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False ): """ Helper function to populate default values in sales invoice """ + if posting_date is None: + posting_date = nowdate() + sinv = create_sales_invoice( qty=qty, rate=rate, @@ -112,10 +115,12 @@ def create_sales_invoice( ) return sinv - def create_payment_entry(self, amount=100, posting_date=nowdate()): + def create_payment_entry(self, amount=100, posting_date=None): """ Helper function to populate default values in payment entry """ + if posting_date is None: + posting_date = nowdate() payment = create_payment_entry( company=self.company, payment_type="Receive", @@ -128,9 +133,10 @@ def create_payment_entry(self, amount=100, posting_date=nowdate()): payment.posting_date = posting_date return payment - def create_sales_order( - self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False - ): + def create_sales_order(self, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False): + if posting_date is None: + posting_date = nowdate() + so = make_sales_order( company=self.company, transaction_date=posting_date, diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index 25525a483e29..22f05957a79b 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -126,11 +126,14 @@ def create_account(self): setattr(self, x.attribute, acc.name) def create_sales_invoice( - self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False + self, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False ): """ Helper function to populate default values in sales invoice """ + if posting_date is None: + posting_date = nowdate() + sinv = create_sales_invoice( qty=qty, rate=rate, @@ -154,10 +157,13 @@ def create_sales_invoice( ) return sinv - def create_payment_entry(self, amount=100, posting_date=nowdate(), customer=None): + def create_payment_entry(self, amount=100, posting_date=None, customer=None): """ Helper function to populate default values in payment entry """ + if posting_date is None: + posting_date = nowdate() + payment = create_payment_entry( company=self.company, payment_type="Receive", @@ -171,11 +177,14 @@ def create_payment_entry(self, amount=100, posting_date=nowdate(), customer=None return payment def create_purchase_invoice( - self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False + self, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False ): """ Helper function to populate default values in sales invoice """ + if posting_date is None: + posting_date = nowdate() + pinv = make_purchase_invoice( qty=qty, rate=rate, @@ -200,11 +209,14 @@ def create_purchase_invoice( return pinv def create_purchase_order( - self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False + self, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False ): """ Helper function to populate default values in sales invoice """ + if posting_date is None: + posting_date = nowdate() + pord = create_purchase_order( qty=qty, rate=rate, 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 5b0d1cfa8ce8..1302a0c386c7 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 @@ -440,7 +440,7 @@ def create_merge_logs(invoice_by_customer, closing_entry=None): if closing_entry: closing_entry.set_status(update=True, status="Failed") - if type(error_message) == list: + if isinstance(error_message, list): error_message = frappe.json.dumps(error_message) closing_entry.db_set("error_message", error_message) raise 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 33cff14ac4e1..c7535e76d7e7 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py @@ -478,7 +478,7 @@ def reconcile(doc: None | str = None) -> None: def is_any_doc_running(for_filter: str | dict | None = None) -> str | None: running_doc = None if for_filter: - if type(for_filter) == str: + if isinstance(for_filter, str): for_filter = frappe.json.loads(for_filter) running_doc = frappe.db.get_value( diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 109b2e8ea62d..22e28e6ce36d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -216,7 +216,7 @@ def test_purchase_invoice_for_blocked_supplier_payment_past_date(self): supplier.on_hold = 0 supplier.save() - except: + except Exception: pass else: raise Exception diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index ea9f01510743..87d297f4aa12 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3521,41 +3521,6 @@ def test_taxes_merging_from_delivery_note(self): self.assertEqual(expected, actual) -def get_sales_invoice_for_e_invoice(): - si = make_sales_invoice_for_ewaybill() - si.naming_series = "INV-2020-.#####" - si.items = [] - si.append( - "items", - { - "item_code": "_Test Item", - "uom": "Nos", - "warehouse": "_Test Warehouse - _TC", - "qty": 2000, - "rate": 12, - "income_account": "Sales - _TC", - "expense_account": "Cost of Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC", - }, - ) - - si.append( - "items", - { - "item_code": "_Test Item 2", - "uom": "Nos", - "warehouse": "_Test Warehouse - _TC", - "qty": 420, - "rate": 15, - "income_account": "Sales - _TC", - "expense_account": "Cost of Goods Sold - _TC", - "cost_center": "_Test Cost Center - _TC", - }, - ) - - return si - - def check_gl_entries(doc, voucher_no, expected_gle, posting_date): gl_entries = frappe.db.sql( """select account, debit, credit, posting_date diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py index 2e227609b0ee..ea79917045d1 100644 --- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py +++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py @@ -473,7 +473,7 @@ def execute(filters=None): def _get_account_type_based_data(filters, account_names, period_list, accumulated_values, opening_balances=0): - if not account_names or not account_names[0] or not type(account_names[0]) == str: + if not account_names or not account_names[0] or not isinstance(account_names[0], str): # only proceed if account_names is a list of account names return {} diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py index 303305d20c58..8999ef710f04 100644 --- a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py +++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py @@ -192,7 +192,7 @@ def calculate_invoice_revenue_expense_for_period(self): for item in self.items: item_total = item.calculate_item_revenue_expense_for_period() # update invoice total - for idx, period in enumerate(self.period_list, 0): + for idx in range(len(self.period_list)): self.period_total[idx].total += item_total[idx].total self.period_total[idx].actual += item_total[idx].actual return self.period_total @@ -346,7 +346,7 @@ def calculate_revenue_and_expense(self): for inv in self.deferred_invoices: inv_total = inv.calculate_invoice_revenue_expense_for_period() # calculate total for whole report - for idx, period in enumerate(self.period_list, 0): + for idx in range(len(self.period_list)): self.period_total[idx].total += inv_total[idx].total self.period_total[idx].actual += inv_total[idx].actual diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 685797abd195..f70aec743d2d 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -477,7 +477,7 @@ def update_value_in_dict(data, key, gle): else: update_value_in_dict(consolidated_gle, key, gle) - for key, value in consolidated_gle.items(): + for value in consolidated_gle.values(): update_value_in_dict(totals, "total", value) update_value_in_dict(totals, "closing", value) entries.append(value) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 0d61a33e0648..53be730ce577 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -494,7 +494,7 @@ def process(self): def get_average_rate_based_on_group_by(self): for key in list(self.grouped): if self.filters.get("group_by") == "Invoice": - for i, row in enumerate(self.grouped[key]): + for row in self.grouped[key]: if row.indent == 1.0: if ( row.parent in self.returned_invoices diff --git a/erpnext/accounts/report/gross_profit/test_gross_profit.py b/erpnext/accounts/report/gross_profit/test_gross_profit.py index 8d15900741e9..741ea46a5167 100644 --- a/erpnext/accounts/report/gross_profit/test_gross_profit.py +++ b/erpnext/accounts/report/gross_profit/test_gross_profit.py @@ -86,11 +86,14 @@ def create_customer(self): self.customer = customer.name def create_sales_invoice( - self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False + self, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False ): """ Helper function to populate default values in sales invoice """ + if posting_date is None: + posting_date = nowdate() + sinv = create_sales_invoice( qty=qty, rate=rate, @@ -115,11 +118,14 @@ def create_sales_invoice( return sinv def create_delivery_note( - self, item=None, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False + self, item=None, qty=1, rate=100, posting_date=None, do_not_save=False, do_not_submit=False ): """ Helper function to populate default values in Delivery Note """ + if posting_date is None: + posting_date = nowdate() + dnote = create_delivery_note( company=self.company, customer=self.customer, diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index a95be2969f54..38cb0fbf7ab0 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -692,7 +692,7 @@ def test_po_for_blocked_supplier_payments_past_date(self): supplier.on_hold = 0 supplier.save() - except: + except Exception: pass else: raise Exception diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py deleted file mode 100644 index ebceb7f655a5..000000000000 --- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.tests.utils import FrappeTestCase - - -class TestProcurementTracker(FrappeTestCase): - pass diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 5bfed8cddeb5..92bbc0577333 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -140,13 +140,16 @@ def create_sales_invoice( qty=1, rate=1, conversion_rate=80, - posting_date=nowdate(), + posting_date=None, do_not_save=False, do_not_submit=False, ): """ Helper function to populate default values in sales invoice """ + if posting_date is None: + posting_date = nowdate() + sinv = create_sales_invoice( qty=qty, rate=rate, @@ -171,10 +174,13 @@ def create_sales_invoice( ) return sinv - def create_payment_entry(self, amount=1, source_exc_rate=75, posting_date=nowdate(), customer=None): + def create_payment_entry(self, amount=1, source_exc_rate=75, posting_date=None, customer=None): """ Helper function to populate default values in payment entry """ + if posting_date is None: + posting_date = nowdate() + payment = create_payment_entry( company=self.company, payment_type="Receive", diff --git a/erpnext/controllers/tests/test_subcontracting_controller.py b/erpnext/controllers/tests/test_subcontracting_controller.py index c7cda2dea988..4e5df6e91952 100644 --- a/erpnext/controllers/tests/test_subcontracting_controller.py +++ b/erpnext/controllers/tests/test_subcontracting_controller.py @@ -551,7 +551,7 @@ def test_item_with_batch_based_on_material_transfer(self): scr2.set_missing_values() scr2.submit() - for key, value in get_supplied_items(scr2).items(): + for value in get_supplied_items(scr2).values(): self.assertEqual(value.qty, 4) scr3 = make_subcontracting_receipt(sco.name) @@ -561,7 +561,7 @@ def test_item_with_batch_based_on_material_transfer(self): scr3.set_missing_values() scr3.submit() - for key, value in get_supplied_items(scr3).items(): + for value in get_supplied_items(scr3).values(): self.assertEqual(value.qty, 1) def test_partial_transfer_serial_no_components_based_on_material_transfer(self): 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 57e80f9abc88..cd09172b0c8e 100644 --- a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py +++ b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py @@ -3,6 +3,7 @@ import datetime +import typing import frappe from frappe import _ @@ -10,7 +11,7 @@ class AppointmentBookingSettings(Document): - agent_list = [] # Hack + agent_list: typing.ClassVar[list] = [] # Hack min_date = "01/01/1970 " format_string = "%d/%m/%Y %H:%M:%S" diff --git a/erpnext/e_commerce/variant_selector/item_variants_cache.py b/erpnext/e_commerce/variant_selector/item_variants_cache.py index f8439d5d43d0..194ef03ea39d 100644 --- a/erpnext/e_commerce/variant_selector/item_variants_cache.py +++ b/erpnext/e_commerce/variant_selector/item_variants_cache.py @@ -87,7 +87,7 @@ def build_cache(self): item_attribute_value_map.setdefault(item_code, {})[attribute] = attribute_value optional_attributes = set() - for item_code, attr_dict in item_attribute_value_map.items(): + for attr_dict in item_attribute_value_map.values(): for attribute in attributes: if attribute not in attr_dict: optional_attributes.add(attribute) diff --git a/erpnext/e_commerce/variant_selector/utils.py b/erpnext/e_commerce/variant_selector/utils.py index ea7221ed674e..14d7b7cbf8f6 100644 --- a/erpnext/e_commerce/variant_selector/utils.py +++ b/erpnext/e_commerce/variant_selector/utils.py @@ -80,7 +80,7 @@ def get_attributes_and_values(item_code): attribute_list = [a.attribute for a in attributes] valid_options = {} - for item_code, attribute, attribute_value in item_variants_data: + for _, attribute, attribute_value in item_variants_data: if attribute in attribute_list: valid_options.setdefault(attribute, set()).add(attribute_value) diff --git a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py index 93cab9e4e4ab..a257ffc2113f 100644 --- a/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py +++ b/erpnext/erpnext_integrations/doctype/gocardless_settings/gocardless_settings.py @@ -2,6 +2,7 @@ # For license information, please see license.txt +import typing from urllib.parse import urlencode import frappe @@ -15,7 +16,7 @@ class GoCardlessSettings(Document): - supported_currencies = ["EUR", "DKK", "GBP", "SEK", "AUD", "NZD", "CAD", "USD"] + supported_currencies: typing.ClassVar[list] = ["EUR", "DKK", "GBP", "SEK", "AUD", "NZD", "CAD", "USD"] def validate(self): self.initialize_client() diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py index d42112991783..57fb2c0153af 100644 --- a/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py +++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/mpesa_settings.py @@ -2,6 +2,7 @@ # For license information, please see license.txt +import typing from json import dumps, loads import frappe @@ -19,7 +20,7 @@ class MpesaSettings(Document): - supported_currencies = ["KES"] + supported_currencies: typing.ClassVar[list] = ["KES"] def validate_transaction_currency(self, currency): if currency not in self.supported_currencies: diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index aedd25a05e01..f4822fe583a4 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -1503,7 +1503,7 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d so_item_details[sales_order][item_code] = details mr_items = [] - for sales_order, item_code in so_item_details.items(): + for sales_order in so_item_details: item_dict = so_item_details[sales_order] for details in item_dict.values(): bin_dict = get_bin_details(details, doc.company, warehouse) diff --git a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py index 26b933c52dd7..0155b19d14c0 100644 --- a/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py +++ b/erpnext/manufacturing/report/exponential_smoothing_forecasting/exponential_smoothing_forecasting.py @@ -87,7 +87,7 @@ def prepare_periodical_data(self): entry.get(self.based_on_field) ) - for key, value in self.period_wise_data.items(): + for value in self.period_wise_data.values(): list_of_period_value = [value.get(p.key, 0) for p in self.period_list] if list_of_period_value: diff --git a/erpnext/patches/v12_0/update_due_date_in_gle.py b/erpnext/patches/v12_0/update_due_date_in_gle.py index a1c4f51ad017..693311001de0 100644 --- a/erpnext/patches/v12_0/update_due_date_in_gle.py +++ b/erpnext/patches/v12_0/update_due_date_in_gle.py @@ -8,13 +8,11 @@ def execute(): frappe.reload_doc("accounts", "doctype", frappe.scrub(doctype)) frappe.db.sql( - """ UPDATE `tabGL Entry`, `tab{doctype}` + f""" UPDATE `tabGL Entry`, `tab{doctype}` SET `tabGL Entry`.due_date = `tab{doctype}`.due_date WHERE `tabGL Entry`.voucher_no = `tab{doctype}`.name and `tabGL Entry`.party is not null and `tabGL Entry`.voucher_type in ('Sales Invoice', 'Purchase Invoice', 'Journal Entry') - and `tabGL Entry`.account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable'))""".format( # nosec - doctype=doctype - ) + and `tabGL Entry`.account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable'))""" ) diff --git a/erpnext/selling/page/sales_funnel/sales_funnel.py b/erpnext/selling/page/sales_funnel/sales_funnel.py index 155d21ed5d19..24bb0d2fe717 100644 --- a/erpnext/selling/page/sales_funnel/sales_funnel.py +++ b/erpnext/selling/page/sales_funnel/sales_funnel.py @@ -100,7 +100,7 @@ def get_opp_by_lead_source(from_date, to_date, company): pivot_table = [] for sales_stage in sales_stages: row = [] - for source, sales_stage_values in summary.items(): + for sales_stage_values in summary.values(): row.append(flt(sales_stage_values.get(sales_stage))) pivot_table.append({"chartType": "bar", "name": sales_stage, "values": row}) diff --git a/erpnext/setup/doctype/holiday_list/test_holiday_list.py b/erpnext/setup/doctype/holiday_list/test_holiday_list.py index 21dacc624b66..0d3c35fb2cf5 100644 --- a/erpnext/setup/doctype/holiday_list/test_holiday_list.py +++ b/erpnext/setup/doctype/holiday_list/test_holiday_list.py @@ -112,7 +112,13 @@ def test_localized_country_names(self): frappe.local.lang = lang -def make_holiday_list(name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None): +def make_holiday_list(name, from_date=None, to_date=None, holiday_dates=None): + if from_date is None: + from_date = getdate() - timedelta(days=10) + + if to_date is None: + to_date = getdate() + frappe.delete_doc_if_exists("Holiday List", name, force=1) doc = frappe.get_doc( { 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 3cda609f0432..2b4d0754759a 100644 --- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py +++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py @@ -456,12 +456,7 @@ def is_deletion_doc_running(company: str | None = None, err_msg: str | None = No def check_for_running_deletion_job(doc, method=None): # Check if DocType has 'company' field df = qb.DocType("DocField") - if ( - not_allowed := qb.from_(df) - .select(df.parent) - .where((df.fieldname == "company") & (df.parent == doc.doctype)) - .run() - ): + if qb.from_(df).select(df.parent).where((df.fieldname == "company") & (df.parent == doc.doctype)).run(): is_deletion_doc_running( doc.company, _("Cannot make any transactions until the deletion job is completed") ) 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 3fcdb7b49bd9..7a6d39045c44 100644 --- a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py +++ b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.py @@ -1,6 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt - +import typing import frappe from frappe import _ @@ -8,7 +8,7 @@ class ItemVariantSettings(Document): - invalid_fields_for_copy_fields_in_variants = ["barcodes"] + invalid_fields_for_copy_fields_in_variants: typing.ClassVar[list] = ["barcodes"] def set_default_fields(self): self.fields = [] diff --git a/erpnext/stock/doctype/packed_item/test_packed_item.py b/erpnext/stock/doctype/packed_item/test_packed_item.py index 3f87cede7d6c..24a302f009f4 100644 --- a/erpnext/stock/doctype/packed_item/test_packed_item.py +++ b/erpnext/stock/doctype/packed_item/test_packed_item.py @@ -182,12 +182,12 @@ def assertReturns(self, original, returned): def sort_function(p): return p.parent_item, p.item_code, p.qty - for sent, returned in zip( + for sent_item, returned_item in zip( sorted(original, key=sort_function), sorted(returned, key=sort_function), strict=False ): - self.assertEqual(sent.item_code, returned.item_code) - self.assertEqual(sent.parent_item, returned.parent_item) - self.assertEqual(sent.qty, -1 * returned.qty) + self.assertEqual(sent_item.item_code, returned_item.item_code) + self.assertEqual(sent_item.parent_item, returned_item.parent_item) + self.assertEqual(sent_item.qty, -1 * returned_item.qty) def test_returning_full_bundles(self): from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index d45207e23a00..571ad4bea1d1 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -2,10 +2,9 @@ # License: GNU General Public License v3. See license.txt -import frappe from frappe.permissions import add_user_permission, remove_user_permission from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import add_days, flt, nowdate, nowtime, today +from frappe.utils import add_days, flt, nowtime, today from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.stock.doctype.item.test_item import ( @@ -518,10 +517,10 @@ def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle): self.assertTrue(sle) sle.sort(key=lambda x: x[1]) - for i, sle in enumerate(sle): - self.assertEqual(expected_sle[i][0], sle[0]) - self.assertEqual(expected_sle[i][1], sle[1]) - self.assertEqual(expected_sle[i][2], sle[2]) + for i, sle_value in enumerate(sle): + self.assertEqual(expected_sle[i][0], sle_value[0]) + self.assertEqual(expected_sle[i][1], sle_value[1]) + self.assertEqual(expected_sle[i][2], sle_value[2]) def check_gl_entries(self, voucher_type, voucher_no, expected_gl_entries): expected_gl_entries.sort(key=lambda x: x[0]) 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 80a44d902a36..2b01ada10929 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 @@ -900,14 +900,14 @@ def test_fifo_dependent_consumption(self): receipt.submit() expected_queues = [] - for idx, rate in enumerate(rates, start=1): + for idx in range(1, len(rates) + 1): expected_queues.append({"stock_queue": [[10, 10 * i] for i in range(1, idx + 1)]}) self.assertSLEs(receipt, expected_queues) transfer = make_stock_entry( item_code=item.name, source=source, target=target, qty=10, do_not_save=True, rate=10 ) - for rate in rates[1:]: + for _ in rates[1:]: row = frappe.copy_doc(transfer.items[0], ignore_no_copy=False) transfer.append("items", row) @@ -936,7 +936,7 @@ def test_fifo_multi_item_repack_consumption(self): repack = make_stock_entry( item_code=rm.name, source=warehouse, qty=10, do_not_save=True, rate=10, purpose="Repack" ) - for rate in rates[1:]: + for _ in rates[1:]: row = frappe.copy_doc(repack.items[0], ignore_no_copy=False) repack.append("items", row) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 6aaecb1c1658..d78e3c140489 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -550,9 +550,7 @@ def merge_similar_item_serial_nos(self, sl_entries): data.incoming_rate = (data.total_amount) / data.actual_qty - for key, value in merge_similar_entries.items(): - new_sl_entries.append(value) - + new_sl_entries.extend(merge_similar_entries.values()) return new_sl_entries def get_gl_entries(self, warehouse_account=None): diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index a8c2c2891257..e980c53670de 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -188,7 +188,7 @@ def get_child_warehouses(warehouse): from frappe.utils.nestedset import get_descendants_of children = get_descendants_of("Warehouse", warehouse, ignore_permissions=True, order_by="lft") - return children + [warehouse] # append self for backward compatibility + return [*children, warehouse] # append self for backward compatibility def get_warehouses_based_on_account(account, company=None): diff --git a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py index b3c8e93e4e17..07119411304e 100644 --- a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py +++ b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py @@ -3,7 +3,6 @@ import datetime from collections import OrderedDict -from typing import Union import frappe from frappe import _ @@ -15,7 +14,7 @@ Row = frappe._dict Data = list[Row] Columns = list[dict[str, str]] -DateTime = Union[datetime.date, datetime.datetime] +DateTime = datetime.date | datetime.datetime FilteredEntries = list[dict[str, str | float | DateTime | None]] ItemGroupsDict = dict[tuple[int, int], dict[str, str | int]] SVDList = list[frappe._dict] From 2425119b5e450fa06e7cba61f5d98c52d7c5a3ec Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 27 Mar 2024 21:49:44 +0530 Subject: [PATCH 51/72] fix: exclude some query builder lines from ruff rules `== None` and `== True` are intentional here (cherry picked from commit ac69513f6099ea302370c6c09e3b46b477606d72) (cherry picked from commit 41d7c03cbb86baade0d0db0a13a27832c8299da8) Signed-off-by: Akhil Narang --- erpnext/patches/v14_0/update_flag_for_return_invoices.py | 4 ++-- .../customer_wise_item_price/customer_wise_item_price.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/patches/v14_0/update_flag_for_return_invoices.py b/erpnext/patches/v14_0/update_flag_for_return_invoices.py index ca1b2967c535..e8b54d6afefd 100644 --- a/erpnext/patches/v14_0/update_flag_for_return_invoices.py +++ b/erpnext/patches/v14_0/update_flag_for_return_invoices.py @@ -22,7 +22,7 @@ def execute(): .where( (si.creation.gte(creation_date)) & (si.docstatus == 1) - & (si.is_return is True) + & (si.is_return == True) # noqa: E712 & (si.return_against.notnull()) ) .run() @@ -51,7 +51,7 @@ def execute(): .where( (pi.creation.gte(creation_date)) & (pi.docstatus == 1) - & (pi.is_return is True) + & (pi.is_return == True) # noqa: E712 & (pi.return_against.notnull()) ) .run() diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py index 6acc060031a3..3922beae1d2b 100644 --- a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py @@ -62,10 +62,10 @@ def fetch_item_prices( or_conditions = [] if items: and_conditions.append(ip.item_code.isin([x.item_code for x in items])) - and_conditions.append(ip.selling is True) + and_conditions.append(ip.selling == True) # noqa: E712 - or_conditions.append(ip.customer is None) - or_conditions.append(ip.price_list is None) + or_conditions.append(ip.customer == None) # noqa: E711 + or_conditions.append(ip.price_list == None) # noqa: E711 if customer: or_conditions.append(ip.customer == customer) From b4ed2d2c16d64d8fd06ec9c273f25c97f032d124 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 28 Mar 2024 09:17:36 +0530 Subject: [PATCH 52/72] fix: use 'eq' and isnull() on qb conditions (cherry picked from commit eee86d2e4b74a4af7bbd150b2adee61a26ff7969) (cherry picked from commit 22689958da2dfd96d19271989afdd54ad57a5990) Signed-off-by: Akhil Narang --- erpnext/patches/v14_0/update_flag_for_return_invoices.py | 4 ++-- .../customer_wise_item_price/customer_wise_item_price.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/patches/v14_0/update_flag_for_return_invoices.py b/erpnext/patches/v14_0/update_flag_for_return_invoices.py index e8b54d6afefd..2136d55a7869 100644 --- a/erpnext/patches/v14_0/update_flag_for_return_invoices.py +++ b/erpnext/patches/v14_0/update_flag_for_return_invoices.py @@ -22,7 +22,7 @@ def execute(): .where( (si.creation.gte(creation_date)) & (si.docstatus == 1) - & (si.is_return == True) # noqa: E712 + & (si.is_return.eq(True)) & (si.return_against.notnull()) ) .run() @@ -51,7 +51,7 @@ def execute(): .where( (pi.creation.gte(creation_date)) & (pi.docstatus == 1) - & (pi.is_return == True) # noqa: E712 + & (pi.is_return.eq(True)) & (pi.return_against.notnull()) ) .run() diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py index 3922beae1d2b..84da765d9308 100644 --- a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py @@ -62,10 +62,10 @@ def fetch_item_prices( or_conditions = [] if items: and_conditions.append(ip.item_code.isin([x.item_code for x in items])) - and_conditions.append(ip.selling == True) # noqa: E712 + and_conditions.append(ip.selling.eq(True)) - or_conditions.append(ip.customer == None) # noqa: E711 - or_conditions.append(ip.price_list == None) # noqa: E711 + or_conditions.append(ip.customer.isnull()) + or_conditions.append(ip.price_list.isnull()) if customer: or_conditions.append(ip.customer == customer) From cc6bacb1902b1a9b603ba91ebfb2309386c9d7b1 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 10 Apr 2024 14:22:01 +0000 Subject: [PATCH 53/72] chore(release): Bumped to Version 14.67.0 # [14.67.0](https://github.com/frappe/erpnext/compare/v14.66.4...v14.67.0) (2024-04-10) ### Bug Fixes * Get pro-rata depr amount based on correct days ([10d7600](https://github.com/frappe/erpnext/commit/10d760089e3ad44859c89dac2250c296c68dc764)) * group warehouse added in the stock reconciliation ([9dea6d3](https://github.com/frappe/erpnext/commit/9dea6d3393c6f02feed666e05d3ae792bee2afc1)) * ignore dimension validation for cancelled entries ([9745724](https://github.com/frappe/erpnext/commit/9745724d413d65ff533654a4a2a66d8ddae892a9)) * incorrect currency symbol in General Ledger print ([5896e75](https://github.com/frappe/erpnext/commit/5896e755bf3cf9e5b4385699b6ddfc7cef852b4f)) * incorrect operator causing incorrect validation ([7e1ab75](https://github.com/frappe/erpnext/commit/7e1ab75b382d18d8453d59c496f20641567851de)) * query_report.trigger_refresh is not a function ([a6145fa](https://github.com/frappe/erpnext/commit/a6145fa13c7dc6d5334cef7aeb9d712c2c9f4c27)) * translatable web footer ([#40834](https://github.com/frappe/erpnext/issues/40834)) ([b55d859](https://github.com/frappe/erpnext/commit/b55d8597e8dffee0412c3806f76b99ac1920e35c)) * use reference type name to update exc rate ([09cda60](https://github.com/frappe/erpnext/commit/09cda60bdf11444bb05d6ec8968deffee59559f7)) ### Features * ledger health doctype ([b667a02](https://github.com/frappe/erpnext/commit/b667a024709ce70851eaf308ff48e6550e9c07af)) * new hook `fields_for_group_similar_items` to group additional fields for print formats ([#40831](https://github.com/frappe/erpnext/issues/40831)) ([0172880](https://github.com/frappe/erpnext/commit/0172880fd3a20a4a6a07685c208bbb5d1df7afd9)) ### Performance Improvements * memory consumption for the Batch-Wise Balance History report ([3165682](https://github.com/frappe/erpnext/commit/3165682d7a6efb73b1123998417ef0356c276bd2)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 09803b970198..4901e2651479 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import frappe -__version__ = "14.66.4" +__version__ = "14.67.0" def get_default_company(user=None): From 59cea9f4ddac122c2b8b109b5e2d75f8ff75c23b Mon Sep 17 00:00:00 2001 From: Corentin Flr <10946971+cogk@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:59:58 +0200 Subject: [PATCH 54/72] fix: Don't call get_fiscal_year if setup is not done yet (cherry picked from commit c203fafb1b6db875ce31d7ed19c4e4a61fcbe312) # Conflicts: # erpnext/public/js/utils.js --- erpnext/public/js/utils.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 716b655d7395..faa153c34b1d 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -397,7 +397,43 @@ $.extend(erpnext.utils, { } }, +<<<<<<< HEAD get_fiscal_year: function (date) { +======= + pick_serial_and_batch_bundle(frm, cdt, cdn, type_of_transaction, warehouse_field) { + let item_row = frappe.get_doc(cdt, cdn); + item_row.type_of_transaction = type_of_transaction; + + frappe.db.get_value("Item", item_row.item_code, ["has_batch_no", "has_serial_no"]).then((r) => { + item_row.has_batch_no = r.message.has_batch_no; + item_row.has_serial_no = r.message.has_serial_no; + + new erpnext.SerialBatchPackageSelector(frm, item_row, (r) => { + if (r) { + let update_values = { + serial_and_batch_bundle: r.name, + qty: Math.abs(r.total_qty), + }; + + if (!warehouse_field) { + warehouse_field = "warehouse"; + } + + if (r.warehouse) { + update_values[warehouse_field] = r.warehouse; + } + + frappe.model.set_value(item_row.doctype, item_row.name, update_values); + } + }); + }); + }, + + get_fiscal_year: function (date, with_dates = false, boolean = false) { + if (!frappe.boot.setup_complete) { + return; + } +>>>>>>> c203fafb1b (fix: Don't call get_fiscal_year if setup is not done yet) if (!date) { date = frappe.datetime.get_today(); } From cf3c26d80c24736886c57416839566062d0ebfd6 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 10 Apr 2024 16:10:53 +0530 Subject: [PATCH 55/72] chore: gitignore ruff format Signed-off-by: Akhil Narang --- .git-blame-ignore-revs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 3bc22af96ab5..a770019bf701 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -28,4 +28,7 @@ b147b85e6ac19a9220cd1e2958a6ebd99373283a 494bd9ef78313436f0424b918f200dab8fc7c20b # bulk format python code with black -baec607ff5905b1c67531096a9cf50ec7ff00a5d \ No newline at end of file +baec607ff5905b1c67531096a9cf50ec7ff00a5d + +# ruff +4d34b1ead73baf4c5430a2ecbe44b9e8468d7626 From cc925ae938a201beff8413f21646fa17522db8f6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 12 Apr 2024 12:10:55 +0530 Subject: [PATCH 56/72] fix: Resolve merge conflicts --- erpnext/public/js/utils.js | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index faa153c34b1d..a52a9dbeac28 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -397,43 +397,10 @@ $.extend(erpnext.utils, { } }, -<<<<<<< HEAD - get_fiscal_year: function (date) { -======= - pick_serial_and_batch_bundle(frm, cdt, cdn, type_of_transaction, warehouse_field) { - let item_row = frappe.get_doc(cdt, cdn); - item_row.type_of_transaction = type_of_transaction; - - frappe.db.get_value("Item", item_row.item_code, ["has_batch_no", "has_serial_no"]).then((r) => { - item_row.has_batch_no = r.message.has_batch_no; - item_row.has_serial_no = r.message.has_serial_no; - - new erpnext.SerialBatchPackageSelector(frm, item_row, (r) => { - if (r) { - let update_values = { - serial_and_batch_bundle: r.name, - qty: Math.abs(r.total_qty), - }; - - if (!warehouse_field) { - warehouse_field = "warehouse"; - } - - if (r.warehouse) { - update_values[warehouse_field] = r.warehouse; - } - - frappe.model.set_value(item_row.doctype, item_row.name, update_values); - } - }); - }); - }, - get_fiscal_year: function (date, with_dates = false, boolean = false) { if (!frappe.boot.setup_complete) { return; } ->>>>>>> c203fafb1b (fix: Don't call get_fiscal_year if setup is not done yet) if (!date) { date = frappe.datetime.get_today(); } From c2c4548cc0013dd058e564157c767e9b18f66582 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 14:50:12 +0530 Subject: [PATCH 57/72] fix: Subcontracting Receipt GL Entries (backport #40773) (#40978) * fix: Subcontracting Receipt GL Entries (cherry picked from commit 9808ae92a44328f357c224e2f61c89e79c9255f7) * chore: linter --------- Co-authored-by: s-aga-r --- .../subcontracting_receipt.py | 91 +++++++++++++------ .../test_subcontracting_receipt.py | 67 ++++++++++---- 2 files changed, 114 insertions(+), 44 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 7e3863766244..c0235f9b85c5 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -311,8 +311,6 @@ def get_gl_entries(self, warehouse_account=None): return process_gl_map(gl_entries) def make_item_gl_entries(self, gl_entries, warehouse_account=None): - stock_rbnb = self.get_company_default("stock_received_but_not_billed") - warehouse_with_no_account = [] for item in self.items: @@ -330,31 +328,41 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): "stock_value_difference", ) - warehouse_account_name = warehouse_account[item.warehouse]["account"] - warehouse_account_currency = warehouse_account[item.warehouse]["account_currency"] + accepted_warehouse_account = warehouse_account[item.warehouse]["account"] supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get( "account" ) - supplier_warehouse_account_currency = warehouse_account.get( - self.supplier_warehouse, {} - ).get("account_currency") remarks = self.get("remarks") or _("Accounting Entry for Stock") - # FG Warehouse Account (Debit) + # Accepted Warehouse Account (Debit) self.add_gl_entry( gl_entries=gl_entries, - account=warehouse_account_name, + account=accepted_warehouse_account, cost_center=item.cost_center, debit=stock_value_diff, credit=0.0, remarks=remarks, - against_account=stock_rbnb, - account_currency=warehouse_account_currency, + against_account=item.expense_account, + account_currency=get_account_currency(accepted_warehouse_account), + project=item.project, + item=item, + ) + # Expense Account (Credit) + self.add_gl_entry( + gl_entries=gl_entries, + account=item.expense_account, + cost_center=item.cost_center, + debit=0.0, + credit=stock_value_diff, + remarks=remarks, + against_account=accepted_warehouse_account, + account_currency=get_account_currency(item.expense_account), + project=item.project, item=item, ) - # Supplier Warehouse Account (Credit) - if flt(item.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): + if flt(item.rm_supp_cost) and supplier_warehouse_account: + # Supplier Warehouse Account (Credit) self.add_gl_entry( gl_entries=gl_entries, account=supplier_warehouse_account, @@ -362,40 +370,66 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): debit=0.0, credit=flt(item.rm_supp_cost), remarks=remarks, - against_account=warehouse_account_name, - account_currency=supplier_warehouse_account_currency, + against_account=item.expense_account, + account_currency=get_account_currency(supplier_warehouse_account), + project=item.project, item=item, ) - - # Expense Account (Credit) - if flt(item.service_cost_per_qty): + # Expense Account (Debit) self.add_gl_entry( gl_entries=gl_entries, account=item.expense_account, cost_center=item.cost_center, - debit=0.0, - credit=flt(item.service_cost_per_qty) * flt(item.qty), + debit=flt(item.rm_supp_cost), + credit=0.0, remarks=remarks, - against_account=warehouse_account_name, + against_account=supplier_warehouse_account, account_currency=get_account_currency(item.expense_account), + project=item.project, item=item, ) - # Loss Account (Credit) - divisional_loss = flt(item.amount - stock_value_diff, item.precision("amount")) + # Expense Account (Debit) + if item.additional_cost_per_qty: + self.add_gl_entry( + gl_entries=gl_entries, + account=item.expense_account, + cost_center=self.cost_center or self.get_company_default("cost_center"), + debit=item.qty * item.additional_cost_per_qty, + credit=0.0, + remarks=remarks, + against_account=None, + account_currency=get_account_currency(item.expense_account), + ) - if divisional_loss: - loss_account = item.expense_account + if divisional_loss := flt(item.amount - stock_value_diff, item.precision("amount")): + loss_account = self.get_company_default( + "stock_adjustment_account", ignore_validation=True + ) + # Loss Account (Credit) self.add_gl_entry( gl_entries=gl_entries, account=loss_account, cost_center=item.cost_center, + debit=0.0, + credit=divisional_loss, + remarks=remarks, + against_account=item.expense_account, + account_currency=get_account_currency(loss_account), + project=item.project, + item=item, + ) + # Expense Account (Debit) + self.add_gl_entry( + gl_entries=gl_entries, + account=item.expense_account, + cost_center=item.cost_center, debit=divisional_loss, credit=0.0, remarks=remarks, - against_account=warehouse_account_name, - account_currency=get_account_currency(loss_account), + against_account=loss_account, + account_currency=get_account_currency(item.expense_account), project=item.project, item=item, ) @@ -405,7 +439,6 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): ): warehouse_with_no_account.append(item.warehouse) - # Additional Costs Expense Accounts (Credit) for row in self.additional_costs: credit_amount = ( flt(row.base_amount) @@ -413,6 +446,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): else flt(row.amount) ) + # Additional Cost Expense Account (Credit) self.add_gl_entry( gl_entries=gl_entries, account=row.expense_account, @@ -421,6 +455,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): credit=credit_amount, remarks=remarks, against_account=None, + account_currency=get_account_currency(row.expense_account), ) if warehouse_with_no_account: diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index b2b0f0e98432..1b1d823a9208 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -434,26 +434,15 @@ def test_subcontracting_receipt_gl_entry(self): self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(scr.company)), 1) gl_entries = get_gl_entries("Subcontracting Receipt", scr.name) - self.assertTrue(gl_entries) fg_warehouse_ac = get_inventory_account(scr.company, scr.items[0].warehouse) - supplier_warehouse_ac = get_inventory_account(scr.company, scr.supplier_warehouse) expense_account = scr.items[0].expense_account - - if fg_warehouse_ac == supplier_warehouse_ac: - expected_values = { - fg_warehouse_ac: [2100.0, 1000.0], # FG Amount (D), RM Cost (C) - expense_account: [0.0, 1000.0], # Service Cost (C) - additional_costs_expense_account: [0.0, 100.0], # Additional Cost (C) - } - else: - expected_values = { - fg_warehouse_ac: [2100.0, 0.0], # FG Amount (D) - supplier_warehouse_ac: [0.0, 1000.0], # RM Cost (C) - expense_account: [0.0, 1000.0], # Service Cost (C) - additional_costs_expense_account: [0.0, 100.0], # Additional Cost (C) - } + expected_values = { + fg_warehouse_ac: [2100.0, 1000], + expense_account: [1100, 2100], + additional_costs_expense_account: [0.0, 100.0], + } for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit) @@ -463,6 +452,52 @@ def test_subcontracting_receipt_gl_entry(self): scr.cancel() self.assertTrue(get_gl_entries("Subcontracting Receipt", scr.name)) + def test_subcontracting_receipt_with_zero_service_cost(self): + warehouse = "Stores - TCP1" + service_items = [ + { + "warehouse": warehouse, + "item_code": "Subcontracted Service Item 7", + "qty": 10, + "rate": 0, + "fg_item": "Subcontracted Item SA7", + "fg_item_qty": 10, + }, + ] + sco = get_subcontracting_order( + company="_Test Company with perpetual inventory", + warehouse=warehouse, + supplier_warehouse="Work In Progress - TCP1", + 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() + + gl_entries = get_gl_entries("Subcontracting Receipt", scr.name) + self.assertTrue(gl_entries) + + fg_warehouse_ac = get_inventory_account(scr.company, scr.items[0].warehouse) + expense_account = scr.items[0].expense_account + expected_values = { + fg_warehouse_ac: [1000, 1000], + expense_account: [1000, 1000], + } + + for gle in gl_entries: + self.assertEqual(expected_values[gle.account][0], gle.debit) + self.assertEqual(expected_values[gle.account][1], gle.credit) + + scr.reload() + scr.cancel() + def test_supplied_items_consumed_qty(self): # Set Backflush Based On as "Material Transferred for Subcontracting" to transfer RM's more than the required qty set_backflush_based_on("Material Transferred for Subcontract") From 4672f59599bfc0d57f0d0479058b37b1a3d07d74 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:30:27 +0530 Subject: [PATCH 58/72] fix: Subcontracting Receipt GL Entries (backport #40773) (backport #40978) (#40982) * fix: Subcontracting Receipt GL Entries (backport #40773) (#40978) * fix: Subcontracting Receipt GL Entries (cherry picked from commit 9808ae92a44328f357c224e2f61c89e79c9255f7) * chore: linter --------- Co-authored-by: s-aga-r (cherry picked from commit c2c4548cc0013dd058e564157c767e9b18f66582) # Conflicts: # erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py * chore: `conflicts` --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: s-aga-r --- .../subcontracting_receipt.py | 89 +++++++++++++------ .../test_subcontracting_receipt.py | 67 ++++++++++---- 2 files changed, 112 insertions(+), 44 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 3e5e2b42c046..84a90707c317 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -307,8 +307,6 @@ def get_gl_entries(self, warehouse_account=None): return process_gl_map(gl_entries) def make_item_gl_entries(self, gl_entries, warehouse_account=None): - stock_rbnb = self.get_company_default("stock_received_but_not_billed") - warehouse_with_no_account = [] for item in self.items: @@ -326,29 +324,39 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): "stock_value_difference", ) - warehouse_account_name = warehouse_account[item.warehouse]["account"] - warehouse_account_currency = warehouse_account[item.warehouse]["account_currency"] + accepted_warehouse_account = warehouse_account[item.warehouse]["account"] supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") - supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( - "account_currency" - ) remarks = self.get("remarks") or _("Accounting Entry for Stock") - # FG Warehouse Account (Debit) + # Accepted Warehouse Account (Debit) self.add_gl_entry( gl_entries=gl_entries, - account=warehouse_account_name, + account=accepted_warehouse_account, cost_center=item.cost_center, debit=stock_value_diff, credit=0.0, remarks=remarks, - against_account=stock_rbnb, - account_currency=warehouse_account_currency, + against_account=item.expense_account, + account_currency=get_account_currency(accepted_warehouse_account), + project=item.project, + item=item, + ) + # Expense Account (Credit) + self.add_gl_entry( + gl_entries=gl_entries, + account=item.expense_account, + cost_center=item.cost_center, + debit=0.0, + credit=stock_value_diff, + remarks=remarks, + against_account=accepted_warehouse_account, + account_currency=get_account_currency(item.expense_account), + project=item.project, item=item, ) - # Supplier Warehouse Account (Credit) - if flt(item.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): + if flt(item.rm_supp_cost) and supplier_warehouse_account: + # Supplier Warehouse Account (Credit) self.add_gl_entry( gl_entries=gl_entries, account=supplier_warehouse_account, @@ -356,40 +364,64 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): debit=0.0, credit=flt(item.rm_supp_cost), remarks=remarks, - against_account=warehouse_account_name, - account_currency=supplier_warehouse_account_currency, + against_account=item.expense_account, + account_currency=get_account_currency(supplier_warehouse_account), + project=item.project, item=item, ) - - # Expense Account (Credit) - if flt(item.service_cost_per_qty): + # Expense Account (Debit) self.add_gl_entry( gl_entries=gl_entries, account=item.expense_account, cost_center=item.cost_center, - debit=0.0, - credit=flt(item.service_cost_per_qty) * flt(item.qty), + debit=flt(item.rm_supp_cost), + credit=0.0, remarks=remarks, - against_account=warehouse_account_name, + against_account=supplier_warehouse_account, account_currency=get_account_currency(item.expense_account), + project=item.project, item=item, ) - # Loss Account (Credit) - divisional_loss = flt(item.amount - stock_value_diff, item.precision("amount")) + # Expense Account (Debit) + if item.additional_cost_per_qty: + self.add_gl_entry( + gl_entries=gl_entries, + account=item.expense_account, + cost_center=self.cost_center or self.get_company_default("cost_center"), + debit=item.qty * item.additional_cost_per_qty, + credit=0.0, + remarks=remarks, + against_account=None, + account_currency=get_account_currency(item.expense_account), + ) - if divisional_loss: - loss_account = item.expense_account + if divisional_loss := flt(item.amount - stock_value_diff, item.precision("amount")): + loss_account = self.get_company_default("stock_adjustment_account", ignore_validation=True) + # Loss Account (Credit) self.add_gl_entry( gl_entries=gl_entries, account=loss_account, cost_center=item.cost_center, + debit=0.0, + credit=divisional_loss, + remarks=remarks, + against_account=item.expense_account, + account_currency=get_account_currency(loss_account), + project=item.project, + item=item, + ) + # Expense Account (Debit) + self.add_gl_entry( + gl_entries=gl_entries, + account=item.expense_account, + cost_center=item.cost_center, debit=divisional_loss, credit=0.0, remarks=remarks, - against_account=warehouse_account_name, - account_currency=get_account_currency(loss_account), + against_account=loss_account, + account_currency=get_account_currency(item.expense_account), project=item.project, item=item, ) @@ -399,7 +431,6 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): ): warehouse_with_no_account.append(item.warehouse) - # Additional Costs Expense Accounts (Credit) for row in self.additional_costs: credit_amount = ( flt(row.base_amount) @@ -407,6 +438,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): else flt(row.amount) ) + # Additional Cost Expense Account (Credit) self.add_gl_entry( gl_entries=gl_entries, account=row.expense_account, @@ -415,6 +447,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): credit=credit_amount, remarks=remarks, against_account=None, + account_currency=get_account_currency(row.expense_account), ) if warehouse_with_no_account: diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index b05ed755c7f9..a4986989aac7 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -442,26 +442,15 @@ def test_subcontracting_receipt_gl_entry(self): self.assertEqual(cint(erpnext.is_perpetual_inventory_enabled(scr.company)), 1) gl_entries = get_gl_entries("Subcontracting Receipt", scr.name) - self.assertTrue(gl_entries) fg_warehouse_ac = get_inventory_account(scr.company, scr.items[0].warehouse) - supplier_warehouse_ac = get_inventory_account(scr.company, scr.supplier_warehouse) expense_account = scr.items[0].expense_account - - if fg_warehouse_ac == supplier_warehouse_ac: - expected_values = { - fg_warehouse_ac: [2100.0, 1000.0], # FG Amount (D), RM Cost (C) - expense_account: [0.0, 1000.0], # Service Cost (C) - additional_costs_expense_account: [0.0, 100.0], # Additional Cost (C) - } - else: - expected_values = { - fg_warehouse_ac: [2100.0, 0.0], # FG Amount (D) - supplier_warehouse_ac: [0.0, 1000.0], # RM Cost (C) - expense_account: [0.0, 1000.0], # Service Cost (C) - additional_costs_expense_account: [0.0, 100.0], # Additional Cost (C) - } + expected_values = { + fg_warehouse_ac: [2100.0, 1000], + expense_account: [1100, 2100], + additional_costs_expense_account: [0.0, 100.0], + } for gle in gl_entries: self.assertEqual(expected_values[gle.account][0], gle.debit) @@ -471,6 +460,52 @@ def test_subcontracting_receipt_gl_entry(self): scr.cancel() self.assertTrue(get_gl_entries("Subcontracting Receipt", scr.name)) + def test_subcontracting_receipt_with_zero_service_cost(self): + warehouse = "Stores - TCP1" + service_items = [ + { + "warehouse": warehouse, + "item_code": "Subcontracted Service Item 7", + "qty": 10, + "rate": 0, + "fg_item": "Subcontracted Item SA7", + "fg_item_qty": 10, + }, + ] + sco = get_subcontracting_order( + company="_Test Company with perpetual inventory", + warehouse=warehouse, + supplier_warehouse="Work In Progress - TCP1", + 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() + + gl_entries = get_gl_entries("Subcontracting Receipt", scr.name) + self.assertTrue(gl_entries) + + fg_warehouse_ac = get_inventory_account(scr.company, scr.items[0].warehouse) + expense_account = scr.items[0].expense_account + expected_values = { + fg_warehouse_ac: [1000, 1000], + expense_account: [1000, 1000], + } + + for gle in gl_entries: + self.assertEqual(expected_values[gle.account][0], gle.debit) + self.assertEqual(expected_values[gle.account][1], gle.credit) + + scr.reload() + scr.cancel() + def test_supplied_items_consumed_qty(self): # Set Backflush Based On as "Material Transferred for Subcontracting" to transfer RM's more than the required qty set_backflush_based_on("Material Transferred for Subcontract") From 7a6c0e52836d228a98cfbcdeac861568a19c6f36 Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Fri, 12 Apr 2024 10:01:51 +0000 Subject: [PATCH 59/72] chore(release): Bumped to Version 14.67.1 ## [14.67.1](https://github.com/frappe/erpnext/compare/v14.67.0...v14.67.1) (2024-04-12) ### Bug Fixes * Subcontracting Receipt GL Entries (backport [#40773](https://github.com/frappe/erpnext/issues/40773)) (backport [#40978](https://github.com/frappe/erpnext/issues/40978)) ([#40982](https://github.com/frappe/erpnext/issues/40982)) ([4672f59](https://github.com/frappe/erpnext/commit/4672f59599bfc0d57f0d0479058b37b1a3d07d74)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 4901e2651479..f06f45bf862e 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import frappe -__version__ = "14.67.0" +__version__ = "14.67.1" def get_default_company(user=None): From b47e224a1cc0bd8d9c985284150ef66eebe1b35a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 4 Apr 2024 15:25:46 +0530 Subject: [PATCH 60/72] fix: Don't set delivery date as today while making SO from Quotation (cherry picked from commit fec20decc109ff1965fa2afe592f57113482cd73) --- erpnext/selling/doctype/quotation/quotation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 70d0c1a25fe6..bd23440aaf0a 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -302,7 +302,6 @@ def set_missing_values(source, target): ) target.flags.ignore_permissions = ignore_permissions - target.delivery_date = nowdate() target.run_method("set_missing_values") target.run_method("calculate_taxes_and_totals") From 79e23dad2c61aafb0145048a49a2d79abf811cb0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 11 Apr 2024 11:01:28 +0530 Subject: [PATCH 61/72] fix: test cases (cherry picked from commit 65c74fa3c7197f0e751ba62abe1f63c8e7735147) --- erpnext/selling/doctype/quotation/test_quotation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index e840ac202682..4219d0698cad 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -122,6 +122,7 @@ def test_make_sales_order(self): sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = nowdate() + sales_order.delivery_date = nowdate() sales_order.insert() def test_make_sales_order_with_terms(self): @@ -152,6 +153,7 @@ def test_make_sales_order_with_terms(self): sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = nowdate() + sales_order.delivery_date = nowdate() sales_order.insert() # Remove any unknown taxes if applied From 50a74ee7fe95f1b58bdf8ef935eae5ba0bc04ffc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 16 Apr 2024 08:53:29 +0530 Subject: [PATCH 62/72] fix: incorrect exc gain/loss for PE against JE for payable accounts (cherry picked from commit 81b574053ffc15c4337fbe497c53d8696d26f878) # Conflicts: # erpnext/controllers/accounts_controller.py --- erpnext/controllers/accounts_controller.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index dd4a247e0a11..29ac86cb941d 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1293,7 +1293,8 @@ def make_exchange_gain_loss_journal( dr_or_cr = "debit" if d.exchange_gain_loss > 0 else "credit" - if d.reference_doctype == "Purchase Invoice": + # Inverse debit/credit for payable accounts + if self.is_payable_account(d.reference_doctype, party_account): dr_or_cr = "debit" if dr_or_cr == "credit" else "credit" reverse_dr_or_cr = "debit" if dr_or_cr == "credit" else "credit" @@ -1327,6 +1328,7 @@ def make_exchange_gain_loss_journal( ) ) +<<<<<<< HEAD def make_precision_loss_gl_entry(self, gl_entries): round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center @@ -1353,6 +1355,15 @@ def make_precision_loss_gl_entry(self, gl_entries): } ) ) +======= + def is_payable_account(self, reference_doctype, account): + if reference_doctype == "Purchase Invoice" or ( + reference_doctype == "Journal Entry" + and frappe.get_cached_value("Account", account, "account_type") == "Payable" + ): + return True + return False +>>>>>>> 81b574053f (fix: incorrect exc gain/loss for PE against JE for payable accounts) def update_against_document_in_jv(self): """ From 2ebdd93a834ba84bd0ea861806cbc9d1ded60e4b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 16 Apr 2024 10:17:41 +0530 Subject: [PATCH 63/72] test: exc gain/loss journals booking in Payable accounts (cherry picked from commit 8821c98625f21fe2ec3434462c031f8bd27afde7) --- .../tests/test_accounts_controller.py | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 92bbc0577333..4ada8e60d9b5 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -135,6 +135,27 @@ def create_account(self): acc = frappe.get_doc("Account", name) self.debtors_usd = acc.name + account_name = "Creditors USD" + if not frappe.db.get_value( + "Account", filters={"account_name": account_name, "company": self.company} + ): + acc = frappe.new_doc("Account") + acc.account_name = account_name + acc.parent_account = "Accounts Payable - " + self.company_abbr + acc.company = self.company + acc.account_currency = "USD" + acc.account_type = "Payable" + acc.insert() + else: + name = frappe.db.get_value( + "Account", + filters={"account_name": account_name, "company": self.company}, + fieldname="name", + pluck=True, + ) + acc = frappe.get_doc("Account", name) + self.creditors_usd = acc.name + def create_sales_invoice( self, qty=1, @@ -174,7 +195,9 @@ def create_sales_invoice( ) return sinv - def create_payment_entry(self, amount=1, source_exc_rate=75, posting_date=None, customer=None): + def create_payment_entry( + self, amount=1, source_exc_rate=75, posting_date=None, customer=None, submit=True + ): """ Helper function to populate default values in payment entry """ @@ -1645,3 +1668,72 @@ def test_60_payment_entry_against_journal(self): exc_je_for_je2 = self.get_journals_for(je2.doctype, je2.name) self.assertEqual(exc_je_for_je1, []) self.assertEqual(exc_je_for_je2, []) + + def test_61_payment_entry_against_journal_for_payable_accounts(self): + # Invoices + exc_rate1 = 75 + exc_rate2 = 77 + amount = 1 + je1 = self.create_journal_entry( + acc1=self.creditors_usd, + acc1_exc_rate=exc_rate1, + acc2=self.cash, + acc1_amount=-amount, + acc2_amount=(-amount * 75), + acc2_exc_rate=1, + ) + je1.accounts[0].party_type = "Supplier" + je1.accounts[0].party = self.supplier + je1 = je1.save().submit() + + # Payment + pe = create_payment_entry( + company=self.company, + payment_type="Pay", + party_type="Supplier", + party=self.supplier, + paid_from=self.cash, + paid_to=self.creditors_usd, + paid_amount=amount, + ) + pe.target_exchange_rate = exc_rate2 + pe.received_amount = amount + pe.paid_amount = amount * exc_rate2 + pe.save().submit() + + pr = frappe.get_doc( + { + "doctype": "Payment Reconciliation", + "company": self.company, + "party_type": "Supplier", + "party": self.supplier, + "receivable_payable_account": get_party_account("Supplier", self.supplier, self.company), + } + ) + pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate() + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + invoices = [x.as_dict() for x in pr.invoices] + payments = [x.as_dict() for x in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + self.assertEqual(len(pr.invoices), 0) + self.assertEqual(len(pr.payments), 0) + + # There should be no outstanding in both currencies + self.assert_ledger_outstanding(je1.doctype, je1.name, 0.0, 0.0) + + # Exchange Gain/Loss Journal should've been created + exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name) + self.assertEqual(len(exc_je_for_je1), 1) + + # Cancel Payment + pe.reload() + pe.cancel() + + self.assert_ledger_outstanding(je1.doctype, je1.name, (amount * exc_rate1), amount) + + # Exchange Gain/Loss Journal should've been cancelled + exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name) + self.assertEqual(exc_je_for_je1, []) From e8d05517c57bcb0ef8cd61d9ba03b5f9fba2aff7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 16 Apr 2024 11:07:39 +0530 Subject: [PATCH 64/72] chore: resolve conflict --- erpnext/controllers/accounts_controller.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 29ac86cb941d..86e4cf684a33 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1328,7 +1328,14 @@ def make_exchange_gain_loss_journal( ) ) -<<<<<<< HEAD + def is_payable_account(self, reference_doctype, account): + if reference_doctype == "Purchase Invoice" or ( + reference_doctype == "Journal Entry" + and frappe.get_cached_value("Account", account, "account_type") == "Payable" + ): + return True + return False + def make_precision_loss_gl_entry(self, gl_entries): round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center @@ -1355,15 +1362,6 @@ def make_precision_loss_gl_entry(self, gl_entries): } ) ) -======= - def is_payable_account(self, reference_doctype, account): - if reference_doctype == "Purchase Invoice" or ( - reference_doctype == "Journal Entry" - and frappe.get_cached_value("Account", account, "account_type") == "Payable" - ): - return True - return False ->>>>>>> 81b574053f (fix: incorrect exc gain/loss for PE against JE for payable accounts) def update_against_document_in_jv(self): """ From 0bee921d402060abe6c06568dd3f600d1445719f Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 14:22:32 +0530 Subject: [PATCH 65/72] fix: barcode not fetched on selection of item (backport #40814) (#41027) * fix: barcode not fetched on selection of item (cherry picked from commit b0730293e2b9aa89ed5904256d7846cef45cb4fe) # Conflicts: # erpnext/stock/get_item_details.py * chore: fix conflicts * chore: fix test case --------- Co-authored-by: Rohit Waghchaure --- erpnext/stock/doctype/item/test_item.py | 10 +++++++++- .../stock/doctype/stock_entry/stock_entry.py | 14 +++++++++++++- .../doctype/stock_entry/test_stock_entry.py | 6 ++++++ .../stock_reconciliation.js | 19 +++++++++++++++++++ erpnext/stock/get_item_details.py | 11 ++++++++++- 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index d109cf2f01c7..d486e972771d 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -32,7 +32,7 @@ test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand", "Item Attribute"] -def make_item(item_code=None, properties=None, uoms=None): +def make_item(item_code=None, properties=None, uoms=None, barcode=None): if not item_code: item_code = frappe.generate_hash(length=16) @@ -61,6 +61,14 @@ def make_item(item_code=None, properties=None, uoms=None): for uom in uoms: item.append("uoms", uom) + if barcode: + item.append( + "barcodes", + { + "barcode": barcode, + }, + ) + item.insert() return item diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 2e1ec6869145..c27cda7035a5 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -32,6 +32,7 @@ OpeningEntryAccountError, ) from erpnext.stock.get_item_details import ( + get_barcode_data, get_bin_details, get_conversion_factor, get_default_cost_center, @@ -354,7 +355,14 @@ def validate_item(self): for field in reset_fields: item.set(field, item_details.get(field)) - update_fields = ("uom", "description", "expense_account", "cost_center", "conversion_factor") + update_fields = ( + "uom", + "description", + "expense_account", + "cost_center", + "conversion_factor", + "barcode", + ) for field in update_fields: if not item.get(field): @@ -1439,6 +1447,10 @@ def get_item_details(self, args=None, for_update=False): if subcontract_items and len(subcontract_items) == 1: ret["subcontracted_item"] = subcontract_items[0].main_item_code + barcode_data = get_barcode_data(item_code=item.name) + if barcode_data and len(barcode_data.get(item.name)) == 1: + ret["barcode"] = barcode_data.get(item.name)[0] + return ret @frappe.whitelist() diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 571ad4bea1d1..085f6b36f29b 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -95,6 +95,12 @@ def test_auto_material_request(self): self._test_auto_material_request("_Test Item") self._test_auto_material_request("_Test Item", material_request_type="Transfer") + def test_barcode_item_stock_entry(self): + item_code = make_item("_Test Item Stock Entry For Barcode", barcode="BDD-1234567890") + + se = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=1, basic_rate=100) + self.assertEqual(se.items[0].barcode, "BDD-1234567890") + def test_auto_material_request_for_variant(self): fields = [{"field_name": "reorder_levels"}] set_item_variant_settings(fields) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js index 0abc52644490..6ba2f0ac051c 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js @@ -53,6 +53,18 @@ frappe.ui.form.on("Stock Reconciliation", { if (frm.doc.company) { frm.trigger("toggle_display_account_head"); } + + frm.events.set_fields_onload_for_line_item(frm); + }, + + set_fields_onload_for_line_item(frm) { + if (frm.is_new() && frm.doc?.items && cint(frappe.user_defaults?.use_serial_batch_fields) === 1) { + frm.doc.items.forEach((item) => { + if (!item.serial_and_batch_bundle) { + frappe.model.set_value(item.doctype, item.name, "use_serial_batch_fields", 1); + } + }); + } }, scan_barcode: function (frm) { @@ -127,6 +139,9 @@ frappe.ui.form.on("Stock Reconciliation", { item.qty = item.qty || 0; item.valuation_rate = item.valuation_rate || 0; + item.use_serial_batch_fields = cint( + frappe.user_defaults?.use_serial_batch_fields + ); }); frm.refresh_field("items"); }, @@ -267,6 +282,10 @@ frappe.ui.form.on("Stock Reconciliation Item", { if (!item.warehouse && frm.doc.set_warehouse) { frappe.model.set_value(cdt, cdn, "warehouse", frm.doc.set_warehouse); } + + if (item.docstatus === 0 && cint(frappe.user_defaults?.use_serial_batch_fields) === 1) { + frappe.model.set_value(item.doctype, item.name, "use_serial_batch_fields", 1); + } }, }); diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index fe66f747f07c..64715d28ce8d 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -524,12 +524,21 @@ def update_barcode_value(out): out["barcode"] = barcode_data.get(out.item_code)[0] -def get_barcode_data(items_list): +def get_barcode_data(items_list=None, item_code=None): # get itemwise batch no data # exmaple: {'LED-GRE': [Batch001, Batch002]} # where LED-GRE is item code, SN0001 is serial no and Pune is warehouse itemwise_barcode = {} + if not items_list and item_code: + _dict_item_code = frappe._dict( + { + "item_code": item_code, + } + ) + + items_list = [frappe._dict(_dict_item_code)] + for item in items_list: barcodes = frappe.db.get_all("Item Barcode", filters={"parent": item.item_code}, fields="barcode") From 153e0ba81b62acc170a951a289363fff5579edc7 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 14:22:53 +0530 Subject: [PATCH 66/72] fix: expense account set as COGS for stock entry Material Issue (backport #41026) (#41028) fix: expense account set as COGS for stock entry Material Issue (#41026) (cherry picked from commit 03231e99ef638c2938eb570eb184bb8a8f1dcdca) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/stock_entry/stock_entry.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index c27cda7035a5..2a8bb383a9c2 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1402,11 +1402,7 @@ def get_item_details(self, args=None, for_update=False): ret.update(get_uom_details(args.get("item_code"), args.get("uom"), args.get("qty"))) if self.purpose == "Material Issue": - ret["expense_account"] = ( - item.get("expense_account") - or item_group_defaults.get("expense_account") - or frappe.get_cached_value("Company", self.company, "default_expense_account") - ) + ret["expense_account"] = item.get("expense_account") or item_group_defaults.get("expense_account") for company_field, field in { "stock_adjustment_account": "expense_account", From 04938726d9ca1803505d118c0650d3df6e9f4f84 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Mon, 11 Mar 2024 16:34:44 +0530 Subject: [PATCH 67/72] fix: get address if multiple companies (cherry picked from commit c6cf1bec76581bbe653b191e983de1692254ef48) # Conflicts: # erpnext/selling/doctype/sales_order/sales_order.js --- .../doctype/sales_order/sales_order.js | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index e9a6cc385d3c..749b12f96b35 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -89,9 +89,36 @@ frappe.ui.form.on("Sales Order", { }, __('Get Items From')); }, +<<<<<<< HEAD onload: function(frm) { if (!frm.doc.transaction_date){ frm.set_value('transaction_date', frappe.datetime.get_today()) +======= + // When multiple companies are set up. in case company name is changed set default company address + company: function (frm) { + if (frm.doc.company) { + frappe.call({ + method: "erpnext.setup.doctype.company.company.get_default_company_address", + args: { + name: frm.doc.company, + existing_address: frm.doc.company_address || "" + }, + debounce: 2000, + callback: function (r) { + if (r.message) { + frm.set_value("company_address", r.message); + } else { + frm.set_value("company_address", ""); + } + }, + }); + } + }, + + onload: function (frm) { + if (!frm.doc.transaction_date) { + frm.set_value("transaction_date", frappe.datetime.get_today()); +>>>>>>> c6cf1bec76 (fix: get address if multiple companies) } erpnext.queries.setup_queries(frm, "Warehouse", function() { return { From c2b6b64e2ecbd236d977a617a463258bc2ad20a1 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:46:00 +0530 Subject: [PATCH 68/72] fix: get address if multiple companies (cherry picked from commit 655a1797bed38f87172aeb4589bc16c6490327a4) --- erpnext/selling/doctype/sales_order/sales_order.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 749b12f96b35..e622cd5346d0 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -101,7 +101,7 @@ frappe.ui.form.on("Sales Order", { method: "erpnext.setup.doctype.company.company.get_default_company_address", args: { name: frm.doc.company, - existing_address: frm.doc.company_address || "" + existing_address: frm.doc.company_address || "", }, debounce: 2000, callback: function (r) { From ee06448f0d7f726461f2a9a95537755a2bb0b68c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 16 Apr 2024 16:38:32 +0530 Subject: [PATCH 69/72] chore: resolve conflict --- erpnext/selling/doctype/sales_order/sales_order.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index e622cd5346d0..2995a1e99bce 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -89,11 +89,6 @@ frappe.ui.form.on("Sales Order", { }, __('Get Items From')); }, -<<<<<<< HEAD - onload: function(frm) { - if (!frm.doc.transaction_date){ - frm.set_value('transaction_date', frappe.datetime.get_today()) -======= // When multiple companies are set up. in case company name is changed set default company address company: function (frm) { if (frm.doc.company) { @@ -115,10 +110,9 @@ frappe.ui.form.on("Sales Order", { } }, - onload: function (frm) { - if (!frm.doc.transaction_date) { - frm.set_value("transaction_date", frappe.datetime.get_today()); ->>>>>>> c6cf1bec76 (fix: get address if multiple companies) + onload: function(frm) { + if (!frm.doc.transaction_date){ + frm.set_value('transaction_date', frappe.datetime.get_today()) } erpnext.queries.setup_queries(frm, "Warehouse", function() { return { From e956dbbf684c8a806942d9cf08a4ebfb65671057 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 18:24:45 +0530 Subject: [PATCH 70/72] fix: Delayed Order Report not working (backport #41037) (#41038) fix: Delayed Order Report not working (#41037) (cherry picked from commit d69a18b8262bdc77b9fc0cb7eabb6321626b1926) Co-authored-by: rohitwaghchaure --- .../stock/report/delayed_item_report/delayed_item_report.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/report/delayed_item_report/delayed_item_report.py b/erpnext/stock/report/delayed_item_report/delayed_item_report.py index 0bfb4da06a06..88a188e0cad7 100644 --- a/erpnext/stock/report/delayed_item_report/delayed_item_report.py +++ b/erpnext/stock/report/delayed_item_report/delayed_item_report.py @@ -86,7 +86,11 @@ def filter_transactions_data(self, consolidated=False): filters = {"parent": ("in", sales_orders), "name": ("in", sales_order_items)} so_data = {} - for d in frappe.get_all(doctype, filters=filters, fields=["delivery_date", "parent", "name"]): + fields = ["delivery_date", "name"] + if frappe.db.has_column(doctype, "parent"): + fields.append("parent") + + for d in frappe.get_all(doctype, filters=filters, fields=fields): key = d.name if consolidated else (d.parent, d.name) if key not in so_data: so_data.setdefault(key, d.delivery_date) From 97e7b3f3d3f1bd77e26db7dc3e02796ce683b092 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Sat, 30 Mar 2024 16:32:43 +0530 Subject: [PATCH 71/72] fix(gp): SLEs not fetched for correct warehouse (cherry picked from commit f958e8be0698723630db0c742cb6fe9428c2c8f4) --- erpnext/accounts/report/gross_profit/gross_profit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 187a154a6513..ed895749fd3c 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -656,13 +656,13 @@ def get_buying_amount(self, row, item_code): elif self.delivery_notes.get((row.parent, row.item_code), None): # check if Invoice has delivery notes dn = self.delivery_notes.get((row.parent, row.item_code)) - parenttype, parent, item_row, warehouse = ( + parenttype, parent, item_row, dn_warehouse = ( "Delivery Note", dn["delivery_note"], dn["item_row"], dn["warehouse"], ) - my_sle = self.get_stock_ledger_entries(item_code, row.warehouse) + my_sle = self.get_stock_ledger_entries(item_code, dn_warehouse) return self.calculate_buying_amount_from_sle( row, my_sle, parenttype, parent, item_row, item_code ) From 84789b7407198389d52be437c5ade3ac26c6b2aa Mon Sep 17 00:00:00 2001 From: Frappe PR Bot Date: Wed, 17 Apr 2024 06:12:30 +0000 Subject: [PATCH 72/72] chore(release): Bumped to Version 14.67.2 ## [14.67.2](https://github.com/frappe/erpnext/compare/v14.67.1...v14.67.2) (2024-04-17) ### Bug Fixes * barcode not fetched on selection of item (backport [#40814](https://github.com/frappe/erpnext/issues/40814)) ([#41027](https://github.com/frappe/erpnext/issues/41027)) ([0bee921](https://github.com/frappe/erpnext/commit/0bee921d402060abe6c06568dd3f600d1445719f)) * Delayed Order Report not working (backport [#41037](https://github.com/frappe/erpnext/issues/41037)) ([#41038](https://github.com/frappe/erpnext/issues/41038)) ([e956dbb](https://github.com/frappe/erpnext/commit/e956dbbf684c8a806942d9cf08a4ebfb65671057)) * Don't call get_fiscal_year if setup is not done yet ([59cea9f](https://github.com/frappe/erpnext/commit/59cea9f4ddac122c2b8b109b5e2d75f8ff75c23b)) * Don't set delivery date as today while making SO from Quotation ([b47e224](https://github.com/frappe/erpnext/commit/b47e224a1cc0bd8d9c985284150ef66eebe1b35a)) * exclude some query builder lines from ruff rules ([2425119](https://github.com/frappe/erpnext/commit/2425119b5e450fa06e7cba61f5d98c52d7c5a3ec)) * expense account set as COGS for stock entry Material Issue (backport [#41026](https://github.com/frappe/erpnext/issues/41026)) ([#41028](https://github.com/frappe/erpnext/issues/41028)) ([153e0ba](https://github.com/frappe/erpnext/commit/153e0ba81b62acc170a951a289363fff5579edc7)) * get address if multiple companies ([c2b6b64](https://github.com/frappe/erpnext/commit/c2b6b64e2ecbd236d977a617a463258bc2ad20a1)) * get address if multiple companies ([0493872](https://github.com/frappe/erpnext/commit/04938726d9ca1803505d118c0650d3df6e9f4f84)) * **gp:** SLEs not fetched for correct warehouse ([97e7b3f](https://github.com/frappe/erpnext/commit/97e7b3f3d3f1bd77e26db7dc3e02796ce683b092)) * incorrect exc gain/loss for PE against JE for payable accounts ([50a74ee](https://github.com/frappe/erpnext/commit/50a74ee7fe95f1b58bdf8ef935eae5ba0bc04ffc)) * Resolve merge conflicts ([cc925ae](https://github.com/frappe/erpnext/commit/cc925ae938a201beff8413f21646fa17522db8f6)) * Subcontracting Receipt GL Entries (backport [#40773](https://github.com/frappe/erpnext/issues/40773)) ([#40978](https://github.com/frappe/erpnext/issues/40978)) ([c2c4548](https://github.com/frappe/erpnext/commit/c2c4548cc0013dd058e564157c767e9b18f66582)) * test cases ([79e23da](https://github.com/frappe/erpnext/commit/79e23dad2c61aafb0145048a49a2d79abf811cb0)) * **treewide:** manual ruff fixes ([b087fb3](https://github.com/frappe/erpnext/commit/b087fb3d549462ea8c9d1e65e8622e952d4039f6)) * use 'eq' and isnull() on qb conditions ([b4ed2d2](https://github.com/frappe/erpnext/commit/b4ed2d2c16d64d8fd06ec9c273f25c97f032d124)) --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 0898ee7b4cd8..95ffb09c661c 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -3,7 +3,7 @@ import frappe -__version__ = "14.67.1" +__version__ = "14.67.2" def get_default_company(user=None):