chore: resolve conflicts

This commit is contained in:
Smit Vora
2026-04-07 14:51:35 +05:30
parent 0b0dccd294
commit 904ac62830
5 changed files with 8 additions and 255 deletions

View File

@@ -3,13 +3,8 @@
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase, change_settings, timeout
from frappe.utils import add_days, add_months, add_to_date, cint, flt, now, today
=======
from frappe.tests import timeout
from frappe.utils import add_days, add_months, add_to_date, cint, flt, now, nowdate, nowtime, today
>>>>>>> 93ad48bc1b (fix: process loss with bom path disassembly)
from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError
from erpnext.manufacturing.doctype.job_card.job_card import make_stock_entry as make_stock_entry_from_jc

View File

@@ -868,10 +868,6 @@ erpnext.work_order = {
return flt(max, precision("qty"));
},
<<<<<<< HEAD
show_prompt_for_qty_input: function (frm, purpose) {
let max = this.get_max_transferable_qty(frm, purpose);
=======
show_disassembly_prompt: function (frm) {
let max_qty = flt(frm.doc.produced_qty - frm.doc.disassembled_qty);
@@ -926,9 +922,8 @@ erpnext.work_order = {
});
},
show_prompt_for_qty_input: function (frm, purpose, qty, additional_transfer_entry) {
let max = !additional_transfer_entry ? this.get_max_transferable_qty(frm, purpose) : qty;
>>>>>>> 68e97808c5 (fix: disassembly prompt with source stock entry field)
show_prompt_for_qty_input: function (frm, purpose) {
let max = this.get_max_transferable_qty(frm, purpose);
let fields = [
{

View File

@@ -1480,18 +1480,13 @@ def set_work_order_ops(name):
@frappe.whitelist()
<<<<<<< HEAD
def make_stock_entry(work_order_id, purpose, qty=None, target_warehouse=None):
=======
def make_stock_entry(
work_order_id: str,
purpose: str,
qty: float | None = None,
target_warehouse: str | None = None,
is_additional_transfer_entry: bool = False,
source_stock_entry: str | None = None,
):
>>>>>>> 68e97808c5 (fix: disassembly prompt with source stock entry field)
work_order = frappe.get_doc("Work Order", work_order_id)
if not frappe.db.get_value("Warehouse", work_order.wip_warehouse, "is_group"):
wip_warehouse = work_order.wip_warehouse
@@ -1541,16 +1536,7 @@ def make_stock_entry(
@frappe.whitelist()
<<<<<<< HEAD
<<<<<<< HEAD
def get_default_warehouse():
doc = frappe.get_cached_doc("Manufacturing Settings")
=======
def get_disassembly_available_qty(stock_entry_name: str) -> float:
=======
def get_disassembly_available_qty(stock_entry_name: str, current_se_name: str | None = None) -> float:
>>>>>>> 6394dead72 (fix: validate qty that can be disassembled from source stock entry.)
se = frappe.db.get_value("Stock Entry", stock_entry_name, ["fg_completed_qty"], as_dict=True)
if not se:
return 0.0
@@ -1570,11 +1556,9 @@ def get_disassembly_available_qty(stock_entry_name: str, current_se_name: str |
@frappe.whitelist()
def get_default_warehouse(company: str):
wip, fg, scrap = frappe.get_cached_value(
"Company", company, ["default_wip_warehouse", "default_fg_warehouse", "default_scrap_warehouse"]
)
>>>>>>> 68e97808c5 (fix: disassembly prompt with source stock entry field)
def get_default_warehouse():
doc = frappe.get_cached_doc("Manufacturing Settings")
return {
"wip_warehouse": doc.default_wip_warehouse,
"fg_warehouse": doc.default_fg_warehouse,

View File

@@ -11,6 +11,7 @@
"naming_series",
"stock_entry_type",
"outgoing_stock_entry",
"source_stock_entry",
"purpose",
"add_to_transit",
"work_order",
@@ -28,15 +29,7 @@
"column_break_eaoa",
"set_posting_time",
"inspection_required",
<<<<<<< HEAD
"apply_putaway_rule",
=======
"column_break_jabv",
"work_order",
"subcontracting_order",
"outgoing_stock_entry",
"source_stock_entry",
>>>>>>> d4baa9a74a (fix: create source_stock_entry to refer to original manufacturing entry)
"bom_info_section",
"from_bom",
"use_multi_level_bom",

View File

@@ -141,12 +141,8 @@ class StockEntry(StockController):
scan_barcode: DF.Data | None
select_print_heading: DF.Link | None
set_posting_time: DF.Check
<<<<<<< HEAD
source_address_display: DF.SmallText | None
=======
source_address_display: DF.TextEditor | None
source_stock_entry: DF.Link | None
>>>>>>> d4baa9a74a (fix: create source_stock_entry to refer to original manufacturing entry)
source_warehouse_address: DF.Link | None
stock_entry_type: DF.Link
subcontracting_order: DF.Link | None
@@ -375,34 +371,17 @@ class StockEntry(StockController):
self._set_serial_batch_bundle_for_disassembly_row(row, serial_nos, batches)
<<<<<<< HEAD
bundle_doc = SerialBatchCreation(
{
"item_code": row.item_code,
"warehouse": warehouse,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
"voucher_type": self.doctype,
"voucher_no": self.name,
"voucher_detail_no": row.name,
"qty": row.transfer_qty,
"type_of_transaction": "Inward" if row.t_warehouse else "Outward",
"company": self.company,
"do_not_submit": True,
}
).make_serial_and_batch_bundle(serial_nos=serial_nos, batch_nos=batches)
=======
def _set_serial_batch_bundle_for_disassembly_row(self, row, serial_nos, batches):
if not serial_nos and not batches:
return
>>>>>>> 13b019ab8e (fix: set serial and batch from source stock entry - on disassemble)
warehouse = row.s_warehouse or row.t_warehouse
bundle_doc = SerialBatchCreation(
{
"item_code": row.item_code,
"warehouse": warehouse,
"posting_datetime": get_combine_datetime(self.posting_date, self.posting_time),
"posting_date": self.posting_date,
"posting_time": self.posting_time,
"voucher_type": self.doctype,
"voucher_no": self.name,
"voucher_detail_no": row.name,
@@ -2215,45 +2194,7 @@ class StockEntry(StockController):
# Finished goods
self.load_items_from_bom()
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
def get_items_from_manufacture_entry(self):
return frappe.get_all(
"Stock Entry",
fields=[
"`tabStock Entry Detail`.`item_code`",
"`tabStock Entry Detail`.`item_name`",
"`tabStock Entry Detail`.`description`",
"sum(`tabStock Entry Detail`.qty) as qty",
"sum(`tabStock Entry Detail`.transfer_qty) as transfer_qty",
"`tabStock Entry Detail`.`stock_uom`",
"`tabStock Entry Detail`.`uom`",
"`tabStock Entry Detail`.`basic_rate`",
"`tabStock Entry Detail`.`conversion_factor`",
"`tabStock Entry Detail`.`is_finished_item`",
"`tabStock Entry Detail`.`batch_no`",
"`tabStock Entry Detail`.`serial_no`",
"`tabStock Entry Detail`.`s_warehouse`",
"`tabStock Entry Detail`.`t_warehouse`",
"`tabStock Entry Detail`.`use_serial_batch_fields`",
],
filters=[
["Stock Entry", "purpose", "=", "Manufacture"],
["Stock Entry", "work_order", "=", self.work_order],
["Stock Entry", "docstatus", "=", 1],
["Stock Entry Detail", "docstatus", "=", 1],
],
order_by="`tabStock Entry Detail`.`idx` desc, `tabStock Entry Detail`.`is_finished_item` desc",
group_by="`tabStock Entry Detail`.`item_code`",
=======
def get_items_from_manufacture_stock_entry(self, stock_entry):
=======
def get_items_from_manufacture_stock_entry(self, stock_entry=None):
>>>>>>> 3cf1ce8360 (fix: manufacture entry with group_by support)
=======
def get_items_from_manufacture_stock_entry(self):
>>>>>>> 98dfd64f63 (fix: remove unnecessary param, and use value from self)
SE = frappe.qb.DocType("Stock Entry")
SED = frappe.qb.DocType("Stock Entry Detail")
query = frappe.qb.from_(SED).join(SE).on(SED.parent == SE.name).where(SE.docstatus == 1)
@@ -2293,7 +2234,6 @@ class StockEntry(StockController):
.groupby(SED.item_code)
.orderby(SED.idx)
.run(as_dict=True)
>>>>>>> 1ed0124ad7 (fix: add support to fetch items based on manufacture stock entry; fix how it's done from work order)
)
@frappe.whitelist()
@@ -2420,161 +2360,7 @@ class StockEntry(StockController):
if self.pro_doc and self.pro_doc.scrap_warehouse:
item["to_warehouse"] = self.pro_doc.scrap_warehouse
<<<<<<< HEAD
self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
=======
if (
self.purpose not in ["Material Transfer for Manufacture"]
and frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")
!= "BOM"
and not skip_transfer
):
return
reservation_entries = self.get_available_reserved_materials()
if not reservation_entries:
return
new_items_to_add = []
for d in self.items:
if d.serial_and_batch_bundle or d.serial_no or d.batch_no:
continue
key = (d.item_code, d.s_warehouse)
if details := reservation_entries.get(key):
original_qty = d.qty
if batches := details.get("batch_no"):
for batch_no, qty in batches.items():
if original_qty <= 0:
break
if qty <= 0:
continue
if d.batch_no and original_qty > 0:
new_row = frappe.copy_doc(d)
new_row.name = None
new_row.batch_no = batch_no
new_row.qty = qty
new_row.idx = d.idx + 1
if new_row.batch_no and details.get("batchwise_sn"):
new_row.serial_no = "\n".join(
details.get("batchwise_sn")[new_row.batch_no][: cint(new_row.qty)]
)
new_items_to_add.append(new_row)
original_qty -= qty
batches[batch_no] -= qty
if qty >= d.qty and not d.batch_no:
d.batch_no = batch_no
batches[batch_no] -= d.qty
if d.batch_no and details.get("batchwise_sn"):
d.serial_no = "\n".join(
details.get("batchwise_sn")[d.batch_no][: cint(d.qty)]
)
elif not d.batch_no:
d.batch_no = batch_no
d.qty = qty
original_qty -= qty
batches[batch_no] = 0
if d.batch_no and details.get("batchwise_sn"):
d.serial_no = "\n".join(
details.get("batchwise_sn")[d.batch_no][: cint(d.qty)]
)
if details.get("serial_no"):
d.serial_no = "\n".join(details.get("serial_no")[: cint(d.qty)])
d.use_serial_batch_fields = 1
for new_row in new_items_to_add:
self.append("items", new_row)
sorted_items = sorted(self.items, key=lambda x: x.item_code)
if self.purpose == "Manufacture":
# ensure finished item at last
sorted_items = sorted(sorted_items, key=lambda x: x.t_warehouse)
idx = 0
for row in sorted_items:
idx += 1
row.idx = idx
self.set("items", sorted_items)
def get_available_reserved_materials(self):
reserved_entries = self.get_reserved_materials()
if not reserved_entries:
return {}
itemwise_serial_batch_qty = frappe._dict()
for d in reserved_entries:
key = (d.item_code, d.warehouse)
if key not in itemwise_serial_batch_qty:
itemwise_serial_batch_qty[key] = frappe._dict(
{
"serial_no": [],
"batch_no": defaultdict(float),
"batchwise_sn": defaultdict(list),
}
)
details = itemwise_serial_batch_qty[key]
if d.batch_no:
details.batch_no[d.batch_no] += d.qty
if d.serial_no:
details.batchwise_sn[d.batch_no].extend(d.serial_no.split("\n"))
elif d.serial_no:
details.serial_no.append(d.serial_no)
return itemwise_serial_batch_qty
def get_reserved_materials(self):
doctype = frappe.qb.DocType("Stock Reservation Entry")
serial_batch_doc = frappe.qb.DocType("Serial and Batch Entry")
query = (
frappe.qb.from_(doctype)
.inner_join(serial_batch_doc)
.on(doctype.name == serial_batch_doc.parent)
.select(
serial_batch_doc.serial_no,
serial_batch_doc.batch_no,
serial_batch_doc.qty,
doctype.item_code,
doctype.warehouse,
doctype.name,
doctype.transferred_qty,
doctype.consumed_qty,
)
.where(
(doctype.docstatus == 1)
& (doctype.voucher_no == (self.work_order or self.subcontracting_order))
& (serial_batch_doc.delivered_qty < serial_batch_doc.qty)
)
.orderby(serial_batch_doc.idx)
)
return query.run(as_dict=True)
def set_secondary_items(self):
if self.purpose in ["Manufacture", "Repack"]:
secondary_items_dict = self.get_secondary_items(self.fg_completed_qty)
for item in secondary_items_dict.values():
if self.pro_doc and item.type:
if self.pro_doc.scrap_warehouse and item.type == "Scrap":
item["to_warehouse"] = self.pro_doc.scrap_warehouse
if item.process_loss_per:
item["qty"] -= flt(
item["qty"] * (item.process_loss_per / 100),
self.precision("fg_completed_qty"),
)
self.add_to_stock_entry_detail(secondary_items_dict, bom_no=self.bom_no)
>>>>>>> ea392b2009 (fix: validate work order consistency in stock entry)
def set_process_loss_qty(self):
if self.purpose not in ("Manufacture", "Repack"):