From db033c686229c12671062404efb409c17100635f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 22 Feb 2023 12:30:09 +0530 Subject: [PATCH 01/24] feat: adjust purchase receipt valuation rate as per purchase invoice rate (cherry picked from commit eab775ef3222c2948fa643436612816f01cb52bb) --- .../purchase_invoice/purchase_invoice.py | 35 +++++++++++++- .../buying_settings/buying_settings.json | 11 ++++- erpnext/controllers/buying_controller.py | 5 +- .../purchase_receipt/purchase_receipt.py | 47 ++++++++++++++++++- .../purchase_receipt_item.json | 11 ++++- 5 files changed, 103 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 3bac68a8f65..435dd2461d1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -528,6 +528,32 @@ class PurchaseInvoice(BuyingController): self.update_advance_tax_references() self.process_common_party_accounting() + self.adjust_incoming_rate_of_purchase_receipt() + + def adjust_incoming_rate_of_purchase_receipt(self): + if ( + not frappe.db.get_single_value( + "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate" + ) + and self.is_subcontracted + ): + return + + purchase_receipts = [] + for item in self.items: + if item.purchase_receipt and item.purchase_receipt not in purchase_receipts: + purchase_receipts.append(item.purchase_receipt) + + for purchase_receipt in purchase_receipts: + doc = frappe.get_doc("Purchase Receipt", purchase_receipt) + doc.docstatus = 2 + doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) + doc.make_gl_entries_on_cancel() + + doc.docstatus = 1 + doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) + doc.make_gl_entries() + doc.repost_future_sle_and_gle() def make_gl_entries(self, gl_entries=None, from_repost=False): if not gl_entries: @@ -1423,6 +1449,7 @@ class PurchaseInvoice(BuyingController): "Tax Withheld Vouchers", ) self.update_advance_tax_references(cancel=1) + self.adjust_incoming_rate_of_purchase_receipt() def update_project(self): project_list = [] @@ -1485,11 +1512,17 @@ class PurchaseInvoice(BuyingController): if po_details: updated_pr += update_billed_amount_based_on_po(po_details, update_modified) + adjust_incoming_rate = frappe.db.get_single_value( + "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate" + ) + for pr in set(updated_pr): from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billing_percentage pr_doc = frappe.get_doc("Purchase Receipt", pr) - update_billing_percentage(pr_doc, update_modified=update_modified) + update_billing_percentage( + pr_doc, update_modified=update_modified, adjust_incoming_rate=adjust_incoming_rate + ) def get_pr_details_billed_amt(self): # Get billed amount based on purchase receipt item reference (pr_detail) in purchase invoice diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 652dcf0d43c..7bbe89a063b 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -18,6 +18,7 @@ "pr_required", "column_break_12", "maintain_same_rate", + "adjust_incoming_rate_based_on_purchase_invoice_rate", "allow_multiple_items", "bill_for_rejected_quantity_in_purchase_invoice", "disable_last_purchase_rate", @@ -147,6 +148,14 @@ "fieldname": "show_pay_button", "fieldtype": "Check", "label": "Show Pay Button in Purchase Order Portal" + }, + { + "default": "0", + "depends_on": "eval: !doc.maintain_same_rate", + "description": "Users can enable the checkbox If they want to adjust the incoming rate (set using purchase receipt) based on the purchase invoice rate.", + "fieldname": "adjust_incoming_rate_based_on_purchase_invoice_rate", + "fieldtype": "Check", + "label": "Adjust Incoming Rate Based on Purchase Invoice Rate" } ], "icon": "fa fa-cog", @@ -154,7 +163,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-02-15 14:42:10.200679", + "modified": "2023-02-20 14:25:58.544143", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index cf267716d58..aa050beec4e 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -269,7 +269,10 @@ class BuyingController(SubcontractingController): ) / qty_in_stock_uom else: item.valuation_rate = ( - item.base_net_amount + item.item_tax_amount + flt(item.landed_cost_voucher_amount) + item.base_net_amount + + item.item_tax_amount + + flt(item.landed_cost_voucher_amount) + + flt(item.get("adjust_incoming_rate")) ) / qty_in_stock_uom else: item.valuation_rate = 0.0 diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index c8a4bd3d276..0f3224cffb3 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -293,6 +293,7 @@ class PurchaseReceipt(BuyingController): get_purchase_document_details, ) + stock_rbnb = None if erpnext.is_perpetual_inventory_enabled(self.company): stock_rbnb = self.get_company_default("stock_received_but_not_billed") landed_cost_entries = get_item_account_wise_additional_cost(self.name) @@ -450,6 +451,21 @@ class PurchaseReceipt(BuyingController): item=d, ) + if d.adjust_incoming_rate and stock_rbnb: + account_currency = get_account_currency(stock_rbnb) + self.add_gl_entry( + gl_entries=gl_entries, + account=stock_rbnb, + cost_center=d.cost_center, + debit=0.0, + credit=flt(d.adjust_incoming_rate), + remarks=_("Adjustment based on Purchase Invoice rate"), + against_account=warehouse_account_name, + account_currency=account_currency, + project=d.project, + item=d, + ) + # sub-contracting warehouse if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): self.add_gl_entry( @@ -470,6 +486,7 @@ class PurchaseReceipt(BuyingController): + flt(d.landed_cost_voucher_amount) + flt(d.rm_supp_cost) + flt(d.item_tax_amount) + + flt(d.adjust_incoming_rate) ) divisional_loss = flt( @@ -765,7 +782,7 @@ class PurchaseReceipt(BuyingController): updated_pr += update_billed_amount_based_on_po(po_details, update_modified) for pr in set(updated_pr): - pr_doc = self if (pr == self.name) else frappe.get_cached_doc("Purchase Receipt", pr) + pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr) update_billing_percentage(pr_doc, update_modified=update_modified) self.load_from_db() @@ -881,7 +898,7 @@ def get_billed_amount_against_po(po_items): return {d.po_detail: flt(d.billed_amt) for d in query} -def update_billing_percentage(pr_doc, update_modified=True): +def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate=False): # Reload as billed amount was set in db directly pr_doc.load_from_db() @@ -897,6 +914,12 @@ def update_billing_percentage(pr_doc, update_modified=True): total_amount += total_billable_amount total_billed_amount += flt(item.billed_amt) + if adjust_incoming_rate: + adjusted_amt = 0.0 + if item.billed_amt and item.amount: + adjusted_amt = flt(item.billed_amt) - flt(item.amount) + + item.db_set("adjust_incoming_rate", adjusted_amt, update_modified=False) percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6) pr_doc.db_set("per_billed", percent_billed) @@ -906,6 +929,26 @@ def update_billing_percentage(pr_doc, update_modified=True): pr_doc.set_status(update=True) pr_doc.notify_update() + if adjust_incoming_rate: + adjust_incoming_rate_for_pr(pr_doc) + + +def adjust_incoming_rate_for_pr(doc): + doc.update_valuation_rate(reset_outgoing_rate=False) + + for item in doc.get("items"): + item.db_update() + + doc.docstatus = 2 + doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) + doc.make_gl_entries_on_cancel() + + # update stock & gl entries for submit state of PR + doc.docstatus = 1 + doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) + doc.make_gl_entries() + doc.repost_future_sle_and_gle() + def get_item_wise_returned_qty(pr_doc): items = [d.name for d in pr_doc.items] diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 7a350b9e446..e12c5834619 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -69,6 +69,7 @@ "item_tax_amount", "rm_supp_cost", "landed_cost_voucher_amount", + "adjust_incoming_rate", "billed_amt", "warehouse_and_reference", "warehouse", @@ -1007,12 +1008,20 @@ "fieldtype": "Check", "label": "Has Item Scanned", "read_only": 1 + }, + { + "fieldname": "adjust_incoming_rate", + "fieldtype": "Currency", + "label": "Adjust Incoming Rate (Purchase Invoice)", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-01-18 15:48:58.114923", + "modified": "2023-02-28 12:05:59.732266", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From 3ea1c73c07309752458ee75e0dfa741a13976e45 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 28 Feb 2023 14:39:05 +0530 Subject: [PATCH 02/24] test: added test cases (cherry picked from commit 8e865537170251e8a788a73034345f12b90017d1) --- .../purchase_invoice/purchase_invoice.py | 27 ------ .../purchase_invoice/test_purchase_invoice.py | 88 +++++++++++++++++++ .../buying_settings/buying_settings.py | 7 ++ 3 files changed, 95 insertions(+), 27 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 435dd2461d1..0036abdc59d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -528,32 +528,6 @@ class PurchaseInvoice(BuyingController): self.update_advance_tax_references() self.process_common_party_accounting() - self.adjust_incoming_rate_of_purchase_receipt() - - def adjust_incoming_rate_of_purchase_receipt(self): - if ( - not frappe.db.get_single_value( - "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate" - ) - and self.is_subcontracted - ): - return - - purchase_receipts = [] - for item in self.items: - if item.purchase_receipt and item.purchase_receipt not in purchase_receipts: - purchase_receipts.append(item.purchase_receipt) - - for purchase_receipt in purchase_receipts: - doc = frappe.get_doc("Purchase Receipt", purchase_receipt) - doc.docstatus = 2 - doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) - doc.make_gl_entries_on_cancel() - - doc.docstatus = 1 - doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True) - doc.make_gl_entries() - doc.repost_future_sle_and_gle() def make_gl_entries(self, gl_entries=None, from_repost=False): if not gl_entries: @@ -1449,7 +1423,6 @@ class PurchaseInvoice(BuyingController): "Tax Withheld Vouchers", ) self.update_advance_tax_references(cancel=1) - self.adjust_incoming_rate_of_purchase_receipt() def update_project(self): project_list = [] diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index f901257ccf6..d20eddfc96f 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1523,6 +1523,94 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin): company.enable_provisional_accounting_for_non_stock_items = 0 company.save() + def test_adjust_incoming_rate(self): + frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) + + frappe.db.set_single_value( + "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate", 1 + ) + + # Increase the cost of the item + + pr = make_purchase_receipt(qty=1, rate=100) + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 100) + + pi = create_purchase_invoice_from_receipt(pr.name) + for row in pi.items: + row.rate = 150 + + pi.save() + pi.submit() + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 150) + + # Reduce the cost of the item + + pr = make_purchase_receipt(qty=1, rate=100) + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 100) + + pi = create_purchase_invoice_from_receipt(pr.name) + for row in pi.items: + row.rate = 50 + + pi.save() + pi.submit() + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 50) + + frappe.db.set_single_value( + "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate", 0 + ) + + # Don't adjust incoming rate + + pr = make_purchase_receipt(qty=1, rate=100) + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 100) + + pi = create_purchase_invoice_from_receipt(pr.name) + for row in pi.items: + row.rate = 50 + + pi.save() + pi.submit() + + stock_value_difference = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_type": "Purchase Receipt", "voucher_no": pr.name}, + "stock_value_difference", + ) + self.assertEqual(stock_value_difference, 100) + + frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1) + def test_item_less_defaults(self): pi = frappe.new_doc("Purchase Invoice") diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py index be1ebdeb64e..d14ffc90ad7 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.py +++ b/erpnext/buying/doctype/buying_settings/buying_settings.py @@ -21,3 +21,10 @@ class BuyingSettings(Document): self.get("supp_master_name") == "Naming Series", hide_name_field=False, ) + + def before_save(self): + self.check_maintain_same_rate() + + def check_maintain_same_rate(self): + if self.maintain_same_rate: + self.adjust_incoming_rate_based_on_purchase_invoice_rate = 0 From 5e9f1dfbb3f136aa70f6bb476d90aae77790d80d Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 28 Feb 2023 15:47:45 +0530 Subject: [PATCH 03/24] fix: labels name (cherry picked from commit a8445da02aa48dfa2a44e426074c59f4f04e5356) --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 2 +- .../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++-- .../buying/doctype/buying_settings/buying_settings.json | 8 ++++---- erpnext/buying/doctype/buying_settings/buying_settings.py | 2 +- erpnext/controllers/buying_controller.py | 2 +- .../stock/doctype/purchase_receipt/purchase_receipt.py | 8 ++++---- .../purchase_receipt_item/purchase_receipt_item.json | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 0036abdc59d..ae707ab1435 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1486,7 +1486,7 @@ class PurchaseInvoice(BuyingController): updated_pr += update_billed_amount_based_on_po(po_details, update_modified) adjust_incoming_rate = frappe.db.get_single_value( - "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate" + "Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate" ) for pr in set(updated_pr): diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index d20eddfc96f..a6d7df6971f 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1527,7 +1527,7 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin): frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) frappe.db.set_single_value( - "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate", 1 + "Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1 ) # Increase the cost of the item @@ -1581,7 +1581,7 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin): self.assertEqual(stock_value_difference, 50) frappe.db.set_single_value( - "Buying Settings", "adjust_incoming_rate_based_on_purchase_invoice_rate", 0 + "Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0 ) # Don't adjust incoming rate diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 7bbe89a063b..95857e4604d 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -18,7 +18,7 @@ "pr_required", "column_break_12", "maintain_same_rate", - "adjust_incoming_rate_based_on_purchase_invoice_rate", + "set_landed_cost_based_on_purchase_invoice_rate", "allow_multiple_items", "bill_for_rejected_quantity_in_purchase_invoice", "disable_last_purchase_rate", @@ -153,9 +153,9 @@ "default": "0", "depends_on": "eval: !doc.maintain_same_rate", "description": "Users can enable the checkbox If they want to adjust the incoming rate (set using purchase receipt) based on the purchase invoice rate.", - "fieldname": "adjust_incoming_rate_based_on_purchase_invoice_rate", + "fieldname": "set_landed_cost_based_on_purchase_invoice_rate", "fieldtype": "Check", - "label": "Adjust Incoming Rate Based on Purchase Invoice Rate" + "label": "Set Landed Cost Based on Purchase Invoice Rate" } ], "icon": "fa fa-cog", @@ -163,7 +163,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-02-20 14:25:58.544143", + "modified": "2023-02-28 15:41:32.686805", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py index d14ffc90ad7..4680a889d3a 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.py +++ b/erpnext/buying/doctype/buying_settings/buying_settings.py @@ -27,4 +27,4 @@ class BuyingSettings(Document): def check_maintain_same_rate(self): if self.maintain_same_rate: - self.adjust_incoming_rate_based_on_purchase_invoice_rate = 0 + self.set_landed_cost_based_on_purchase_invoice_rate = 0 diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index aa050beec4e..ab29dd85829 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -272,7 +272,7 @@ class BuyingController(SubcontractingController): item.base_net_amount + item.item_tax_amount + flt(item.landed_cost_voucher_amount) - + flt(item.get("adjust_incoming_rate")) + + flt(item.get("rate_difference_with_purchase_invoice")) ) / qty_in_stock_uom else: item.valuation_rate = 0.0 diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 0f3224cffb3..c1abd31bcc1 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -451,14 +451,14 @@ class PurchaseReceipt(BuyingController): item=d, ) - if d.adjust_incoming_rate and stock_rbnb: + if d.rate_difference_with_purchase_invoice and stock_rbnb: account_currency = get_account_currency(stock_rbnb) self.add_gl_entry( gl_entries=gl_entries, account=stock_rbnb, cost_center=d.cost_center, debit=0.0, - credit=flt(d.adjust_incoming_rate), + credit=flt(d.rate_difference_with_purchase_invoice), remarks=_("Adjustment based on Purchase Invoice rate"), against_account=warehouse_account_name, account_currency=account_currency, @@ -486,7 +486,7 @@ class PurchaseReceipt(BuyingController): + flt(d.landed_cost_voucher_amount) + flt(d.rm_supp_cost) + flt(d.item_tax_amount) - + flt(d.adjust_incoming_rate) + + flt(d.rate_difference_with_purchase_invoice) ) divisional_loss = flt( @@ -919,7 +919,7 @@ def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate if item.billed_amt and item.amount: adjusted_amt = flt(item.billed_amt) - flt(item.amount) - item.db_set("adjust_incoming_rate", adjusted_amt, update_modified=False) + item.db_set("rate_difference_with_purchase_invoice", adjusted_amt, update_modified=False) percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6) pr_doc.db_set("per_billed", percent_billed) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index e12c5834619..cd320fdfcd0 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -69,7 +69,7 @@ "item_tax_amount", "rm_supp_cost", "landed_cost_voucher_amount", - "adjust_incoming_rate", + "rate_difference_with_purchase_invoice", "billed_amt", "warehouse_and_reference", "warehouse", @@ -1010,9 +1010,9 @@ "read_only": 1 }, { - "fieldname": "adjust_incoming_rate", + "fieldname": "rate_difference_with_purchase_invoice", "fieldtype": "Currency", - "label": "Adjust Incoming Rate (Purchase Invoice)", + "label": "Rate Difference with Purchase Invoice", "no_copy": 1, "print_hide": 1, "read_only": 1 @@ -1021,7 +1021,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-02-28 12:05:59.732266", + "modified": "2023-02-28 15:43:04.470104", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From 7eccf431fd4caa755a9224a4ea635017022d14fe Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 1 Mar 2023 11:06:46 +0530 Subject: [PATCH 04/24] fix: consumed qty validation for subcontracting receipt (cherry picked from commit b38fe240900da4e3ac64c7bb03ef3aecbcd09f0d) --- .../subcontracting_receipt.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index f4fd4de169d..95dbc83bf80 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -191,14 +191,17 @@ class SubcontractingReceipt(SubcontractingController): def validate_available_qty_for_consumption(self): for item in self.get("supplied_items"): + precision = item.precision("consumed_qty") if ( - item.available_qty_for_consumption and item.available_qty_for_consumption < item.consumed_qty + item.available_qty_for_consumption + and flt(item.available_qty_for_consumption, precision) - flt(item.consumed_qty, precision) < 0 ): - frappe.throw( - _( - "Row {0}: Consumed Qty must be less than or equal to Available Qty For Consumption in Consumed Items Table." - ).format(item.idx) - ) + msg = f"""Row {item.idx}: Consumed Qty {flt(item.consumed_qty, precision)} + must be less than or equal to Available Qty For Consumption + {flt(item.available_qty_for_consumption, precision)} + in Consumed Items Table.""" + + frappe.throw(_(msg)) def validate_items_qty(self): for item in self.items: From b13bf1ebc517ccd9c5b6b079208ca3883e7418fd Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 1 Mar 2023 16:16:58 +0530 Subject: [PATCH 05/24] fix: Wrap unexpectedly long text in remark (cherry picked from commit ba66a6714c495f9d70dad79344342779c8011c6e) # Conflicts: # erpnext/accounts/report/general_ledger/general_ledger.html --- .../report/general_ledger/general_ledger.html | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html index 475be92add5..e91c05dfb8c 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.html +++ b/erpnext/accounts/report/general_ledger/general_ledger.html @@ -38,8 +38,11 @@ {% if(data[i].posting_date) { %} {%= frappe.datetime.str_to_user(data[i].posting_date) %} {%= data[i].voucher_type %} -
{%= data[i].voucher_no %} - +
{%= data[i].voucher_no %} + + {% var longest_word = cstr(data[i].remarks).split(" ").reduce((longest, word) => word.length > longest.length ? word : longest, ""); %} + 45 %} class="overflow-wrap-anywhere" {% endif %}> + {% if(!(filters.party || filters.account)) { %} {%= data[i].party || data[i].account %}
@@ -49,11 +52,22 @@ {% if(data[i].bill_no) { %}
{%= __("Supplier Invoice No") %}: {%= data[i].bill_no %} {% } %} +<<<<<<< HEAD {%= format_currency(data[i].debit, filters.presentation_currency || data[i].account_currency) %} {%= format_currency(data[i].credit, filters.presentation_currency || data[i].account_currency) %} +======= +
+ + + {%= format_currency(data[i].debit, filters.presentation_currency) %} + + + {%= format_currency(data[i].credit, filters.presentation_currency) %} + +>>>>>>> ba66a6714c (fix: Wrap unexpectedly long text in remark) {% } else { %} From f6469d83981386a7bb57b41178055eae5cda30bf Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Wed, 1 Mar 2023 16:25:25 +0530 Subject: [PATCH 06/24] fix: Resolve conflicts --- .../accounts/report/general_ledger/general_ledger.html | 8 -------- 1 file changed, 8 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html index e91c05dfb8c..2d5ca497654 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.html +++ b/erpnext/accounts/report/general_ledger/general_ledger.html @@ -52,13 +52,6 @@ {% if(data[i].bill_no) { %}
{%= __("Supplier Invoice No") %}: {%= data[i].bill_no %} {% } %} -<<<<<<< HEAD - - - {%= format_currency(data[i].debit, filters.presentation_currency || data[i].account_currency) %} - - {%= format_currency(data[i].credit, filters.presentation_currency || data[i].account_currency) %} -======= @@ -67,7 +60,6 @@ {%= format_currency(data[i].credit, filters.presentation_currency) %} ->>>>>>> ba66a6714c (fix: Wrap unexpectedly long text in remark) {% } else { %} From 3db82587eb9d3e55a672bdbd2118a37ee1e72f33 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 2 Mar 2023 11:15:46 +0530 Subject: [PATCH 07/24] fix: `rejected_serial_no` not getting copied from PR to PR(Return) (cherry picked from commit a9f0a11ce62d8337fcbc1ebdda3be1b818a5f8a2) --- erpnext/controllers/sales_and_purchase_return.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 8bd09982bf4..c5ef28a2eed 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -400,6 +400,16 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None): if serial_nos: target_doc.serial_no = "\n".join(serial_nos) + if source_doc.get("rejected_serial_no"): + returned_serial_nos = get_returned_serial_nos( + source_doc, source_parent, serial_no_field="rejected_serial_no" + ) + rejected_serial_nos = list( + set(get_serial_nos(source_doc.rejected_serial_no)) - set(returned_serial_nos) + ) + if rejected_serial_nos: + target_doc.rejected_serial_no = "\n".join(rejected_serial_nos) + if doctype in ["Purchase Receipt", "Subcontracting Receipt"]: returned_qty_map = get_returned_qty_map_for_row( source_parent.name, source_parent.supplier, source_doc.name, doctype @@ -610,7 +620,7 @@ def get_filters( return filters -def get_returned_serial_nos(child_doc, parent_doc): +def get_returned_serial_nos(child_doc, parent_doc, serial_no_field="serial_no"): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos return_ref_field = frappe.scrub(child_doc.doctype) @@ -619,7 +629,7 @@ def get_returned_serial_nos(child_doc, parent_doc): serial_nos = [] - fields = ["`{0}`.`serial_no`".format("tab" + child_doc.doctype)] + fields = [f"`{'tab' + child_doc.doctype}`.`{serial_no_field}`"] filters = [ [parent_doc.doctype, "return_against", "=", parent_doc.name], @@ -629,6 +639,6 @@ def get_returned_serial_nos(child_doc, parent_doc): ] for row in frappe.get_all(parent_doc.doctype, fields=fields, filters=filters): - serial_nos.extend(get_serial_nos(row.serial_no)) + serial_nos.extend(get_serial_nos(row.get(serial_no_field))) return serial_nos From aa6b891ef0285102797f924d75e2332f60008dd8 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 2 Mar 2023 11:27:46 +0530 Subject: [PATCH 08/24] fix: `Serial No is mandatory` even if the `qty` is `0` (cherry picked from commit cb0b6de4b97009d0f7d1053f4e065416971a4832) --- erpnext/controllers/sales_and_purchase_return.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index c5ef28a2eed..341d51b8a5f 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -131,7 +131,7 @@ def validate_returned_items(doc): ) elif ref.serial_no: - if not d.serial_no: + if d.qty and not d.serial_no: frappe.throw(_("Row # {0}: Serial No is mandatory").format(d.idx)) else: serial_nos = get_serial_nos(d.serial_no) From 1e086db7c7d96335bb28126745d11538f8a6810a Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Sat, 18 Feb 2023 12:18:41 +0530 Subject: [PATCH 09/24] refactor: rewrite `get_item_details.py` queries in `QB` (cherry picked from commit 6b144baa69c0c31c8e7fb7e9ba3ccd9d9671e7fb) --- erpnext/stock/get_item_details.py | 271 +++++++++++++++--------------- 1 file changed, 140 insertions(+), 131 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index b53f429edf2..e2a1f3973c2 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -8,6 +8,7 @@ import frappe from frappe import _, throw from frappe.model import child_table_fields, default_fields from frappe.model.meta import get_field_precision +from frappe.query_builder.functions import CombineDatetime, IfNull, Sum from frappe.utils import add_days, add_months, cint, cstr, flt, getdate from erpnext import get_company_currency @@ -526,12 +527,8 @@ def get_barcode_data(items_list): itemwise_barcode = {} for item in items_list: - barcodes = frappe.db.sql( - """ - select barcode from `tabItem Barcode` where parent = %s - """, - item.item_code, - as_dict=1, + barcodes = frappe.db.get_all( + "Item Barcode", filters={"parent": item.item_code}, fields="barcode" ) for barcode in barcodes: @@ -891,34 +888,36 @@ def get_item_price(args, item_code, ignore_party=False): :param item_code: str, Item Doctype field item_code """ - args["item_code"] = item_code - - conditions = """where item_code=%(item_code)s - and price_list=%(price_list)s - and ifnull(uom, '') in ('', %(uom)s)""" - - conditions += "and ifnull(batch_no, '') in ('', %(batch_no)s)" + ip = frappe.qb.DocType("Item Price") + query = ( + frappe.qb.from_(ip) + .select(ip.name, ip.price_list_rate, ip.uom) + .where( + (ip.item_code == item_code) + & (ip.price_list == args.get("price_list")) + & (IfNull(ip.uom, "").isin(["", args.get("uom")])) + & (IfNull(ip.batch_no, "").isin(["", args.get("batch_no")])) + ) + .orderby(ip.valid_from, order=frappe.qb.desc) + .orderby(IfNull(ip.batch_no, ""), order=frappe.qb.desc) + .orderby(ip.uom, order=frappe.qb.desc) + ) if not ignore_party: if args.get("customer"): - conditions += " and customer=%(customer)s" + query = query.where(ip.customer == args.get("customer")) elif args.get("supplier"): - conditions += " and supplier=%(supplier)s" + query = query.where(ip.supplier == args.get("supplier")) else: - conditions += "and (customer is null or customer = '') and (supplier is null or supplier = '')" + query = query.where((IfNull(ip.customer, "") == "") & (IfNull(ip.supplier, "") == "")) if args.get("transaction_date"): - conditions += """ and %(transaction_date)s between - ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')""" + query = query.where( + (IfNull(ip.valid_from, "2000-01-01") <= args["transaction_date"]) + & (IfNull(ip.valid_upto, "2500-12-31") >= args["transaction_date"]) + ) - return frappe.db.sql( - """ select name, price_list_rate, uom - from `tabItem Price` {conditions} - order by valid_from desc, ifnull(batch_no, '') desc, uom desc """.format( - conditions=conditions - ), - args, - ) + return query.run() def get_price_list_rate_for(args, item_code): @@ -1091,91 +1090,88 @@ def get_pos_profile(company, pos_profile=None, user=None): if not user: user = frappe.session["user"] - condition = "pfu.user = %(user)s AND pfu.default=1" - if user and company: - condition = "pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1" + pf = frappe.qb.DocType("POS Profile") + pfu = frappe.qb.DocType("POS Profile User") - pos_profile = frappe.db.sql( - """SELECT pf.* - FROM - `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu - ON - pf.name = pfu.parent - WHERE - {cond} AND pf.disabled = 0 - """.format( - cond=condition - ), - {"user": user, "company": company}, - as_dict=1, + query = ( + frappe.qb.from_(pf) + .left_join(pfu) + .on(pf.name == pfu.parent) + .select(pf.star) + .where((pfu.user == user) & (pfu.default == 1)) ) + if company: + query = query.where(pf.company == company) + + pos_profile = query.run(as_dict=True) + if not pos_profile and company: - pos_profile = frappe.db.sql( - """SELECT pf.* - FROM - `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu - ON - pf.name = pfu.parent - WHERE - pf.company = %(company)s AND pf.disabled = 0 - """, - {"company": company}, - as_dict=1, - ) + pos_profile = ( + frappe.qb.from_(pf) + .left_join(pfu) + .on(pf.name == pfu.parent) + .select(pf.star) + .where((pf.company == company) & (pf.disabled == 0)) + ).run(as_dict=True) return pos_profile and pos_profile[0] or None def get_serial_nos_by_fifo(args, sales_order=None): if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): - return "\n".join( - frappe.db.sql_list( - """select name from `tabSerial No` - where item_code=%(item_code)s and warehouse=%(warehouse)s and - sales_order=IF(%(sales_order)s IS NULL, sales_order, %(sales_order)s) - order by timestamp(purchase_date, purchase_time) - asc limit %(qty)s""", - { - "item_code": args.item_code, - "warehouse": args.warehouse, - "qty": abs(cint(args.stock_qty)), - "sales_order": sales_order, - }, - ) + sn = frappe.qb.DocType("Serial No") + query = ( + frappe.qb.from_(sn) + .select(sn.name) + .where((sn.item_code == args.item_code) & (sn.warehouse == args.warehouse)) + .orderby(CombineDatetime(sn.purchase_date, sn.purchase_time)) + .limit(abs(cint(args.stock_qty))) ) + if sales_order: + query = query.where(sn.sales_order == sales_order) + + serial_nos = query.run(as_list=True) + serial_nos = [s[0] for s in serial_nos] + + return "\n".join(serial_nos) + def get_serial_no_batchwise(args, sales_order=None): if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): - return "\n".join( - frappe.db.sql_list( - """select name from `tabSerial No` - where item_code=%(item_code)s and warehouse=%(warehouse)s and - sales_order=IF(%(sales_order)s IS NULL, sales_order, %(sales_order)s) - and batch_no=IF(%(batch_no)s IS NULL, batch_no, %(batch_no)s) order - by timestamp(purchase_date, purchase_time) asc limit %(qty)s""", - { - "item_code": args.item_code, - "warehouse": args.warehouse, - "batch_no": args.batch_no, - "qty": abs(cint(args.stock_qty)), - "sales_order": sales_order, - }, - ) + sn = frappe.qb.DocType("Serial No") + query = ( + frappe.qb.from_(sn) + .select(sn.name) + .where((sn.item_code == args.item_code) & (sn.warehouse == args.warehouse)) + .orderby(CombineDatetime(sn.purchase_date, sn.purchase_time)) + .limit(abs(cint(args.stock_qty))) ) + if sales_order: + query = query.where(sn.sales_order == sales_order) + if args.batch_no: + query = query.where(sn.batch_no == args.batch_no) + + serial_nos = query.run(as_list=True) + serial_nos = [s[0] for s in serial_nos] + + return "\n".join(serial_nos) + @frappe.whitelist() def get_conversion_factor(item_code, uom): variant_of = frappe.db.get_value("Item", item_code, "variant_of", cache=True) filters = {"parent": item_code, "uom": uom} + if variant_of: filters["parent"] = ("in", (item_code, variant_of)) conversion_factor = frappe.db.get_value("UOM Conversion Detail", filters, "conversion_factor") if not conversion_factor: stock_uom = frappe.db.get_value("Item", item_code, "stock_uom") conversion_factor = get_uom_conv_factor(uom, stock_uom) + return {"conversion_factor": conversion_factor or 1.0} @@ -1194,7 +1190,6 @@ def get_bin_details(item_code, warehouse, company=None, include_child_warehouses if warehouse: from frappe.query_builder.functions import Coalesce, Sum - from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses warehouses = get_child_warehouses(warehouse) if include_child_warehouses else [warehouse] @@ -1217,12 +1212,16 @@ def get_bin_details(item_code, warehouse, company=None, include_child_warehouses def get_company_total_stock(item_code, company): - return frappe.db.sql( - """SELECT sum(actual_qty) from - (`tabBin` INNER JOIN `tabWarehouse` ON `tabBin`.warehouse = `tabWarehouse`.name) - WHERE `tabWarehouse`.company = %s and `tabBin`.item_code = %s""", - (company, item_code), - )[0][0] + bin = frappe.qb.DocType("Bin") + wh = frappe.qb.DocType("Warehouse") + + return ( + frappe.qb.from_(bin) + .inner_join(wh) + .on(bin.warehouse == wh.name) + .select(Sum(bin.actual_qty)) + .where((wh.company == company) & (bin.item_code == item_code)) + ).run()[0][0] @frappe.whitelist() @@ -1231,6 +1230,7 @@ def get_serial_no_details(item_code, warehouse, stock_qty, serial_no): {"item_code": item_code, "warehouse": warehouse, "stock_qty": stock_qty, "serial_no": serial_no} ) serial_no = get_serial_no(args) + return {"serial_no": serial_no} @@ -1250,6 +1250,7 @@ def get_bin_details_and_serial_nos( bin_details_and_serial_nos.update( get_serial_no_details(item_code, warehouse, stock_qty, serial_no) ) + return bin_details_and_serial_nos @@ -1264,6 +1265,7 @@ def get_batch_qty_and_serial_no(batch_no, stock_qty, warehouse, item_code, has_s ) serial_no = get_serial_no(args) batch_qty_and_serial_no.update({"serial_no": serial_no}) + return batch_qty_and_serial_no @@ -1336,7 +1338,6 @@ def apply_price_list(args, as_doc=False): def apply_price_list_on_item(args): item_doc = frappe.db.get_value("Item", args.item_code, ["name", "variant_of"], as_dict=1) item_details = get_price_list_rate(args, item_doc) - item_details.update(get_pricing_rule_for_item(args)) return item_details @@ -1420,12 +1421,15 @@ def get_valuation_rate(item_code, company, warehouse=None): ) or {"valuation_rate": 0} elif not item.get("is_stock_item"): - valuation_rate = frappe.db.sql( - """select sum(base_net_amount) / sum(qty*conversion_factor) - from `tabPurchase Invoice Item` - where item_code = %s and docstatus=1""", - item_code, - ) + 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))) + .where( + (pi_item.docstatus == 1) + & (pi_item.item_code == item_code) + ) + ).run() if valuation_rate: return {"valuation_rate": valuation_rate[0][0] or 0.0} @@ -1483,31 +1487,35 @@ def get_blanket_order_details(args): args = frappe._dict(json.loads(args)) blanket_order_details = None - condition = "" - if args.item_code: - if args.customer and args.doctype == "Sales Order": - condition = " and bo.customer=%(customer)s" - elif args.supplier and args.doctype == "Purchase Order": - condition = " and bo.supplier=%(supplier)s" - if args.blanket_order: - condition += " and bo.name =%(blanket_order)s" - if args.transaction_date: - condition += " and bo.to_date>=%(transaction_date)s" - blanket_order_details = frappe.db.sql( - """ - select boi.rate as blanket_order_rate, bo.name as blanket_order - from `tabBlanket Order` bo, `tabBlanket Order Item` boi - where bo.company=%(company)s and boi.item_code=%(item_code)s - and bo.docstatus=1 and bo.name = boi.parent {0} - """.format( - condition - ), - args, - as_dict=True, + if args.item_code: + bo = frappe.qb.DocType("Blanket Order") + bo_item = frappe.qb.DocType("Blanket Order Item") + + query = ( + frappe.qb.from_(bo) + .from_(bo_item) + .select(bo_item.rate.as_("blanket_order_rate"), bo.name.as_("blanket_order")) + .where( + (bo.company == args.company) + & (bo_item.item_code == args.item_code) + & (bo.docstatus == 1) + & (bo.name == bo_item.parent) + ) ) + if args.customer and args.doctype == "Sales Order": + query = query.where(bo.customer == args.customer) + elif args.supplier and args.doctype == "Purchase Order": + query = query.where(bo.supplier == args.supplier) + if args.blanket_order: + query = query.where(bo.name == args.blanket_order) + if args.transaction_date: + query = query.where(bo.to_date >= args.transaction_date) + + blanket_order_details = query.run(as_dict=True) blanket_order_details = blanket_order_details[0] if blanket_order_details else "" + return blanket_order_details @@ -1517,10 +1525,10 @@ def get_so_reservation_for_item(args): if get_reserved_qty_for_so(args.get("against_sales_order"), args.get("item_code")): reserved_so = args.get("against_sales_order") elif args.get("against_sales_invoice"): - sales_order = frappe.db.sql( - """select sales_order from `tabSales Invoice Item` where - parent=%s and item_code=%s""", - (args.get("against_sales_invoice"), args.get("item_code")), + sales_order = frappe.db.get_all( + "Sales Invoice Item", + filters={"parent": args.get("against_sales_invoice"), "item_code": args.get("item_code")}, + fields="sales_order", ) if sales_order and sales_order[0]: if get_reserved_qty_for_so(sales_order[0][0], args.get("item_code")): @@ -1532,13 +1540,14 @@ def get_so_reservation_for_item(args): def get_reserved_qty_for_so(sales_order, item_code): - reserved_qty = frappe.db.sql( - """select sum(qty) from `tabSales Order Item` - where parent=%s and item_code=%s and ensure_delivery_based_on_produced_serial_no=1 - """, - (sales_order, item_code), + reserved_qty = frappe.db.get_value( + "Sales Order Item", + filters={ + "parent": sales_order, + "item_code": item_code, + "ensure_delivery_based_on_produced_serial_no": 1, + }, + fieldname="sum(qty)", ) - if reserved_qty and reserved_qty[0][0]: - return reserved_qty[0][0] - else: - return 0 + + return reserved_qty or 0 From dea5290d81dca51da28d73fe58622df0557fa935 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Sat, 18 Feb 2023 14:33:31 +0530 Subject: [PATCH 10/24] refactor: remove method `get_serial_no_batchwise` from `get_item_details.py` (cherry picked from commit 35489fbbf94080644094a73dd1cc643de1a059c9) --- erpnext/stock/get_item_details.py | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index e2a1f3973c2..f017af6e915 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -1119,26 +1119,6 @@ def get_pos_profile(company, pos_profile=None, user=None): def get_serial_nos_by_fifo(args, sales_order=None): - if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): - sn = frappe.qb.DocType("Serial No") - query = ( - frappe.qb.from_(sn) - .select(sn.name) - .where((sn.item_code == args.item_code) & (sn.warehouse == args.warehouse)) - .orderby(CombineDatetime(sn.purchase_date, sn.purchase_time)) - .limit(abs(cint(args.stock_qty))) - ) - - if sales_order: - query = query.where(sn.sales_order == sales_order) - - serial_nos = query.run(as_list=True) - serial_nos = [s[0] for s in serial_nos] - - return "\n".join(serial_nos) - - -def get_serial_no_batchwise(args, sales_order=None): if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): sn = frappe.qb.DocType("Serial No") query = ( @@ -1455,7 +1435,7 @@ def get_serial_no(args, serial_nos=None, sales_order=None): if args.get("warehouse") and args.get("stock_qty") and args.get("item_code"): has_serial_no = frappe.get_value("Item", {"item_code": args.item_code}, "has_serial_no") if args.get("batch_no") and has_serial_no == 1: - return get_serial_no_batchwise(args, sales_order) + return get_serial_nos_by_fifo(args, sales_order) elif has_serial_no == 1: args = json.dumps( { From 731dc4cdd9d9e263828136918883561245a002fc Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 28 Feb 2023 15:14:34 +0530 Subject: [PATCH 11/24] chore: `Linters` (cherry picked from commit 58c027d4cc5895041446243ce9690f0948cee070) --- erpnext/stock/get_item_details.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index f017af6e915..489ec6ebecc 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -1144,7 +1144,7 @@ def get_serial_nos_by_fifo(args, sales_order=None): def get_conversion_factor(item_code, uom): variant_of = frappe.db.get_value("Item", item_code, "variant_of", cache=True) filters = {"parent": item_code, "uom": uom} - + if variant_of: filters["parent"] = ("in", (item_code, variant_of)) conversion_factor = frappe.db.get_value("UOM Conversion Detail", filters, "conversion_factor") @@ -1170,6 +1170,7 @@ def get_bin_details(item_code, warehouse, company=None, include_child_warehouses if warehouse: from frappe.query_builder.functions import Coalesce, Sum + from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses warehouses = get_child_warehouses(warehouse) if include_child_warehouses else [warehouse] @@ -1245,7 +1246,7 @@ def get_batch_qty_and_serial_no(batch_no, stock_qty, warehouse, item_code, has_s ) serial_no = get_serial_no(args) batch_qty_and_serial_no.update({"serial_no": serial_no}) - + return batch_qty_and_serial_no @@ -1405,10 +1406,7 @@ def get_valuation_rate(item_code, company, warehouse=None): valuation_rate = ( frappe.qb.from_(pi_item) .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) - ) + .where((pi_item.docstatus == 1) & (pi_item.item_code == item_code)) ).run() if valuation_rate: From 1cdf7e0988a3202bb0d5ac74912720a2f958f18c Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 1 Mar 2023 15:00:24 +0530 Subject: [PATCH 12/24] chore: Make finance book read only (cherry picked from commit 28dd1a25cb3c292883c709ae06d331a56d7c0f40) --- erpnext/accounts/doctype/journal_entry/journal_entry.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json index 498fc7c295f..80e72226d3d 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.json +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json @@ -137,7 +137,8 @@ "fieldname": "finance_book", "fieldtype": "Link", "label": "Finance Book", - "options": "Finance Book" + "options": "Finance Book", + "read_only": 1 }, { "fieldname": "2_add_edit_gl_entries", @@ -538,7 +539,7 @@ "idx": 176, "is_submittable": 1, "links": [], - "modified": "2023-01-17 12:53:53.280620", + "modified": "2023-03-01 14:58:59.286591", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry", From b08cdc00f2022c2622939e6af9db8db51c31912e Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Sat, 4 Mar 2023 01:05:55 +0530 Subject: [PATCH 13/24] fix: `Inventory Dimension` for `Stock Reconciliation` (cherry picked from commit 0e1b7760a8b688d419bf6f99e67d222ca430d7de) --- .../stock/doctype/stock_reconciliation/stock_reconciliation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 398b3c98e38..3dbdfd56e28 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -406,6 +406,8 @@ class StockReconciliation(StockController): } ) + self.update_inventory_dimensions(row, data) + if not row.batch_no: data.qty_after_transaction = flt(row.qty, row.precision("qty")) From ab737424c26fb751693e8003e6d9eade104f08cd Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Sat, 4 Mar 2023 15:19:59 +0530 Subject: [PATCH 14/24] fix: update inventory dimensions before returning sle --- .../doctype/stock_reconciliation/stock_reconciliation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 3dbdfd56e28..a89981f82e9 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -397,6 +397,7 @@ class StockReconciliation(StockController): "voucher_type": self.doctype, "voucher_no": self.name, "voucher_detail_no": row.name, + "actual_qty": flt(row.current_qty), "company": self.company, "stock_uom": frappe.db.get_value("Item", row.item_code, "stock_uom"), "is_cancelled": 1 if self.docstatus == 2 else 0, @@ -406,8 +407,6 @@ class StockReconciliation(StockController): } ) - self.update_inventory_dimensions(row, data) - if not row.batch_no: data.qty_after_transaction = flt(row.qty, row.precision("qty")) @@ -425,6 +424,8 @@ class StockReconciliation(StockController): data.valuation_rate = flt(row.valuation_rate) data.stock_value_difference = -1 * flt(row.amount_difference) + self.update_inventory_dimensions(row, data) + return data def make_sle_on_cancel(self): From d97c1bf0f4dd74bfa64819b901f0ce6f7a798cb9 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Sat, 4 Mar 2023 17:06:07 +0530 Subject: [PATCH 15/24] fix: Stock Reconciliation `actual_qty` (cherry picked from commit 70de444b7b868d9fbf89413684cedc85ca491d4f) --- .../stock/doctype/stock_reconciliation/stock_reconciliation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index a89981f82e9..3f6a2c881b8 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -397,7 +397,7 @@ class StockReconciliation(StockController): "voucher_type": self.doctype, "voucher_no": self.name, "voucher_detail_no": row.name, - "actual_qty": flt(row.current_qty), + "actual_qty": 0, "company": self.company, "stock_uom": frappe.db.get_value("Item", row.item_code, "stock_uom"), "is_cancelled": 1 if self.docstatus == 2 else 0, From 235ecca9fa96ce4ce6ff75e05012d9b1adca2148 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 6 Mar 2023 12:02:35 +0530 Subject: [PATCH 16/24] fix: BOM Update log not completed (cherry picked from commit 2f157fa5d3e08c642847042282512536e9a20ca5) --- erpnext/hooks.py | 2 +- .../manufacturing/doctype/bom_update_log/bom_update_log.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 797f8aa650f..e24038d0c6e 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -368,7 +368,7 @@ auto_cancel_exempted_doctypes = [ scheduler_events = { "cron": { - "0/5 * * * *": [ + "0/15 * * * *": [ "erpnext.manufacturing.doctype.bom_update_log.bom_update_log.resume_bom_cost_update_jobs", ], "0/30 * * * *": [ 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 c3f52d45833..51f7b24e745 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py @@ -212,7 +212,7 @@ def resume_bom_cost_update_jobs(): ["name", "boms_updated", "status"], ) incomplete_level = any(row.get("status") == "Pending" for row in bom_batches) - if not bom_batches or incomplete_level: + if not bom_batches or not incomplete_level: continue # Prep parent BOMs & updated processed BOMs for next level @@ -252,6 +252,9 @@ def get_processed_current_boms( current_boms = [] for row in bom_batches: + if not row.boms_updated: + continue + boms_updated = json.loads(row.boms_updated) current_boms.extend(boms_updated) boms_updated_dict = {bom: True for bom in boms_updated} From 9b84e1e39c93bcc008d0f4e8d7d6616668b2fdb6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:45:51 +0530 Subject: [PATCH 17/24] chore: add german translations (#34167) chore: add german translations (#34167) * chore: add german translations * Apply suggestions from code review Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --------- Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> (cherry picked from commit bbb6a62a7ddbc5337998652721160437f79301eb) Co-authored-by: Patrick Eissler <77415730+PatrickDenis-stack@users.noreply.github.com> Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- erpnext/translations/de.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index c474698d261..1094d4bd984 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -9916,3 +9916,5 @@ Cost and Freight,Kosten und Fracht, Delivered at Place,Geliefert benannter Ort, Delivered at Place Unloaded,Geliefert benannter Ort entladen, Delivered Duty Paid,Geliefert verzollt, +Discount Validity,Frist für den Rabatt, +Discount Validity Based On,Frist für den Rabatt berechnet sich nach, From ca59c699cdfe1eddce7263e1ed586021a2b0590e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 13:34:25 +0530 Subject: [PATCH 18/24] fix: Payment Request against sales order with disabled rounded total (#34281) fix: Payment Request against sales order with disabled rounded total (#34281) * fix: Payment Request against sales order with disabled rounded total * chore: Do not consider advance amount (cherry picked from commit ea8e23384d3029569691e266700e3ebcdff6e17b) Co-authored-by: Deepesh Garg --- erpnext/accounts/doctype/payment_request/payment_request.py | 6 +----- .../doctype/payment_request/test_payment_request.py | 5 ++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index b0ee5885482..d9b07435fdb 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -495,26 +495,22 @@ def get_amount(ref_doc, payment_account=None): """get amount based on doctype""" dt = ref_doc.doctype if dt in ["Sales Order", "Purchase Order"]: - grand_total = flt(ref_doc.rounded_total) - flt(ref_doc.advance_paid) - + grand_total = flt(ref_doc.rounded_total) or flt(ref_doc.grand_total) elif dt in ["Sales Invoice", "Purchase Invoice"]: if ref_doc.party_account_currency == ref_doc.currency: grand_total = flt(ref_doc.outstanding_amount) else: grand_total = flt(ref_doc.outstanding_amount) / ref_doc.conversion_rate - elif dt == "POS Invoice": for pay in ref_doc.payments: if pay.type == "Phone" and pay.account == payment_account: grand_total = pay.amount break - elif dt == "Fees": grand_total = ref_doc.outstanding_amount if grand_total > 0: return grand_total - else: frappe.throw(_("Payment Entry is already created")) diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py index 477c726940c..4279aa4f85c 100644 --- a/erpnext/accounts/doctype/payment_request/test_payment_request.py +++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py @@ -45,7 +45,10 @@ class TestPaymentRequest(unittest.TestCase): frappe.get_doc(method).insert(ignore_permissions=True) def test_payment_request_linkings(self): - so_inr = make_sales_order(currency="INR") + so_inr = make_sales_order(currency="INR", do_not_save=True) + so_inr.disable_rounded_total = 1 + so_inr.save() + pr = make_payment_request( dt="Sales Order", dn=so_inr.name, From 480797e85699ffe76bac841b30b6b7418451fad7 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:44:15 +0530 Subject: [PATCH 19/24] fix: Do not calculate commission post submit (#34267) fix: Do not calculate commission post submit (#34267) * fix: Do not calculate commision post submit * chore: Update condition to match server side logic Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --------- Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> (cherry picked from commit 10632d75b049616525fb2810c94db8a7a53759b0) Co-authored-by: Deepesh Garg --- erpnext/controllers/selling_controller.py | 2 +- erpnext/selling/sales_common.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index fce34b002a4..590e00fb11e 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -139,7 +139,7 @@ class SellingController(StockController): self.in_words = money_in_words(amount, self.currency) def calculate_commission(self): - if not self.meta.get_field("commission_rate"): + if not self.meta.get_field("commission_rate") or self.docstatus.is_submitted(): return self.round_floats_in(self, ("amount_eligible_for_commission", "commission_rate")) diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 5ce6e9c1460..f1df3a11de4 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -253,7 +253,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran } calculate_commission() { - if(!this.frm.fields_dict.commission_rate) return; + if(!this.frm.fields_dict.commission_rate || this.frm.doc.docstatus === 1) return; if(this.frm.doc.commission_rate > 100) { this.frm.set_value("commission_rate", 100); From 64c758d0c0d2dcc168f5eabb5e3d90f19a0e4c47 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:45:43 +0530 Subject: [PATCH 20/24] fix: Default sales team not getting set (#34284) fix: Default sales team not getting set (#34284) (cherry picked from commit 7d0199d743c7861e883cadd582c036cc8d9b0a62) Co-authored-by: Deepesh Garg --- erpnext/controllers/selling_controller.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 590e00fb11e..1a81158b366 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -87,6 +87,9 @@ class SellingController(StockController): ) if not self.meta.get_field("sales_team"): party_details.pop("sales_team") + else: + self.set("sales_team", party_details.get("sales_team")) + self.update_if_missing(party_details) elif lead: From 71a281fb11c99e2ab37af6346ee038924de071b4 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:46:18 +0530 Subject: [PATCH 21/24] fix: Performance improvement when adding a new item (#34195) fix: Performance improvement when adding a new item (cherry picked from commit 49af5ba4349a03131e70c23a4580cb6c9c7d0c7d) Co-authored-by: HarryPaulo Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com> --- erpnext/public/js/controllers/transaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index b6fab544220..741e6acb50b 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -488,7 +488,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe () => { var d = locals[cdt][cdn]; me.add_taxes_from_item_tax_template(d.item_tax_rate); - if (d.free_item_data) { + if (d.free_item_data && d.free_item_data.length > 0) { me.apply_product_discount(d); } }, From 0e9f9c31a0deb7ce02e2eb582ce4c72aaf7964ff Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:47:54 +0530 Subject: [PATCH 22/24] fix(minor): Dirty the form after clicking on Get advances button in Invoices (#34323) fix(minor): Dirty the form after clicking on Get advances button in Invoices (#34323) fix(minor): Dirty form after clicking on Get advances button (cherry picked from commit 2feb27e399632c858a7de144ae8873dc92e6af81) Co-authored-by: Marica --- erpnext/public/js/controllers/transaction.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 741e6acb50b..f7620db2f1e 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1884,11 +1884,13 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe get_advances() { if(!this.frm.is_return) { + var me = this; return this.frm.call({ method: "set_advances", doc: this.frm.doc, callback: function(r, rt) { refresh_field("advances"); + me.frm.dirty(); } }) } From 164933aae81d831c9e82cf7c4496a39db0b1912f Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 16:52:56 +0530 Subject: [PATCH 23/24] refactor: use renamed timezone utils (#34301) refactor: use renamed timezone utils https://github.com/frappe/frappe/pull/20253 (cherry picked from commit 502a37a8641ed82c2936bfed1544b5178e1a3355) Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com> Co-authored-by: Deepesh Garg --- .../service_level_agreement/service_level_agreement.py | 4 ++-- erpnext/utilities/doctype/video/video.py | 3 ++- erpnext/www/book_appointment/index.py | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) 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 e49f212f10f..d60d7f86ce6 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -13,8 +13,8 @@ from frappe.utils import ( get_datetime, get_datetime_str, get_link_to_form, + get_system_timezone, get_time, - get_time_zone, get_weekdays, getdate, nowdate, @@ -978,7 +978,7 @@ def convert_utc_to_user_timezone(utc_timestamp, user): def get_tz(user): - return frappe.db.get_value("User", user, "time_zone") or get_time_zone() + return frappe.db.get_value("User", user, "time_zone") or get_system_timezone() @frappe.whitelist() diff --git a/erpnext/utilities/doctype/video/video.py b/erpnext/utilities/doctype/video/video.py index 13b7877b21d..62033a5e18e 100644 --- a/erpnext/utilities/doctype/video/video.py +++ b/erpnext/utilities/doctype/video/video.py @@ -10,6 +10,7 @@ import pytz from frappe import _ from frappe.model.document import Document from frappe.utils import cint +from frappe.utils.data import get_system_timezone from pyyoutube import Api @@ -64,7 +65,7 @@ def update_youtube_data(): frequency = get_frequency(frequency) time = datetime.now() - timezone = pytz.timezone(frappe.utils.get_time_zone()) + timezone = pytz.timezone(get_system_timezone()) site_time = time.astimezone(timezone) if frequency == 30: diff --git a/erpnext/www/book_appointment/index.py b/erpnext/www/book_appointment/index.py index dfca9465ed1..f50c207ab98 100644 --- a/erpnext/www/book_appointment/index.py +++ b/erpnext/www/book_appointment/index.py @@ -4,6 +4,7 @@ import json import frappe import pytz from frappe import _ +from frappe.utils.data import get_system_timezone WEEKDAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] @@ -125,7 +126,7 @@ def filter_timeslots(date, timeslots): def convert_to_guest_timezone(guest_tz, datetimeobject): guest_tz = pytz.timezone(guest_tz) - local_timezone = pytz.timezone(frappe.utils.get_time_zone()) + local_timezone = pytz.timezone(get_system_timezone()) datetimeobject = local_timezone.localize(datetimeobject) datetimeobject = datetimeobject.astimezone(guest_tz) return datetimeobject @@ -134,7 +135,7 @@ def convert_to_guest_timezone(guest_tz, datetimeobject): def convert_to_system_timezone(guest_tz, datetimeobject): guest_tz = pytz.timezone(guest_tz) datetimeobject = guest_tz.localize(datetimeobject) - system_tz = pytz.timezone(frappe.utils.get_time_zone()) + system_tz = pytz.timezone(get_system_timezone()) datetimeobject = datetimeobject.astimezone(system_tz) return datetimeobject From a2e001a2da81ed074dff7439b74a07a57a0388bc Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 7 Mar 2023 17:56:57 +0530 Subject: [PATCH 24/24] Revert "refactor: use renamed timezone utils (#34301)" Revert "refactor: use renamed timezone utils (#34301)" This reverts commit 164933aae81d831c9e82cf7c4496a39db0b1912f. --- .../service_level_agreement/service_level_agreement.py | 4 ++-- erpnext/utilities/doctype/video/video.py | 3 +-- erpnext/www/book_appointment/index.py | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) 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 d60d7f86ce6..e49f212f10f 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -13,8 +13,8 @@ from frappe.utils import ( get_datetime, get_datetime_str, get_link_to_form, - get_system_timezone, get_time, + get_time_zone, get_weekdays, getdate, nowdate, @@ -978,7 +978,7 @@ def convert_utc_to_user_timezone(utc_timestamp, user): def get_tz(user): - return frappe.db.get_value("User", user, "time_zone") or get_system_timezone() + return frappe.db.get_value("User", user, "time_zone") or get_time_zone() @frappe.whitelist() diff --git a/erpnext/utilities/doctype/video/video.py b/erpnext/utilities/doctype/video/video.py index 62033a5e18e..13b7877b21d 100644 --- a/erpnext/utilities/doctype/video/video.py +++ b/erpnext/utilities/doctype/video/video.py @@ -10,7 +10,6 @@ import pytz from frappe import _ from frappe.model.document import Document from frappe.utils import cint -from frappe.utils.data import get_system_timezone from pyyoutube import Api @@ -65,7 +64,7 @@ def update_youtube_data(): frequency = get_frequency(frequency) time = datetime.now() - timezone = pytz.timezone(get_system_timezone()) + timezone = pytz.timezone(frappe.utils.get_time_zone()) site_time = time.astimezone(timezone) if frequency == 30: diff --git a/erpnext/www/book_appointment/index.py b/erpnext/www/book_appointment/index.py index f50c207ab98..dfca9465ed1 100644 --- a/erpnext/www/book_appointment/index.py +++ b/erpnext/www/book_appointment/index.py @@ -4,7 +4,6 @@ import json import frappe import pytz from frappe import _ -from frappe.utils.data import get_system_timezone WEEKDAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] @@ -126,7 +125,7 @@ def filter_timeslots(date, timeslots): def convert_to_guest_timezone(guest_tz, datetimeobject): guest_tz = pytz.timezone(guest_tz) - local_timezone = pytz.timezone(get_system_timezone()) + local_timezone = pytz.timezone(frappe.utils.get_time_zone()) datetimeobject = local_timezone.localize(datetimeobject) datetimeobject = datetimeobject.astimezone(guest_tz) return datetimeobject @@ -135,7 +134,7 @@ def convert_to_guest_timezone(guest_tz, datetimeobject): def convert_to_system_timezone(guest_tz, datetimeobject): guest_tz = pytz.timezone(guest_tz) datetimeobject = guest_tz.localize(datetimeobject) - system_tz = pytz.timezone(get_system_timezone()) + system_tz = pytz.timezone(frappe.utils.get_time_zone()) datetimeobject = datetimeobject.astimezone(system_tz) return datetimeobject