mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 11:19:09 +00:00
Merge pull request #34326 from frappe/version-13-hotfix
chore: release v13
This commit is contained in:
@@ -131,7 +131,7 @@ def validate_returned_items(doc):
|
|||||||
)
|
)
|
||||||
|
|
||||||
elif ref.serial_no:
|
elif ref.serial_no:
|
||||||
if not d.serial_no:
|
if d.qty and not d.serial_no:
|
||||||
frappe.throw(_("Row # {0}: Serial No is mandatory").format(d.idx))
|
frappe.throw(_("Row # {0}: Serial No is mandatory").format(d.idx))
|
||||||
else:
|
else:
|
||||||
serial_nos = get_serial_nos(d.serial_no)
|
serial_nos = get_serial_nos(d.serial_no)
|
||||||
@@ -393,6 +393,16 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None):
|
|||||||
if serial_nos:
|
if serial_nos:
|
||||||
target_doc.serial_no = "\n".join(serial_nos)
|
target_doc.serial_no = "\n".join(serial_nos)
|
||||||
|
|
||||||
|
if source_doc.get("rejected_serial_no"):
|
||||||
|
returned_serial_nos = get_returned_serial_nos(
|
||||||
|
source_doc, source_parent, serial_no_field="rejected_serial_no"
|
||||||
|
)
|
||||||
|
rejected_serial_nos = list(
|
||||||
|
set(get_serial_nos(source_doc.rejected_serial_no)) - set(returned_serial_nos)
|
||||||
|
)
|
||||||
|
if rejected_serial_nos:
|
||||||
|
target_doc.rejected_serial_no = "\n".join(rejected_serial_nos)
|
||||||
|
|
||||||
if doctype == "Purchase Receipt":
|
if doctype == "Purchase Receipt":
|
||||||
returned_qty_map = get_returned_qty_map_for_row(
|
returned_qty_map = get_returned_qty_map_for_row(
|
||||||
source_parent.name, source_parent.supplier, source_doc.name, doctype
|
source_parent.name, source_parent.supplier, source_doc.name, doctype
|
||||||
@@ -587,7 +597,7 @@ def get_filters(
|
|||||||
return filters
|
return filters
|
||||||
|
|
||||||
|
|
||||||
def get_returned_serial_nos(child_doc, parent_doc):
|
def get_returned_serial_nos(child_doc, parent_doc, serial_no_field="serial_no"):
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
return_ref_field = frappe.scrub(child_doc.doctype)
|
return_ref_field = frappe.scrub(child_doc.doctype)
|
||||||
@@ -596,7 +606,7 @@ def get_returned_serial_nos(child_doc, parent_doc):
|
|||||||
|
|
||||||
serial_nos = []
|
serial_nos = []
|
||||||
|
|
||||||
fields = ["`{0}`.`serial_no`".format("tab" + child_doc.doctype)]
|
fields = [f"`{'tab' + child_doc.doctype}`.`{serial_no_field}`"]
|
||||||
|
|
||||||
filters = [
|
filters = [
|
||||||
[parent_doc.doctype, "return_against", "=", parent_doc.name],
|
[parent_doc.doctype, "return_against", "=", parent_doc.name],
|
||||||
@@ -606,6 +616,6 @@ def get_returned_serial_nos(child_doc, parent_doc):
|
|||||||
]
|
]
|
||||||
|
|
||||||
for row in frappe.get_all(parent_doc.doctype, fields=fields, filters=filters):
|
for row in frappe.get_all(parent_doc.doctype, fields=fields, filters=filters):
|
||||||
serial_nos.extend(get_serial_nos(row.serial_no))
|
serial_nos.extend(get_serial_nos(row.get(serial_no_field)))
|
||||||
|
|
||||||
return serial_nos
|
return serial_nos
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ class SellingController(StockController):
|
|||||||
)
|
)
|
||||||
if not self.meta.get_field("sales_team"):
|
if not self.meta.get_field("sales_team"):
|
||||||
party_details.pop("sales_team")
|
party_details.pop("sales_team")
|
||||||
|
else:
|
||||||
|
self.set("sales_team", party_details.get("sales_team"))
|
||||||
|
|
||||||
self.update_if_missing(party_details)
|
self.update_if_missing(party_details)
|
||||||
|
|
||||||
elif lead:
|
elif lead:
|
||||||
|
|||||||
@@ -1975,11 +1975,13 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
|
|
||||||
get_advances: function() {
|
get_advances: function() {
|
||||||
if(!this.frm.is_return) {
|
if(!this.frm.is_return) {
|
||||||
|
var me = this;
|
||||||
return this.frm.call({
|
return this.frm.call({
|
||||||
method: "set_advances",
|
method: "set_advances",
|
||||||
doc: this.frm.doc,
|
doc: this.frm.doc,
|
||||||
callback: function(r, rt) {
|
callback: function(r, rt) {
|
||||||
refresh_field("advances");
|
refresh_field("advances");
|
||||||
|
me.frm.dirty();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -417,7 +417,14 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
args: args,
|
args: args,
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message) {
|
if(r.message) {
|
||||||
frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message);
|
if (r.message.batch_no != null) {
|
||||||
|
frappe.model.set_value(doc.doctype, doc.name, 'batch_no', r.message.batch_no);
|
||||||
|
} else if (r.message.msg_print) {
|
||||||
|
frappe.show_alert({
|
||||||
|
message: r.message.msg_print,
|
||||||
|
indicator:'orange'
|
||||||
|
}, 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -260,7 +260,9 @@ def set_batch_nos(doc, warehouse_field, throw=False, child_table="items"):
|
|||||||
warehouse = d.get(warehouse_field, None)
|
warehouse = d.get(warehouse_field, None)
|
||||||
if warehouse and qty > 0 and frappe.db.get_value("Item", d.item_code, "has_batch_no"):
|
if warehouse and qty > 0 and frappe.db.get_value("Item", d.item_code, "has_batch_no"):
|
||||||
if not d.batch_no:
|
if not d.batch_no:
|
||||||
d.batch_no = get_batch_no(d.item_code, warehouse, qty, throw, d.serial_no)
|
d.batch_no = get_batch_no(d.item_code, warehouse, qty, throw, d.serial_no).get(
|
||||||
|
"batch_no", None
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
batch_qty = get_batch_qty(batch_no=d.batch_no, warehouse=warehouse)
|
batch_qty = get_batch_qty(batch_no=d.batch_no, warehouse=warehouse)
|
||||||
if flt(batch_qty, d.precision("qty")) < flt(qty, d.precision("qty")):
|
if flt(batch_qty, d.precision("qty")) < flt(qty, d.precision("qty")):
|
||||||
@@ -282,6 +284,7 @@ def get_batch_no(item_code, warehouse, qty=1, throw=False, serial_no=None):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
batch_no = None
|
batch_no = None
|
||||||
|
message = None
|
||||||
batches = get_batches(item_code, warehouse, qty, throw, serial_no)
|
batches = get_batches(item_code, warehouse, qty, throw, serial_no)
|
||||||
|
|
||||||
for batch in batches:
|
for batch in batches:
|
||||||
@@ -290,15 +293,18 @@ def get_batch_no(item_code, warehouse, qty=1, throw=False, serial_no=None):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if not batch_no:
|
if not batch_no:
|
||||||
frappe.msgprint(
|
message = _(
|
||||||
_(
|
"Please select a Batch for Item {0}. Unable to find a single batch that fulfills this requirement"
|
||||||
"Please select a Batch for Item {0}. Unable to find a single batch that fulfills this requirement"
|
).format(frappe.bold(item_code))
|
||||||
).format(frappe.bold(item_code))
|
|
||||||
)
|
|
||||||
if throw:
|
if throw:
|
||||||
|
frappe.msgprint(
|
||||||
|
_(
|
||||||
|
"Please select a Batch for Item {0}. Unable to find a single batch that fulfills this requirement"
|
||||||
|
).format(frappe.bold(item_code))
|
||||||
|
)
|
||||||
raise UnableToSelectBatchError
|
raise UnableToSelectBatchError
|
||||||
|
|
||||||
return batch_no
|
return {"batch_no": batch_no, "msg_print": message}
|
||||||
|
|
||||||
|
|
||||||
def get_batches(item_code, warehouse, qty=1, throw=False, serial_no=None):
|
def get_batches(item_code, warehouse, qty=1, throw=False, serial_no=None):
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ class TestBatch(FrappeTestCase):
|
|||||||
|
|
||||||
# shipped from FEFO batch
|
# shipped from FEFO batch
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
delivery_note.items[0].batch_no, get_batch_no(item_code, receipt.items[0].warehouse, batch_qty)
|
delivery_note.items[0].batch_no,
|
||||||
|
get_batch_no(item_code, receipt.items[0].warehouse, batch_qty).get("batch_no", None),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_delivery_note_fail(self):
|
def test_delivery_note_fail(self):
|
||||||
@@ -145,7 +146,8 @@ class TestBatch(FrappeTestCase):
|
|||||||
|
|
||||||
# assert same batch is selected
|
# assert same batch is selected
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
stock_entry.items[0].batch_no, get_batch_no(item_code, receipt.items[0].warehouse, batch_qty)
|
stock_entry.items[0].batch_no,
|
||||||
|
get_batch_no(item_code, receipt.items[0].warehouse, batch_qty).get("batch_no", None),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_batch_split(self):
|
def test_batch_split(self):
|
||||||
|
|||||||
@@ -1262,7 +1262,9 @@ class StockEntry(StockController):
|
|||||||
and ret.get("has_batch_no")
|
and ret.get("has_batch_no")
|
||||||
and not args.get("batch_no")
|
and not args.get("batch_no")
|
||||||
):
|
):
|
||||||
args.batch_no = get_batch_no(args["item_code"], args["s_warehouse"], args["qty"])
|
args.batch_no = get_batch_no(args["item_code"], args["s_warehouse"], args["qty"]).get(
|
||||||
|
"batch_no", None
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.purpose == "Send to Subcontractor" and self.get("purchase_order") and args.get("item_code")
|
self.purpose == "Send to Subcontractor" and self.get("purchase_order") and args.get("item_code")
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ def update_stock(args, out):
|
|||||||
):
|
):
|
||||||
|
|
||||||
if out.has_batch_no and not args.get("batch_no"):
|
if out.has_batch_no and not args.get("batch_no"):
|
||||||
out.batch_no = get_batch_no(out.item_code, out.warehouse, out.qty)
|
out.batch_no = get_batch_no(out.item_code, out.warehouse, out.qty).get("batch_no", None)
|
||||||
actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse, out.item_code)
|
actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse, out.item_code)
|
||||||
if actual_batch_qty:
|
if actual_batch_qty:
|
||||||
out.update(actual_batch_qty)
|
out.update(actual_batch_qty)
|
||||||
|
|||||||
@@ -9897,3 +9897,5 @@ Total Asset,Aktiva,
|
|||||||
Total Liability,Verbindlichkeiten,
|
Total Liability,Verbindlichkeiten,
|
||||||
Total Equity,Eigenkapital,
|
Total Equity,Eigenkapital,
|
||||||
Warehouse wise Stock Value,Warenwert nach Lager,
|
Warehouse wise Stock Value,Warenwert nach Lager,
|
||||||
|
Discount Validity,Frist für den Rabatt,
|
||||||
|
Discount Validity Based On,Frist für den Rabatt berechnet sich nach,
|
||||||
|
|||||||
|
Can't render this file because it is too large.
|
Reference in New Issue
Block a user