Merge pull request #32667 from rohitwaghchaure/fixed-bom-cost-update-message
fix: BOM cost update message
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 7f245fd..9487489 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -995,7 +995,9 @@
if self.payment_type in ("Receive", "Pay") and self.party:
for d in self.get("references"):
if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"):
- frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
+ frappe.get_doc(
+ d.reference_doctype, d.reference_name, for_update=True
+ ).set_total_advance_paid()
def on_recurring(self, reference_doc, auto_repeat_doc):
self.reference_no = reference_doc.name
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index afd5a59..0c03c55 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -2017,6 +2017,9 @@
update_address(
target_doc, "shipping_address", "shipping_address_display", source_doc.customer_address
)
+ update_address(
+ target_doc, "billing_address", "billing_address_display", source_doc.customer_address
+ )
if currency:
target_doc.currency = currency
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index ed45106..fb94e8a 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -133,7 +133,7 @@
(%(from_time)s <= jctl.from_time and %(to_time)s >= jctl.to_time) {0}
)
and jctl.name != %(name)s and jc.name != %(parent)s and jc.docstatus < 2 {1}
- order by jctl.to_time desc limit 1""".format(
+ order by jctl.to_time desc""".format(
extra_cond, validate_overlap_for
),
{
diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py
index ac71141..4d2dab7 100644
--- a/erpnext/manufacturing/doctype/job_card/test_job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py
@@ -136,6 +136,45 @@
)
self.assertRaises(OverlapError, jc2.save)
+ def test_job_card_overlap_with_capacity(self):
+ wo2 = make_wo_order_test_record(item="_Test FG Item 2", qty=2)
+
+ workstation = make_workstation(workstation_name=random_string(5)).name
+ frappe.db.set_value("Workstation", workstation, "production_capacity", 1)
+
+ jc1 = frappe.get_last_doc("Job Card", {"work_order": self.work_order.name})
+ jc2 = frappe.get_last_doc("Job Card", {"work_order": wo2.name})
+
+ jc1.workstation = workstation
+ jc1.append(
+ "time_logs",
+ {"from_time": "2021-01-01 00:00:00", "to_time": "2021-01-01 08:00:00", "completed_qty": 1},
+ )
+ jc1.save()
+
+ jc2.workstation = workstation
+
+ # add a new entry in same time slice
+ jc2.append(
+ "time_logs",
+ {"from_time": "2021-01-01 00:01:00", "to_time": "2021-01-01 06:00:00", "completed_qty": 1},
+ )
+ self.assertRaises(OverlapError, jc2.save)
+
+ frappe.db.set_value("Workstation", workstation, "production_capacity", 2)
+ jc2.load_from_db()
+
+ jc2.workstation = workstation
+
+ # add a new entry in same time slice
+ jc2.append(
+ "time_logs",
+ {"from_time": "2021-01-01 00:01:00", "to_time": "2021-01-01 06:00:00", "completed_qty": 1},
+ )
+
+ jc2.save()
+ self.assertTrue(jc2.name)
+
def test_job_card_multiple_materials_transfer(self):
"Test transferring RMs separately against Job Card with multiple RMs."
self.transfer_material_against = "Job Card"
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 4bb4dcc..000ee07 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -27,6 +27,7 @@
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
from erpnext.manufacturing.doctype.work_order.work_order import get_item_details
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.utilities.transaction_base import validate_uom_is_integer
@@ -648,13 +649,23 @@
else:
material_request = material_request_map[key]
+ conversion_factor = 1.0
+ if (
+ material_request_type == "Purchase"
+ and item_doc.purchase_uom
+ and item_doc.purchase_uom != item_doc.stock_uom
+ ):
+ conversion_factor = (
+ get_conversion_factor(item_doc.name, item_doc.purchase_uom).get("conversion_factor") or 1.0
+ )
+
# add item
material_request.append(
"items",
{
"item_code": item.item_code,
"from_warehouse": item.from_warehouse,
- "qty": item.quantity,
+ "qty": item.quantity / conversion_factor,
"schedule_date": schedule_date,
"warehouse": item.warehouse,
"sales_order": item.sales_order,
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index 60e6398..c4ab0f8 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -806,6 +806,35 @@
self.assertEqual(pln.status, "Completed")
self.assertEqual(pln.po_items[0].produced_qty, 5)
+ def test_material_request_item_for_purchase_uom(self):
+ from erpnext.stock.doctype.item.test_item import make_item
+
+ fg_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name
+ bom_item = make_item(
+ properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1", "purchase_uom": "Nos"}
+ ).name
+
+ if not frappe.db.exists("UOM Conversion Detail", {"parent": bom_item, "uom": "Nos"}):
+ doc = frappe.get_doc("Item", bom_item)
+ doc.append("uoms", {"uom": "Nos", "conversion_factor": 10})
+ doc.save()
+
+ make_bom(item=fg_item, raw_materials=[bom_item], source_warehouse="_Test Warehouse - _TC")
+
+ pln = create_production_plan(
+ item_code=fg_item, planned_qty=10, ignore_existing_ordered_qty=1, stock_uom="_Test UOM 1"
+ )
+
+ pln.make_material_request()
+ for row in frappe.get_all(
+ "Material Request Item",
+ filters={"production_plan": pln.name},
+ fields=["item_code", "uom", "qty"],
+ ):
+ self.assertEqual(row.item_code, bom_item)
+ self.assertEqual(row.uom, "Nos")
+ self.assertEqual(row.qty, 1)
+
def create_production_plan(**args):
"""
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 1a309ba..b0082bd 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -28,7 +28,7 @@
},
"open_general_ledger": function(data) {
if (!data.account) return;
- var project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; })
+ let project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; });
frappe.route_options = {
"account": data.account,
@@ -37,7 +37,16 @@
"to_date": data.to_date || data.year_end_date,
"project": (project && project.length > 0) ? project[0].$input.val() : ""
};
- frappe.set_route("query-report", "General Ledger");
+
+ let report = "General Ledger";
+
+ if (["Payable", "Receivable"].includes(data.account_type)) {
+ report = data.account_type == "Payable" ? "Accounts Payable" : "Accounts Receivable";
+ frappe.route_options["party_account"] = data.account;
+ frappe.route_options["report_date"] = data.year_end_date;
+ }
+
+ frappe.set_route("query-report", report);
},
"tree": true,
"name_field": "account",
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 70ae085..6b42e4d 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -84,11 +84,12 @@
}
}
- if(doc.docstatus == 1 && !(['Lost', 'Ordered']).includes(doc.status)) {
- if(!doc.valid_till || frappe.datetime.get_diff(doc.valid_till, frappe.datetime.get_today()) >= 0) {
- cur_frm.add_custom_button(__('Sales Order'),
- cur_frm.cscript['Make Sales Order'], __('Create'));
- }
+ if (doc.docstatus == 1 && !["Lost", "Ordered"].includes(doc.status)) {
+ this.frm.add_custom_button(
+ __("Sales Order"),
+ this.frm.cscript["Make Sales Order"],
+ __("Create")
+ );
if(doc.status!=="Ordered") {
this.frm.add_custom_button(__('Set as Lost'), () => {
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 36d5a6c..9dd28dc 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -842,6 +842,9 @@
update_address(
target_doc, "shipping_address", "shipping_address_display", source_doc.customer_address
)
+ update_address(
+ target_doc, "billing_address", "billing_address_display", source_doc.customer_address
+ )
update_taxes(
target_doc,