mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-20 15:25:13 +00:00
fix: auto batch not set for raw materials in subcontracting receipt
(cherry picked from commit 23f9d4c600)
# Conflicts:
# erpnext/controllers/subcontracting_controller.py
This commit is contained in:
committed by
Mergify
parent
b18afa8bdd
commit
6c8e8384d5
@@ -12,6 +12,12 @@ from frappe.utils import cint, flt, get_link_to_form
|
|||||||
|
|
||||||
from erpnext.controllers.stock_controller import StockController
|
from erpnext.controllers.stock_controller import StockController
|
||||||
from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import (
|
from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import (
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
combine_datetime,
|
||||||
|
get_auto_batch_nos,
|
||||||
|
get_available_serial_nos,
|
||||||
|
>>>>>>> 23f9d4c600 (fix: auto batch not set for raw materials in subcontracting receipt)
|
||||||
get_voucher_wise_serial_batch_from_bundle,
|
get_voucher_wise_serial_batch_from_bundle,
|
||||||
)
|
)
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
@@ -52,9 +58,42 @@ class SubcontractingController(StockController):
|
|||||||
if self.doctype in ["Subcontracting Order", "Subcontracting Receipt"]:
|
if self.doctype in ["Subcontracting Order", "Subcontracting Receipt"]:
|
||||||
self.validate_items()
|
self.validate_items()
|
||||||
self.create_raw_materials_supplied()
|
self.create_raw_materials_supplied()
|
||||||
|
self.set_valuation_rate_for_rm()
|
||||||
else:
|
else:
|
||||||
super().validate()
|
super().validate()
|
||||||
|
|
||||||
|
def set_valuation_rate_for_rm(self):
|
||||||
|
rate_changed = False
|
||||||
|
if self.doctype == "Subcontracting Receipt":
|
||||||
|
for row in self.supplied_items:
|
||||||
|
kwargs = frappe._dict(
|
||||||
|
{
|
||||||
|
"item_code": row.rm_item_code,
|
||||||
|
"warehouse": self.supplier_warehouse,
|
||||||
|
"posting_date": self.posting_date,
|
||||||
|
"posting_time": self.posting_time,
|
||||||
|
"qty": flt(row.consumed_qty) * (-1 if not self.is_return else 1),
|
||||||
|
"voucher_type": self.doctype,
|
||||||
|
"voucher_no": self.name,
|
||||||
|
"company": self.company,
|
||||||
|
"serial_and_batch_bundle": row.serial_and_batch_bundle,
|
||||||
|
"voucher_detail_no": row.name,
|
||||||
|
"batch_no": row.batch_no,
|
||||||
|
"serial_no": row.serial_no,
|
||||||
|
"use_serial_batch_fields": row.use_serial_batch_fields,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
rate = get_incoming_rate(kwargs)
|
||||||
|
precision = frappe.get_precision("Subcontracting Receipt Supplied Item", "rate")
|
||||||
|
if flt(rate, precision) != flt(row.rate, precision):
|
||||||
|
row.rate = rate
|
||||||
|
row.amount = flt(row.consumed_qty) * flt(rate)
|
||||||
|
rate_changed = True
|
||||||
|
|
||||||
|
if rate_changed:
|
||||||
|
self.calculate_items_qty_and_amount()
|
||||||
|
|
||||||
def validate_rejected_warehouse(self):
|
def validate_rejected_warehouse(self):
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if flt(item.rejected_qty) and not item.rejected_warehouse:
|
if flt(item.rejected_qty) and not item.rejected_warehouse:
|
||||||
@@ -610,6 +649,64 @@ class SubcontractingController(StockController):
|
|||||||
self.set_rate_for_supplied_items(rm_obj, item_row)
|
self.set_rate_for_supplied_items(rm_obj, item_row)
|
||||||
elif self.backflush_based_on == "BOM":
|
elif self.backflush_based_on == "BOM":
|
||||||
self.update_rate_for_supplied_items()
|
self.update_rate_for_supplied_items()
|
||||||
|
self.set_batch_for_supplied_items()
|
||||||
|
|
||||||
|
def set_batch_for_supplied_items(self):
|
||||||
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos_for_outward
|
||||||
|
from erpnext.stock.get_item_details import get_filtered_serial_nos
|
||||||
|
|
||||||
|
for row in self.supplied_items:
|
||||||
|
item_details = frappe.get_cached_value(
|
||||||
|
"Item", row.rm_item_code, ["has_batch_no", "has_serial_no"], as_dict=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not item_details.has_batch_no and not item_details.has_serial_no:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not row.use_serial_batch_fields:
|
||||||
|
continue
|
||||||
|
|
||||||
|
kwargs = frappe._dict(
|
||||||
|
{
|
||||||
|
"item_code": row.rm_item_code,
|
||||||
|
"warehouse": self.supplier_warehouse,
|
||||||
|
"posting_date": self.posting_date,
|
||||||
|
"posting_time": self.posting_time,
|
||||||
|
"qty": flt(row.consumed_qty),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if item_details.has_serial_no and not row.serial_and_batch_bundle and not row.serial_no:
|
||||||
|
serial_nos = get_available_serial_nos(kwargs)
|
||||||
|
if serial_nos:
|
||||||
|
serial_nos = [sn.get("serial_no") for sn in serial_nos]
|
||||||
|
serial_nos = get_filtered_serial_nos(serial_nos, self, "supplied_items")
|
||||||
|
row.serial_no = "\n".join(serial_nos)
|
||||||
|
|
||||||
|
elif item_details.has_batch_no and not row.serial_and_batch_bundle and not row.batch_no:
|
||||||
|
batches = get_auto_batch_nos(kwargs)
|
||||||
|
if batches:
|
||||||
|
consumed_qty = row.consumed_qty
|
||||||
|
for index, d in enumerate(batches):
|
||||||
|
if consumed_qty <= 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
if index == 0:
|
||||||
|
row.batch_no = d.get("batch_no")
|
||||||
|
row.consumed_qty = d.get("qty")
|
||||||
|
consumed_qty -= d.get("qty")
|
||||||
|
else:
|
||||||
|
new_row = self.append("supplied_items", {})
|
||||||
|
new_row.update(frappe.copy_doc(row).as_dict())
|
||||||
|
new_row.update(
|
||||||
|
{
|
||||||
|
"consumed_qty": d.get("qty"),
|
||||||
|
"batch_no": d.get("batch_no"),
|
||||||
|
"rate": row.rate,
|
||||||
|
"amount": flt(d.get("qty")) * flt(row.rate),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
consumed_qty -= d.get("qty")
|
||||||
|
|
||||||
def update_rate_for_supplied_items(self):
|
def update_rate_for_supplied_items(self):
|
||||||
if self.doctype != "Subcontracting Receipt":
|
if self.doctype != "Subcontracting Receipt":
|
||||||
|
|||||||
@@ -260,10 +260,13 @@ def filter_batches(batches, doc):
|
|||||||
del batches[row.get("batch_no")]
|
del batches[row.get("batch_no")]
|
||||||
|
|
||||||
|
|
||||||
def get_filtered_serial_nos(serial_nos, doc):
|
def get_filtered_serial_nos(serial_nos, doc, table=None):
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
for row in doc.get("items"):
|
if not table:
|
||||||
|
table = "items"
|
||||||
|
|
||||||
|
for row in doc.get(table):
|
||||||
if row.get("serial_no"):
|
if row.get("serial_no"):
|
||||||
for serial_no in get_serial_nos(row.get("serial_no")):
|
for serial_no in get_serial_nos(row.get("serial_no")):
|
||||||
if serial_no in serial_nos:
|
if serial_no in serial_nos:
|
||||||
|
|||||||
@@ -740,13 +740,13 @@ class TestSubcontractingReceipt(FrappeTestCase):
|
|||||||
for row in scr.supplied_items:
|
for row in scr.supplied_items:
|
||||||
self.assertEqual(row.rate, 300.00)
|
self.assertEqual(row.rate, 300.00)
|
||||||
self.assertTrue(row.serial_and_batch_bundle)
|
self.assertTrue(row.serial_and_batch_bundle)
|
||||||
auto_created_serial_batch = frappe.db.get_value(
|
serial_and_batch_bundle = frappe.db.get_value(
|
||||||
"Stock Ledger Entry",
|
"Stock Ledger Entry",
|
||||||
{"voucher_no": scr.name, "voucher_detail_no": row.name},
|
{"voucher_no": scr.name, "voucher_detail_no": row.name},
|
||||||
"auto_created_serial_and_batch_bundle",
|
"serial_and_batch_bundle",
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertTrue(auto_created_serial_batch)
|
self.assertTrue(serial_and_batch_bundle)
|
||||||
|
|
||||||
self.assertEqual(scr.items[0].rm_cost_per_qty, 900)
|
self.assertEqual(scr.items[0].rm_cost_per_qty, 900)
|
||||||
self.assertEqual(scr.items[0].service_cost_per_qty, 100)
|
self.assertEqual(scr.items[0].service_cost_per_qty, 100)
|
||||||
|
|||||||
Reference in New Issue
Block a user