Merge pull request #37249 from akhilnarang/drop-redundant-check
Drop redundant check
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index c8c9ad1..095617d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -65,6 +65,25 @@
erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm);
}
+ if (this.frm.doc.repost_required && this.frm.doc.docstatus===1) {
+ this.frm.set_intro(__("Accounting entries for this invoice need to be reposted. Please click on 'Repost' button to update."));
+ this.frm.add_custom_button(__('Repost Accounting Entries'),
+ () => {
+ this.frm.call({
+ doc: this.frm.doc,
+ method: 'repost_accounting_entries',
+ freeze: true,
+ freeze_message: __('Reposting...'),
+ callback: (r) => {
+ if (!r.exc) {
+ frappe.msgprint(__('Accounting Entries are reposted.'));
+ me.frm.refresh();
+ }
+ }
+ });
+ }).removeClass('btn-default').addClass('btn-warning');
+ }
+
if(!doc.is_return && doc.docstatus == 1 && doc.outstanding_amount != 0){
if(doc.on_hold) {
this.frm.add_custom_button(
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 0599e19..f3c0181 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -166,6 +166,7 @@
"against_expense_account",
"column_break_63",
"unrealized_profit_loss_account",
+ "repost_required",
"subscription_section",
"subscription",
"auto_repeat",
@@ -191,8 +192,7 @@
"inter_company_invoice_reference",
"is_old_subcontracting_flow",
"remarks",
- "connections_tab",
- "column_break_38"
+ "connections_tab"
],
"fields": [
{
@@ -990,6 +990,7 @@
"print_hide": 1
},
{
+ "allow_on_submit": 1,
"fieldname": "cash_bank_account",
"fieldtype": "Link",
"label": "Cash/Bank Account",
@@ -1053,6 +1054,7 @@
"fieldtype": "Column Break"
},
{
+ "allow_on_submit": 1,
"depends_on": "eval:flt(doc.write_off_amount)!=0",
"fieldname": "write_off_account",
"fieldtype": "Link",
@@ -1217,6 +1219,7 @@
"read_only": 1
},
{
+ "allow_on_submit": 1,
"default": "No",
"fieldname": "is_opening",
"fieldtype": "Select",
@@ -1349,6 +1352,7 @@
"options": "Project"
},
{
+ "allow_on_submit": 1,
"depends_on": "eval:doc.is_internal_supplier",
"description": "Unrealized Profit/Loss account for intra-company transfers",
"fieldname": "unrealized_profit_loss_account",
@@ -1505,10 +1509,6 @@
"fieldtype": "Column Break"
},
{
- "fieldname": "column_break_38",
- "fieldtype": "Column Break"
- },
- {
"fieldname": "column_break_50",
"fieldtype": "Column Break"
},
@@ -1578,13 +1578,22 @@
"fieldname": "use_company_roundoff_cost_center",
"fieldtype": "Check",
"label": "Use Company Default Round Off Cost Center"
+ },
+ {
+ "default": "0",
+ "fieldname": "repost_required",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Repost Required",
+ "options": "Account",
+ "read_only": 1
}
],
"icon": "fa fa-file-text",
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2023-07-25 17:22:59.145031",
+ "modified": "2023-09-21 12:22:04.545106",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 5597271..85ed126 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -11,6 +11,9 @@
import erpnext
from erpnext.accounts.deferred_revenue import validate_service_stop_date
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
+from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
+ validate_docs_for_deferred_accounting,
+)
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
check_if_return_invoice_linked_with_payment_entry,
get_total_in_party_account_currency,
@@ -484,6 +487,11 @@
_("Stock cannot be updated against Purchase Receipt {0}").format(item.purchase_receipt)
)
+ def validate_for_repost(self):
+ self.validate_write_off_account()
+ self.validate_expense_account()
+ validate_docs_for_deferred_accounting([], [self.name])
+
def on_submit(self):
super(PurchaseInvoice, self).on_submit()
@@ -522,6 +530,18 @@
self.process_common_party_accounting()
+ def on_update_after_submit(self):
+ if hasattr(self, "repost_required"):
+ fields_to_check = [
+ "cash_bank_account",
+ "write_off_account",
+ "unrealized_profit_loss_account",
+ ]
+ child_tables = {"items": ("expense_account",), "taxes": ("account_head",)}
+ self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
+ self.validate_for_repost()
+ self.db_set("repost_required", self.needs_repost)
+
def make_gl_entries(self, gl_entries=None, from_repost=False):
if not gl_entries:
gl_entries = self.get_gl_entries()
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index b4dd75a..0aaea06 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1744,7 +1744,6 @@
pi = make_purchase_invoice(
company="_Test Company",
- customer="_Test Supplier",
do_not_save=True,
do_not_submit=True,
rate=1000,
@@ -1862,7 +1861,6 @@
pi = make_purchase_invoice(
company="_Test Company",
- customer="_Test Supplier",
do_not_save=True,
do_not_submit=True,
rate=1000,
@@ -1892,6 +1890,32 @@
clear_dimension_defaults("Branch")
disable_dimension()
+ def test_repost_accounting_entries(self):
+ pi = make_purchase_invoice(
+ rate=1000,
+ price_list_rate=1000,
+ qty=1,
+ )
+ expected_gle = [
+ ["_Test Account Cost for Goods Sold - _TC", 1000, 0.0, nowdate()],
+ ["Creditors - _TC", 0.0, 1000, nowdate()],
+ ]
+ check_gl_entries(self, pi.name, expected_gle, nowdate())
+
+ pi.items[0].expense_account = "Service - _TC"
+ pi.save()
+ pi.load_from_db()
+ self.assertTrue(pi.repost_required)
+ pi.repost_accounting_entries()
+
+ expected_gle = [
+ ["Creditors - _TC", 0.0, 1000, nowdate()],
+ ["Service - _TC", 1000, 0.0, nowdate()],
+ ]
+ check_gl_entries(self, pi.name, expected_gle, nowdate())
+ pi.load_from_db()
+ self.assertFalse(pi.repost_required)
+
def set_advance_flag(company, flag, default_account):
frappe.db.set_value(
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 81c7577..3690142 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -473,6 +473,7 @@
"label": "Accounting"
},
{
+ "allow_on_submit": 1,
"fieldname": "expense_account",
"fieldtype": "Link",
"label": "Expense Head",
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index d86abad..347cae0 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -86,6 +86,7 @@
"fieldtype": "Column Break"
},
{
+ "allow_on_submit": 1,
"columns": 2,
"fieldname": "account_head",
"fieldtype": "Link",
@@ -97,6 +98,7 @@
"reqd": 1
},
{
+ "allow_on_submit": 1,
"default": ":Company",
"fieldname": "cost_center",
"fieldtype": "Link",
diff --git a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json
index 8d56c9b..5b7cd2b 100644
--- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json
+++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json
@@ -55,7 +55,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2023-07-27 15:47:58.975034",
+ "modified": "2023-09-26 14:21:27.362567",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Repost Accounting Ledger",
@@ -77,5 +77,6 @@
],
"sort_field": "modified",
"sort_order": "DESC",
- "states": []
+ "states": [],
+ "track_changes": 1
}
\ No newline at end of file
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 4cf2ed2..dbb0971 100644
--- a/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py
+++ b/erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py
@@ -21,29 +21,8 @@
def validate_for_deferred_accounting(self):
sales_docs = [x.voucher_no for x in self.vouchers if x.voucher_type == "Sales Invoice"]
- docs_with_deferred_revenue = frappe.db.get_all(
- "Sales Invoice Item",
- filters={"parent": ["in", sales_docs], "docstatus": 1, "enable_deferred_revenue": True},
- fields=["parent"],
- as_list=1,
- )
-
purchase_docs = [x.voucher_no for x in self.vouchers if x.voucher_type == "Purchase Invoice"]
- docs_with_deferred_expense = frappe.db.get_all(
- "Purchase Invoice Item",
- filters={"parent": ["in", purchase_docs], "docstatus": 1, "enable_deferred_expense": 1},
- fields=["parent"],
- as_list=1,
- )
-
- 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])
- )
- )
- )
+ validate_docs_for_deferred_accounting(sales_docs, purchase_docs)
def validate_for_closed_fiscal_year(self):
if self.vouchers:
@@ -139,14 +118,17 @@
return rendered_page
def on_submit(self):
- job_name = "repost_accounting_ledger_" + self.name
- frappe.enqueue(
- method="erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.start_repost",
- account_repost_doc=self.name,
- is_async=True,
- job_name=job_name,
- )
- frappe.msgprint(_("Repost has started in the background"))
+ if len(self.vouchers) > 1:
+ job_name = "repost_accounting_ledger_" + self.name
+ frappe.enqueue(
+ method="erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger.start_repost",
+ account_repost_doc=self.name,
+ is_async=True,
+ job_name=job_name,
+ )
+ frappe.msgprint(_("Repost has started in the background"))
+ else:
+ start_repost(self.name)
@frappe.whitelist()
@@ -181,3 +163,26 @@
doc.make_gl_entries()
frappe.db.commit()
+
+
+def validate_docs_for_deferred_accounting(sales_docs, purchase_docs):
+ docs_with_deferred_revenue = frappe.db.get_all(
+ "Sales Invoice Item",
+ filters={"parent": ["in", sales_docs], "docstatus": 1, "enable_deferred_revenue": True},
+ fields=["parent"],
+ as_list=1,
+ )
+
+ docs_with_deferred_expense = frappe.db.get_all(
+ "Purchase Invoice Item",
+ filters={"parent": ["in", purchase_docs], "docstatus": 1, "enable_deferred_expense": 1},
+ fields=["parent"],
+ as_list=1,
+ )
+
+ 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]))
+ )
+ )
diff --git a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.json b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.json
index 5175fd1..ed8d395 100644
--- a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.json
+++ b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.json
@@ -99,7 +99,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2022-11-08 07:38:40.079038",
+ "modified": "2023-09-26 14:21:35.719727",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Repost Payment Ledger",
@@ -155,5 +155,6 @@
],
"sort_field": "modified",
"sort_order": "DESC",
- "states": []
+ "states": [],
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 7bdb2b4..f380825 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -11,13 +11,13 @@
import erpnext
from erpnext.accounts.deferred_revenue import validate_service_stop_date
-from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
- get_accounting_dimensions,
-)
from erpnext.accounts.doctype.loyalty_program.loyalty_program import (
get_loyalty_program_details_with_points,
validate_loyalty_points,
)
+from erpnext.accounts.doctype.repost_accounting_ledger.repost_accounting_ledger import (
+ validate_docs_for_deferred_accounting,
+)
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import (
get_party_tax_withholding_details,
)
@@ -168,6 +168,12 @@
self.validate_account_for_change_amount()
self.validate_income_account()
+ def validate_for_repost(self):
+ self.validate_write_off_account()
+ self.validate_account_for_change_amount()
+ self.validate_income_account()
+ validate_docs_for_deferred_accounting([self.name], [])
+
def validate_fixed_asset(self):
for d in self.get("items"):
if d.is_fixed_asset and d.meta.get_field("asset") and d.asset:
@@ -517,90 +523,21 @@
def on_update_after_submit(self):
if hasattr(self, "repost_required"):
- needs_repost = 0
-
- # 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"]
-
- # Check if opening entry check updated
- if doc_before_update.get("is_opening") != self.is_opening:
- needs_repost = 1
-
- if not needs_repost:
- # Parent Level Accounts excluding party account
- for field in (
- "additional_discount_account",
- "cash_bank_account",
- "account_for_change_amount",
- "write_off_account",
- "loyalty_redemption_account",
- "unrealized_profit_loss_account",
- ):
- if doc_before_update.get(field) != self.get(field):
- needs_repost = 1
- break
-
- # Check for parent accounting dimensions
- for dimension in accounting_dimensions:
- if doc_before_update.get(dimension) != self.get(dimension):
- needs_repost = 1
- break
-
- # Check for child tables
- if self.check_if_child_table_updated(
- "items",
- doc_before_update,
- ("income_account", "expense_account", "discount_account"),
- accounting_dimensions,
- ):
- needs_repost = 1
-
- if self.check_if_child_table_updated(
- "taxes", doc_before_update, ("account_head",), accounting_dimensions
- ):
- needs_repost = 1
-
- self.validate_accounts()
-
- # validate if deferred revenue is enabled for any item
- # Don't allow to update the invoice if deferred revenue is enabled
- if needs_repost:
- for item in self.get("items"):
- if item.enable_deferred_revenue:
- frappe.throw(
- _(
- "Deferred Revenue is enabled for item {0}. You cannot update the invoice after submission."
- ).format(item.item_code)
- )
-
- self.db_set("repost_required", needs_repost)
-
- def check_if_child_table_updated(
- self, child_table, doc_before_update, fields_to_check, accounting_dimensions
- ):
- # Check if any field affecting accounting entry is altered
- for index, item in enumerate(self.get(child_table)):
- for field in fields_to_check:
- if doc_before_update.get(child_table)[index].get(field) != item.get(field):
- return True
-
- for dimension in accounting_dimensions:
- if doc_before_update.get(child_table)[index].get(dimension) != item.get(dimension):
- return True
-
- return False
-
- @frappe.whitelist()
- def repost_accounting_entries(self):
- if self.repost_required:
- self.docstatus = 2
- self.make_gl_entries_on_cancel()
- self.docstatus = 1
- self.make_gl_entries()
- self.db_set("repost_required", 0)
- else:
- frappe.throw(_("No updates pending for reposting"))
+ fields_to_check = [
+ "additional_discount_account",
+ "cash_bank_account",
+ "account_for_change_amount",
+ "write_off_account",
+ "loyalty_redemption_account",
+ "unrealized_profit_loss_account",
+ ]
+ child_tables = {
+ "items": ("income_account", "expense_account", "discount_account"),
+ "taxes": ("account_head",),
+ }
+ self.needs_repost = self.check_if_fields_updated(fields_to_check, child_tables)
+ self.validate_for_repost()
+ self.db_set("repost_required", self.needs_repost)
def set_paid_amount(self):
paid_amount = 0.0
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index e635aa7..6efa09b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -243,13 +243,38 @@
_doc.cancel()
_doc.delete()
- def on_trash(self):
- # delete references in 'Repost Payment Ledger'
- rpi = frappe.qb.DocType("Repost Payment Ledger Items")
- frappe.qb.from_(rpi).delete().where(
- (rpi.voucher_type == self.doctype) & (rpi.voucher_no == self.name)
- ).run()
+ def _remove_references_in_repost_doctypes(self):
+ repost_doctypes = ["Repost Payment Ledger Items", "Repost Accounting Ledger Items"]
+ for _doctype in repost_doctypes:
+ dt = frappe.qb.DocType(_doctype)
+ rows = (
+ frappe.qb.from_(dt)
+ .select(dt.name, dt.parent, dt.parenttype)
+ .where((dt.voucher_type == self.doctype) & (dt.voucher_no == self.name))
+ .run(as_dict=True)
+ )
+
+ if rows:
+ references_map = frappe._dict()
+ for x in rows:
+ references_map.setdefault((x.parenttype, x.parent), []).append(x.name)
+
+ for doc, rows in references_map.items():
+ repost_doc = frappe.get_doc(doc[0], doc[1])
+
+ for row in rows:
+ if _doctype == "Repost Payment Ledger Items":
+ repost_doc.remove(repost_doc.get("repost_vouchers", {"name": row})[0])
+ else:
+ repost_doc.remove(repost_doc.get("vouchers", {"name": row})[0])
+
+ repost_doc.flags.ignore_validate_update_after_submit = True
+ repost_doc.flags.ignore_links = True
+ repost_doc.save(ignore_permissions=True)
+
+ def on_trash(self):
+ self._remove_references_in_repost_doctypes()
self._remove_references_in_unreconcile()
# delete sl and gl entries on deletion of transaction
@@ -2186,6 +2211,45 @@
_("Select finance book for the item {0} at row {1}").format(item.item_code, item.idx)
)
+ 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"]
+
+ # Check if opening entry check updated
+ needs_repost = doc_before_update.get("is_opening") != self.is_opening
+
+ if not needs_repost:
+ # Parent Level Accounts excluding party account
+ fields_to_check += accounting_dimensions
+ for field in fields_to_check:
+ if doc_before_update.get(field) != self.get(field):
+ needs_repost = 1
+ break
+
+ if not needs_repost:
+ # Check for child tables
+ for table in child_tables:
+ needs_repost = check_if_child_table_updated(
+ doc_before_update.get(table), self.get(table), child_tables[table]
+ )
+ if needs_repost:
+ break
+
+ return needs_repost
+
+ @frappe.whitelist()
+ def repost_accounting_entries(self):
+ if self.repost_required:
+ repost_ledger = frappe.new_doc("Repost Accounting Ledger")
+ repost_ledger.company = self.company
+ repost_ledger.append("vouchers", {"voucher_type": self.doctype, "voucher_no": self.name})
+ repost_ledger.insert()
+ repost_ledger.submit()
+ self.db_set("repost_required", 0)
+ else:
+ frappe.throw(_("No updates pending for reposting"))
+
@frappe.whitelist()
def get_tax_rate(account_head):
@@ -3191,6 +3255,23 @@
parent.create_stock_reservation_entries()
+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:
+ if child_table_before_update[index].get(field) != item.get(field):
+ return True
+
+ for dimension in accounting_dimensions:
+ if child_table_before_update[index].get(dimension) != item.get(dimension):
+ return True
+
+ return False
+
+
@erpnext.allow_regional
def validate_regional(doc):
pass
diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index d4270a7..5fa66b1 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -804,7 +804,7 @@
{
"item_code": item.rm_item_code,
"warehouse": self.supplier_warehouse,
- "actual_qty": -1 * flt(item.consumed_qty),
+ "actual_qty": -1 * flt(item.consumed_qty, item.precision("consumed_qty")),
"dependant_sle_voucher_detail_no": item.reference_name,
},
)
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index 5292571..2348d2b 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -1050,6 +1050,59 @@
self.assertEqual(after_qty, before_qty)
+ def test_resered_qty_for_production_plan_for_work_order(self):
+ from erpnext.stock.utils import get_or_make_bin
+
+ bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC")
+ before_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan"))
+
+ pln = create_production_plan(item_code="Test Production Item 1")
+
+ bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC")
+ after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan"))
+
+ self.assertEqual(after_qty - before_qty, 1)
+
+ pln.make_work_order()
+
+ work_orders = []
+ for row in frappe.get_all("Work Order", filters={"production_plan": pln.name}, fields=["name"]):
+ wo_doc = frappe.get_doc("Work Order", row.name)
+ wo_doc.source_warehouse = "_Test Warehouse - _TC"
+ wo_doc.wip_warehouse = "_Test Warehouse 1 - _TC"
+ wo_doc.fg_warehouse = "_Test Warehouse - _TC"
+ for d in wo_doc.required_items:
+ d.source_warehouse = "_Test Warehouse - _TC"
+ make_stock_entry(
+ item_code=d.item_code,
+ qty=d.required_qty,
+ rate=100,
+ target="_Test Warehouse - _TC",
+ )
+
+ wo_doc.submit()
+ work_orders.append(wo_doc)
+
+ bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC")
+ after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan"))
+
+ self.assertEqual(after_qty, before_qty)
+
+ rm_work_order = None
+ for wo_doc in work_orders:
+ for d in wo_doc.required_items:
+ if d.item_code == "Raw Material Item 1":
+ rm_work_order = wo_doc
+ break
+
+ if rm_work_order:
+ s = frappe.get_doc(make_se_from_wo(rm_work_order.name, "Material Transfer for Manufacture", 1))
+ s.submit()
+ bin_name = get_or_make_bin("Raw Material Item 1", "_Test Warehouse - _TC")
+ after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan"))
+
+ self.assertEqual(after_qty, before_qty)
+
def test_resered_qty_for_production_plan_for_material_requests_with_multi_UOM(self):
from erpnext.stock.utils import get_or_make_bin
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 5ad79f9..d8fc220 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -1519,16 +1519,17 @@
wo = frappe.qb.DocType("Work Order")
wo_item = frappe.qb.DocType("Work Order Item")
+ if check_production_plan:
+ qty_field = wo_item.required_qty
+ else:
+ qty_field = Case()
+ qty_field = qty_field.when(wo.skip_transfer == 0, wo_item.required_qty - wo_item.transferred_qty)
+ qty_field = qty_field.else_(wo_item.required_qty - wo_item.consumed_qty)
+
query = (
frappe.qb.from_(wo)
.from_(wo_item)
- .select(
- Sum(
- Case()
- .when(wo.skip_transfer == 0, wo_item.required_qty - wo_item.transferred_qty)
- .else_(wo_item.required_qty - wo_item.consumed_qty)
- )
- )
+ .select(Sum(qty_field))
.where(
(wo_item.item_code == item_code)
& (wo_item.parent == wo.name)
diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json
index f2aabc5..dde2f9b 100644
--- a/erpnext/selling/doctype/quotation_item/quotation_item.json
+++ b/erpnext/selling/doctype/quotation_item/quotation_item.json
@@ -235,6 +235,7 @@
},
{
"collapsible": 1,
+ "collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"fieldname": "discount_and_margin",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -666,7 +667,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2023-02-06 11:00:07.042364",
+ "modified": "2023-09-26 13:42:11.410294",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",