mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-25 17:48:30 +00:00
chore: resolve conflicts
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 = [
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"):
|
||||
|
||||
Reference in New Issue
Block a user